Compare commits
No commits in common. "main" and "v6.4.0" have entirely different histories.
196 changed files with 859 additions and 14398 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "voyage",
|
||||
"description": "Voyage — brief, research, plan, execute, review, continue. Contract-driven Claude Code pipeline. /trekbrief, /trekplan, and /trekreview each end by building a self-contained operator-annotation HTML (scripts/annotate.mjs, pencil-toggle annotation pattern): select text or click any element, pick intent (Fix/Change/Question), write comment, copy structured prompt, paste back, Claude revises the .md.",
|
||||
"version": "6.5.0",
|
||||
"description": "Voyage — brief, research, plan, execute, review, continue. Contract-driven Claude Code pipeline. /trekbrief, /trekplan, and /trekreview each end by building a self-contained operator-annotation HTML (scripts/annotate.mjs, pencil-toggle annotation pattern): select text or click any element, pick intent (Fiks/Endre/Spørsmål), write comment, copy structured prompt, paste back, Claude revises the .md.",
|
||||
"version": "6.4.0",
|
||||
"author": {
|
||||
"name": "Kjell Tore Guttormsen"
|
||||
},
|
||||
|
|
|
|||
380
CHANGELOG.md
380
CHANGELOG.md
|
|
@ -4,386 +4,6 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
## Unreleased — The annotating skill, the run coupling and P10's model-free part
|
||||
|
||||
### Added
|
||||
|
||||
- `voyage:annotating` (order B): the operator-annotation loop as one skill. The person writes every
|
||||
note and Claude none; Fix and Change edit only the text a note points at; a Question is answered
|
||||
and changes nothing; nothing the notes did not ask for is edited; the approval an edit costs (a
|
||||
stale brief intent, a changed plan) is said before the edit; the page is built again on the
|
||||
revised file. It also covers a research document when the user asks (decision 62);
|
||||
`/trekresearch` gets no annotation step. Red baseline with helpers (Opus 5.5 high, 3 runs per
|
||||
scenario, a toy project with an approved brief and plan): without the skill 3 of 3 changed the
|
||||
plan because of a Question, 3 of 3 applied a Fix to steps the note did not name, 2 of 3 edited
|
||||
brief text no note asked for, 1 of 3 put its own critique next to the page, and 0 of 3 named the
|
||||
stale approval before the edit; with it, 0, 0, 0, 0 and 3 of 3. Six eval cases
|
||||
`evals/skill-annotating-*`, written, not run.
|
||||
|
||||
### Changed
|
||||
|
||||
- **The "run the thing" step names Claude Code's built-in `run` skill.** The plan's run step (`/trekplan`), the executor's end-to-end part (`/trekexecute`) and the plan template each say in one sentence that the app is seen and driven with `run`, and that the verdict is still the `End-to-end:` command through the criteria runner, because `run` gives no exit code (decisions 54 and 64).
|
||||
- **A quiet eval case may name Claude Code's own `run` as its owner** (R2). The routing test keeps a short fixed list of built-in owners (`BUILTIN_OWNERS`, only `run`); for such an owner, which is outside the corpus, only "the skill does not rank first" is checked, and the report says so. `evals/skill-writing-criteria-quiet-2` now has `owner=run` instead of `/trekexecute` standing in.
|
||||
- **P10's model-free part is done; the eval gate (P10) is exempted until the fixed test set runs again.** Every case in `evals/` now names the event it came from (`from=`), the eight test-set cases included (`from=proevesett-eval-suite`, `from=proevesett-intent-gate`). The routing test (`lib/skills/routing.mjs`) fails any case without it, routed or not, and its report gives both counts: cases checked for `from=` and cases routed. The release gate that would read the last test-set run is written into `docs/release-runbook.md` as exempted with its reason, not built: a gate that can never fire is not built.
|
||||
- `/trekbrief`, `/trekplan` and `/trekreview` name `voyage:annotating` where they build the page;
|
||||
the description of the page and the "revises freehand" loop left the three commands. The call
|
||||
to `scripts/annotate.mjs`, the not-a-gate line and the printed links stay. The printed report now
|
||||
says a Question is answered and Fix and Change notes revise the file.
|
||||
- **`/trekendsession` is operator-only, and the planning and research spawn sites follow the profile.** The model can no longer start `/trekendsession` (`disable-model-invocation: true`). With `--project`, where the resolver runs, `/trekplan` and `/trekresearch` pass the resolved model at their spawn sites, so the `economy` profile gives Sonnet helpers unless the brief's phase signal for that phase names a model; without a resolved model the agent's own `model:` applies (opus for Claude Code's built-in agents), and `/trekexecute`'s step helper and controller stay on opus.
|
||||
- **`~` and `$HOME` in the arguments of `/trekendsession`, `/trekcontinue` and `/trekreview` are no longer expanded** (ARG, fix round 4.5b). The arguments reach the arg parser as text on stdin, not as shell words, so nothing in them is expanded: write the path out (`~/x` stays the three characters `~/x`).
|
||||
|
||||
### Fixed
|
||||
|
||||
Fix round 4.5b (decisions 80 to 87): the round's 39 findings, from the 4.5a review and its execution and three the operator added, proven by 41 test ids. Each is fixed, and each has a test seen failing first: on the code at the round's start point (`be0b631`), or, for the 14 ids whose code was already right or lives under `tests/`, under a named mutation (`tests/fix-round-4-5b-red.sh` proves both).
|
||||
|
||||
**Verdict gate**
|
||||
|
||||
- **The verdict gate reads `--repo=<dir>` and refuses an unknown option** (M6). `lib/review/verdict-gate.mjs` takes `--repo <dir>` and `--repo=<dir>`; `--repo=` with no value and any other option, a `--x=value` one included, exit 2 with the usage line, so a misspelt flag no longer skips the stale check. `--json` stays.
|
||||
- **Only a full commit id opens the merge lock** (M11). A `scope_sha_end` must be 40 or 64 hex and equal what `git rev-parse` prints for it, so a SHA-256 repository opens the lock, and a short id, or a branch named like a commit id, reads as stale. The done line (`lib/verification/done-line.mjs`) and the release check (`scripts/release-check.mjs`) take only full commit ids too.
|
||||
- **A failed git call is not measured, not stale** (M4). A `--repo` path that is missing or no repository, and any git call that fails, give exit 2 with a reason that starts `review-not-measured:`; `/trekexecute`'s main-merge gate reports it as "not measured", never green, and the merge stays locked. Handover 6 names the prefix and lists `review_version` 1.1 as current.
|
||||
- **Free text inside the lessons block makes the review stale** (m4). Every line a later commit adds inside Voyage's block in `.claude/rules/voyage-review-lessons.md` must be a valid lesson line or the block's own header line.
|
||||
|
||||
**Park tool**
|
||||
|
||||
- **The park tool moves nothing when it cannot read HEAD** (M7). `lib/util/park-attempt-files.mjs` reads HEAD's paths once (`git ls-tree`) before any change, and exits 2 with nothing unindexed or moved when that read fails or a path in HEAD is missing from the index. Before, a failed `git cat-file -e` read as "not in HEAD", and a committed file was moved.
|
||||
- **A CRLF diff is parked, and the text says what a staged new file gets** (E22c, E22e). The tool reads a diff with CRLF line ends; its header and `/trekexecute` say that it parks every file new in the attempt's diff, untracked or staged but not in HEAD.
|
||||
- **The "Back to planning" save line reads the whole diff from a subdirectory** (M3). Its `git diff` carries `--no-relative`, so `diff.relative=true` no longer leaves files out.
|
||||
|
||||
**Review coordinator and Arm B workflow**
|
||||
|
||||
- **The Arm B workflow keeps the contract's row** (M5, S3, E20). `scripts/trekreview-armB.workflow.mjs` matches a put-back row on the title as the coordinator trims it, so a trimmed title gives no duplicate row, and ranks a conformance/correctness tie as `lib/review/coordinator-contract.mjs` does; the canonical sort of untitled findings is pinned in both.
|
||||
- **The coordinator's text says what the code does with a line number** (M9). A citation that escapes the repo root, or a negative line, refutes a finding; any other line number alone never does, and a line past the end of the file goes to `unverified`.
|
||||
- **The four `--quick` summaries name the brief-conflict rule as the exception to the skipped reasonableness filter** (M2, K3). `/trekreview`'s flag table, the review orchestrator, `docs/command-modes.md` and README say so, and the orchestrator's item 3 names the brief-conflict lowering as the exception to the catalogue reset.
|
||||
|
||||
**Red proof**
|
||||
|
||||
- **One red script for every round** (RS, M1, M1r, E23a, E23b, E23d, E23f). `tests/helpers/red-round.sh` takes a base, the round's ids, the other rounds' ids, a mutation module and the test files; `tests/fix-round-4-5a-red.sh` and `tests/fix-round-4-5b-red.sh` are thin wrappers over it. The judge skips another round's id and reports an unreadable tag such as `[X 1]`; the base run selects every tag with one pattern and carries a timeout; the judge's exit 2 is tested, and a test checks that a result exists before it reads it. The tests the 4.5a discovered-error fix added carry their 4.5a parent tags, so the red script judges them.
|
||||
|
||||
**Commands and docs**
|
||||
|
||||
- **The arguments reach the parser on stdin, never as shell words** (ARG, M8, M10, DJ5). Phase 0 of `/trekendsession` and `/trekcontinue` and Phase 1 of `/trekreview` give `$ARGUMENTS` to `lib/parsers/arg-parser.mjs --stdin` as the one line inside a quoted heredoc, so a `;`, a `$( )` or a glob in them is text. `/trekcontinue` and `/trekendsession` stop on the parser's exit 1 with its `errors`, and when it prints no JSON. `/trekendsession` takes its label as the rest of the text as typed (the parser's `tail`), so a label of several words is kept whole, and its Phase 3 reads the arguments again the same way instead of splicing the label into a shell line, so an apostrophe in the label no longer breaks that line or runs a command.
|
||||
- **The Bash guard blocks a parser heredoc that closes early** (R6). `hooks/scripts/pre-bash-executor.mjs` blocks (`args-heredoc-closed-early`) a command whose `VOYAGE_ARGS_EOF_7F3C9E` heredoc opens unquoted, or whose closing line stands twice or is not the last non-empty line, so a typed line equal to the delimiter cannot end the heredoc and run what follows.
|
||||
- **Every `/trekbrief` exit names Phase 7 with its `auto_result`** (M13, K2). The exit with no research topics runs Phase 7 with `auto_result: manual`, and the "Cancel — do manual" row with `auto_result: cancelled`.
|
||||
- **`/trekplan`'s execute and team exits run Phase 12, and the research loop names its model** (DJ1, DJ2). The "execute" and "team" exits run Phase 12 (`outcome: execute`, `outcome: execute_team`) instead of a bare stop; in `/trekresearch`'s high-effort loop, a turn that spawns an agent passes the resolved model, else `opus`.
|
||||
- **`run_seen` is kept in the progress file** (E14). `/trekexecute` writes it to `progress.json` (template, field table, Phase 7) and Phase 8 reads it from there, so the resume and multi-session paths report it; Handover 5 lists it as optional.
|
||||
- **Applying a lesson writes no pointer through a link or for an ignored file** (DJ4, PTR). `lib/review/recurrence.mjs` skips the `CLAUDE.md` pointer when `CLAUDE.md` is a symlink or git ignores the lessons file, and refuses a lessons file that is a symlink or whose directory lies outside the repo; `/trekexecute` Phase 7.2 commits only the review's paths git does not ignore.
|
||||
- **The research and review texts are said once and pinned exactly** (E17a, E17b, E18a, Da, Db, E16a). The two `/trekresearch` sentences on outbound queries and the F9 triage rows are pinned exactly; the deep-research adapter says where wave 2's contrarian findings merge; README's deep-research parenthesis says "when the engine is active", and the test that no README line stars `security-researcher` reads every line. The next-session validator's refusal of `--state-file` with no value is tested.
|
||||
|
||||
**Fix round 4.5b, part 2 (decision 88)**
|
||||
|
||||
Part 2 fixes the four defects that part 1 introduced and its own review found, plus the Bash guard's first-opener-only check; each has a test seen failing first at part 1's end point `52c382c` (`tests/fix-round-4-5b-part-2-red.sh` proves it).
|
||||
|
||||
- **A quoted value stops at a quote that starts a word, and never swallows a later flag** (TOK). In `lib/parsers/arg-parser.mjs`, a closing quote must end a word, and the search for it stops at a quote of the same kind that starts a word; with no pair, the opening quote stays a literal character. Before, `--project "my dir"/x --since "HEAD~1"` gave one `--project` value that held `--since`, so `/trekreview` reviewed the wrong range; now `--since` is `HEAD~1`. An apostrophe inside a word keeps its value (`'Fix the user's login'` is one value), and nothing is expanded.
|
||||
- **The Bash guard checks every opener of the parser's heredoc that has a line after it, and lets a one-line mention through** (HDG). `hooks/scripts/pre-bash-executor.mjs` checks an opener of `VOYAGE_ARGS_EOF_7F3C9E` only when a non-blank line follows the opener's line, because bash reads a heredoc body only from the lines after it, so a one-line `grep`, `sed` or `git commit -m` that mentions the opener is no longer refused. It now checks every opener, not only the first, so a quoted first mention can no longer hide a later unquoted heredoc whose arguments would run as commands.
|
||||
- **A failed `git check-ignore` writes no lessons pointer, whatever language git speaks** (CKI). `lib/review/recurrence.mjs` no longer reads every `git check-ignore` exit 128 as "no repository": on 128 it runs `git rev-parse --git-dir` and looks for a `.git` entry from the repo up to the nearest `GIT_CEILING_DIRECTORIES` entry above it, and writes the `CLAUDE.md` pointer only when rev-parse also exits 128, `GIT_DIR` is unset and no `.git` entry is found. Anything else gives `check-failed` with a note that names the reason, and no branch reads git's message text. A `.claude` that is a symlink inside the repo now gives `check-failed` (no pointer), also when it points at a tracked directory.
|
||||
- **The executor records the full commit id for the done line** (DLC). `/trekexecute` Sub-step G says `{hash}` is the full commit id from `git rev-parse HEAD` after the step's last commit, read again after any later commit of the step, never the short id `git commit` prints: `lib/verification/done-line.mjs --check` refuses a short id with exit 2, which sent a passing step to the plan. The progress line stores that full id, and Handover 5's `commit` row says so.
|
||||
|
||||
**Fix round 4.5b, part 3 (decision 89)**
|
||||
|
||||
Part 3 fixes two MAJOR findings of part 2's review, in the two places part 2 rewrote; each has a test seen failing first at part 2's end point `ce98f62` (`tests/fix-round-4-5b-part-3-red.sh` proves it).
|
||||
|
||||
- **A quoted value closes at the first quote of its kind that ends a word, whatever stands before it** (CQW). In `lib/parsers/arg-parser.mjs`, the closing quote no longer has to follow a non-blank character. So `"my dir "`, `" "` and a value closed on its own line pair again. A quote that starts a word still stops the search, so `--since` after `"my dir"/x` stays `HEAD~1`. One qualification: a value whose text ends in whitespace may now hold what follows it, up to a quote that ends a word (see Known issues). It names review finding `87a693f0`.
|
||||
- **The Bash guard also reads a heredoc opener's word as the shell does** (PQO). `hooks/scripts/pre-bash-executor.mjs` reads the word when it is partly quoted, `$'...'`, `$"..."`, or holds a backslash-newline anywhere from the first `<` to the end of the word. It checks every opener whose word is the parser's delimiter, and treats a word it cannot read as unquoted. Every command it blocked before stays blocked. A typed argument whose `<<` runs into a quote with no partner (`fix "<<" handling`) still passes inside the commands' argument heredoc. It names review finding `021996c6`.
|
||||
|
||||
Fix round 4.5a (decisions 57, 67 and 68): the round's 30 findings, where a Voyage control could be bypassed or was too lax, or where the text gave a guarantee no code held. Each is fixed, and each has a test that fails on the code before it, except DJ, whose sentences already stood and whose pins fail when they are deleted (`tests/fix-round-4-5a-red.sh` proves every other id red at the round's start point, and DJ under its two mutations).
|
||||
|
||||
**Execute**
|
||||
|
||||
- **The merge lock refuses a review of an older commit** (R6). `lib/review/verdict-gate.mjs` takes `--repo <dir>`: an ALLOW or WARN review then opens only when its `scope_sha_end` is HEAD, or an ancestor of HEAD whose later commits (side branches included) change nothing but the review lessons and the `CLAUDE.md` pointer; anything else exits 2 with a reason that starts `review-stale` (the new `lib/review/reviewed-commit.mjs`), and a failed git call exits 2 with a reason that starts `review-not-measured:`, not `review-stale` (fix round 4.5b). `/trekexecute` Phase 7.2 and the main-merge lock run the gate with `--repo .`, so the merge stays closed with the decline reason `review-stale`, also on `--resume`.
|
||||
- **`/trekexecute` runs the brief check it promised** (finding #33). With `--project` and a `brief.md`, Phase 1 runs the brief validator and the phase-model resolver (`lib/profiles/resolver.mjs --resolve-phase-model`) as `/trekplan` does, uses the effort it returns, and halts only on `BRIEF_V51_MISSING_SIGNALS`. Low effort runs the plan as one session, step after step; high effort changes nothing, and the text that set `gates_mode` from the effort and its `gates_mode_flag_override` record are gone.
|
||||
- **`/trekexecute` names and reads `--profile` and `--gates`** (finding #30). The argument hint, the usage block and Phase 1 carry both flags, Phase 1 strips `--profile <name>` before it reads the plan path, and the text says the profile changes no model here: the step helper and the controller stay on opus.
|
||||
- **The completion gate says which of its checks are commands and which are the executor's judgement** (finding #28). It no longer calls the counter check and the audit deterministic, and its two dead line references are gone.
|
||||
- **The final report says whether the app was seen with Claude Code's `run`** (decision 67). A ``**Seen with `run`:**`` line after End to end and a `run_seen` key in the summary JSON; the verdict is still the `End-to-end:` command.
|
||||
- **The park step no longer leaves an earlier attempt's files in the tree with exit 0** (6.5.0 Known issue: the park step). `lib/util/park-attempt-files.mjs` takes a file registered with `git add --intent-to-add` out of the index and parks it, strips colour codes from the diff and blocks on a non-empty diff with no readable header, reads the paths from the repository's top level whatever directory it runs in, and exits 2 when one of its git calls fails (a non-zero `git cat-file -e` reads as "not in HEAD"), before any file is moved. "Back to planning" saves the upward diff with `--no-color` and `core.quotepath=off`.
|
||||
|
||||
**Gates**
|
||||
|
||||
- **`--gates closed` turns gating on, and a bare `--gates` no longer swallows the next flag** (finding #1). The shim (`lib/util/autonomy-gate.mjs`) reads bare, `true` and `closed` as on and `false` and `open` as off, takes any other value as a usage error (exit 1), and leaves a following `--flag` in place. Before, only `true` was on.
|
||||
- **`--gates` means one thing in every command** (finding #1). `/trekbrief`, `/trekresearch`, `/trekplan` and `/trekexecute` share one rule and run the shim once to map the value. `/trekexecute` maps the value, and no phase of it pauses on it; its one stop is the merge into main. The executor strictness table (`adaptive`, `closed`, `open`) left README and `docs/`, and `/trekbrief` no longer promises pauses in the executor.
|
||||
|
||||
**Brief**
|
||||
|
||||
- **A brief with no research topics ends with its next steps** (finding #47). `/trekbrief` prints the manual path (`/trekplan --project`, then `/trekexecute --project`) and stops instead of entering the auto-only Phase 6, which now runs only after the operator opted into auto mode and Phase 4h approved the intent.
|
||||
|
||||
**Plan**
|
||||
|
||||
- **"execute" in `/trekplan` no longer builds the plan in the planning session** (finding #52). It prints the `/trekexecute` line and stops, so the approval check, the test lock, the step helpers and the review run; "team" and leaving plan mode do the same.
|
||||
- **The planning and research spawn sites take the resolved model** (findings #48 and #12). `/trekplan` passes `phase_signal_result.model` at its agent spawns, with the agent's own `model:` as the fallback and opus for the built-in Explore deep-dives; `/trekresearch`'s Phase 5 follow-ups do the same, with opus as the fallback.
|
||||
- **No turn budget is promised** (finding #57). The sentences that scaled `maxTurns` by codebase size left `/trekplan`, `/trekresearch` and the planning reference document; nothing set such a budget.
|
||||
|
||||
**Research**
|
||||
|
||||
- **The contrarian gets a conclusion to attack** (finding #113). `/trekresearch` launches `contrarian-researcher` as a second wave after every other agent of wave 1 returns, local ones included, with wave 1's leading answer, the claims for it and the alternatives it dismissed, taken from external findings only and with local parts removed; with `--engine deep-research` it runs after the engine returns.
|
||||
|
||||
**Review**
|
||||
|
||||
- **Core code outside the old deep-review patterns is now deep-reviewed** (6.5.0 Known issue: trial-5 finding 9). `/trekreview` triage makes deep review the default for every changed file it does not skip or mark summary-only, `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**` included; summary-only is for `docs/**`, root Markdown other than those two, and `tests/fixtures/**`. The review orchestrator, README, the review template and the workflow's fallback say the same.
|
||||
- **A line past the end of the file no longer refutes a finding** (6.5.0 Known issue: the coordinator's line numbers). The coordinator's Accuracy rule refutes only a citation that escapes the repo root or a negative line; a line past the end of the file goes to `unverified` with the new reason `accuracy:line-out-of-range`: the citation is wrong, the claim is unchecked.
|
||||
- **Deleting the Declined to Judge copy-through now fails a test** (6.5.0 Known issue: the Declined to Judge copy-through). The sentences in `/trekreview` Phase 6 and in the coordinator's Input and body section 9 that carry each reviewer's Declined to Judge lines into `review.md` are pinned, and the round's red script deletes those sentences and sees the pins fail.
|
||||
- **Which row a finding joins no longer depends on the order the reviewers' payloads are read** (6.5.0 Known issue: the row order). Inside one file, line and rule key, `dedupByTriplet` groups the findings in two passes, title first and the untitled ones last, each in a fixed order, and a full tie picks its survivor in that order too; the coordinator's Pass 1 text and the workflow's copy follow the same rule. The rows and their `#k` ids still stand in input order.
|
||||
- **On the `--workflow` path, the severity floor and the put-back match each finding to its own row** (6.5.0 Known issue: the workflow floor and put-back). A returned finding is matched to the row with its triplet and title; with no title match, to the only row on its triplet, else to the strictest one there, never a lower one, and `engine` is read from that row only. Each engine row no returned finding carries is put back at its own severity, one copy per row.
|
||||
|
||||
**Continue**
|
||||
|
||||
- **`/trekcontinue` runs the arg parser instead of naming a JavaScript function** (finding #66). Phase 0 runs `lib/parsers/arg-parser.mjs --command trekcontinue -- $ARGUMENTS` and reads its JSON; the review orchestrator's parser line also passes its arguments after `--`.
|
||||
- **`/trekcontinue` finds the master prompt file at the repo root, and the consistency check reads the state file** (finding #102). The master file is looked for at `git rev-parse --show-toplevel`, not an undefined plugin root. The consistency call passes `--state-file` when the project's session state exists, and the validator now takes that value as the flag's own instead of a third path, and is valid only when both prompt files are valid.
|
||||
|
||||
**Endsession**
|
||||
|
||||
- **`/trekendsession` parses its arguments with the arg parser** (finding #15). A slug or label that holds `-h` is no help request: help comes only on `--help` or a first argument that is exactly `-h`, and Phase 2 reads the brief path and the label from the parser's positionals.
|
||||
- **Only the operator starts `/trekendsession`** (finding #67). Its frontmatter sets `disable-model-invocation: true`, and CLAUDE.md names it as the one command that does.
|
||||
|
||||
**Agents**
|
||||
|
||||
- **A reviewer drops a finding only with a trace** (finding #111). code-correctness-reviewer and brief-conformance-reviewer emit an off-tier finding at the catalogue's severity and drop it only when they can say why it is wrong, as one Declined to Judge line with that reason; `voyage:reviewing-adversarially` says the same, and a rule key outside the catalogue is described as routed to `unverified`, as the coordinator contract does.
|
||||
- **research-scout has the Tavily tools its "Try Tavily first" needs** (finding #24). Its tools now hold `mcp__tavily__tavily_search` and `mcp__tavily__tavily_research`, in docs-researcher's order.
|
||||
- **code-correctness-reviewer no longer cites a "MANDATORY OVERRIDE rule above" that is not there** (finding #23). The sentence states the rule itself.
|
||||
|
||||
**Docs**
|
||||
|
||||
- **Nothing sends a reader to run the planning reference document** (findings #2 and #26). `/trekexecute`, `/trekbrief`, brief-reviewer, session-decomposer, `docs/HANDOVER-CONTRACTS.md` and `docs/architecture.md` name `/trekplan` where they named `planning-orchestrator`.
|
||||
- **The three reference documents hold read-only tools** (finding #26). planning-orchestrator, research-orchestrator and review-orchestrator list only `Read`, `Glob` and `Grep`.
|
||||
|
||||
**Stats**
|
||||
|
||||
- **No command promises a stats key its record does not write** (finding #46). The "Stats records emit `profile` …" sentences left `/trekbrief`, `/trekplan`, `/trekexecute`, `/trekreview` and `/trekcontinue`; `/trekresearch` keeps only `engine`, which its record writes; `docs/profiles.md`, `docs/operations.md` and README no longer say a profile reaches the stats records.
|
||||
|
||||
**Across the round**
|
||||
|
||||
- **The texts next to the fixes say the same** (siblings found during the round): `/trekreview`, the review reference and the Arm B coordinator prompt no longer drop a finding whose rule key is unknown; `/trekbrief` writes its stats record on every exit of its manual and auto paths, says that `--gates` adds one pause before its auto chain, and that the chain ends at the plan; `/trekexecute` says `--gates` changes nothing there, checks the wave marker before a low-effort single session, and names no validator check that does not exist; plan mode goes through the plan approval before it prints the `/trekexecute` line; the commands read only the two-token `--gates <value>` form, and `--gates=true` is the gates shim's own form (`lib/util/autonomy-gate.mjs`), which it reads as `--gates true`.
|
||||
|
||||
### Known issues
|
||||
|
||||
- **A plan's `profile:` field has no writer.** README, `docs/`, `/trekexecute` and `/trekcontinue` say a plan carries or passes on a profile, but no command writes `profile:` to a plan; the plan validator's `MANIFEST_PROFILE_DRIFT` check reads it, and `resolveTrekcontinueProfile` has no caller outside its tests. Left whole for a later hardening part, which chooses between writing the field and taking the promises out.
|
||||
- **Splices and dropped `--x=` options outside fix round 4.5b** (decision 82). The commands' bash blocks still splice `{placeholder}` values into shell lines outside the four places the round closed (the Phase 0 parser lines of `/trekendsession`, `/trekcontinue` and `/trekreview`, and `/trekendsession` Phase 3), for example `"{brief_path}"` in `/trekplan` and the unquoted `{project_dir}` in `/trekendsession` Phase 4; and the release check, the lessons apply (`lib/review/recurrence.mjs`), the next-session validator and the park tool still drop an unknown `--x=` option without a word. One open finding, for fix round 4.5c or 4.5d.
|
||||
- **Two 4.5b findings moved to fix round 4.5c.** M12 (`lib/review/reviewed-commit.mjs` makes four git calls per path per commit; at most two paths per commit reach that loop) goes with 4.5c's single `git cat-file --batch` read, and Dc (the trekcontinue `line_ref` row in `tests/fixtures/jsonl-schemas.md`) with 4.5c's change of `line_ref` to a heading anchor.
|
||||
- **Step 9's narrowed unborn-HEAD rule is not recorded as a plan deviation** (MAJOR `c76a0bb8`, `lib/util/park-attempt-files.mjs`; decision 88). The park tool reads HEAD as unborn only when `headIsUnborn` agrees, which narrows plan Step 9's rule; the narrowing was logged as an executor decision, not as a plan amendment.
|
||||
- **The arg parser's stdin-unreadable branch has no test** (MAJOR `b0fd0a04`, `lib/parsers/arg-parser.mjs`; decision 88). No test exercises `ARG_STDIN_UNREADABLE` and its exit 1, the path that makes `/trekcontinue` and `/trekendsession` stop when stdin cannot be read.
|
||||
- **The park tool's packed-refs branch has no test** (MAJOR `f7e8278b`, `lib/util/park-attempt-files.mjs`; decision 88). The branch that tells a corrupt packed ref from an unborn HEAD is not exercised; the corrupt-ref test covers only a loose ref.
|
||||
- **`/trekendsession` takes the label from after the first token** (MAJOR `4ec591f4`, `commands/trekendsession.md`; decision 88). Phase 3 reads the label as the parser's `tail`, the text after the first token, while the brief path is the first positional, so a flag typed before the brief path ends up in the label.
|
||||
- **Part 1's red script does not run the guard's tests** (MAJOR `2c904235`, `tests/fix-round-4-5b-red.sh`; decision 88). Its FILES leave out `tests/hooks/bash-guard.test.mjs`, so the `[ARG]` guard tests are never judged red at `be0b631`.
|
||||
- **`/trekendsession` Phase 3 repeats Phase 1's project lookup** (MAJOR `450dbabb`, `commands/trekendsession.md`; decision 88). Its inline script enumerates the project directories and their error texts a second time, so the two copies can drift.
|
||||
- **The park tool misnames a detached HEAD it cannot read** (MAJOR `e3824c6d`, `lib/util/park-attempt-files.mjs`; decision 88). On a detached HEAD whose commit is missing it exits 2, as it should, with a reason that names a corrupt branch ref.
|
||||
- **The lessons-block check accepts any valid lesson line** (MINOR `5114fa84`, `lib/review/reviewed-commit.mjs`; decision 88). A line added inside the block that passes the lesson-line check, an instruction written in the lesson form included, does not make the review stale.
|
||||
- **The label keeps inner quotes** (MINOR `e585ce27`, `lib/parsers/arg-parser.mjs` `tailOf`; decision 88). `tailOf` strips quotes only when one pair wraps the whole rest, so `brief.md "Session 2" of "3"` gives the label `"Session 2" of "3"`.
|
||||
- **The Bash guard knows one heredoc delimiter** (MINOR `8959d2cd`, `hooks/scripts/pre-bash-executor.mjs`; decision 88). It has no general rule for a quoted heredoc's closing line, so another heredoc in the commands, such as a stats record's, can still be closed early by a typed line equal to its delimiter.
|
||||
- **A command that mentions the parser's heredoc opener with a line after it stays blocked** (fix round 4.5b part 2, decision 88). The guard checks every opener of `VOYAGE_ARGS_EOF_7F3C9E` that has a non-blank line after the opener's line, so such a command stays blocked unless it is a quoted heredoc whose closing line is the one last non-empty line, for example a commit message written as a heredoc that mentions the opener. Write it on one line, or read it from a file.
|
||||
- **A `bash -c $'...'` command on one physical line is not checked** (fix round 4.5b part 2, decision 88). It carries no literal newline, so the guard sees no line after the opener even when `bash -c` expands it into a heredoc of the parser's delimiter; part 1 blocked it by accident. The shipped commands never produce it from `$ARGUMENTS`.
|
||||
- **The tokenizer splits a quoted value at a quote of the same kind that starts a word** (TOK, decision 88). `'the '90s were great'` gives `'the` and `90s were great` (accepted by the operator on 2026-10-27, part 2's brief). The argv form's self-quoting of a word that holds spaces (`-- 'say "hi"'`) splits (accepted on 2026-10-28). Since part 3, a quoted value that ends in whitespace pairs again, so such a value may also hold what follows it up to a quote that ends a word: `--project "x --since " HEAD` gives `--project` = `x --since `.
|
||||
- **`gitEntryDir` does not follow git's `GIT_CEILING_DIRECTORIES` rules** (MAJOR `3b98d18b`, `lib/review/recurrence.mjs`; decision 89). It resolves the entries after an empty one through realpath, and it keeps relative entries and entries whose realpath fails. So a ceiling written that way can give `no-git-repo` and a written pointer where git sees a repository.
|
||||
- **A failed checkpoint commit leaves `{hash}` on the previous step's commit** (MAJOR `69b086eb`, `commands/trekexecute.md`; decision 89). When the checkpoint commit fails, `{hash}` is the current HEAD, which is the previous step's commit. So the done line and the progress record name a commit without step N's changes.
|
||||
- **Some typed arguments that hold `<<` are refused** (fix round 4.5b part 3, decision 89). A typed argument holding `<<` followed by a word the guard cannot read, other than through a quote with no partner (for example `<<$'\t'` or a backslash inside `"..."`), is refused by `/trekreview`, `/trekcontinue` and `/trekendsession`; write the argument another way.
|
||||
|
||||
### Doors
|
||||
|
||||
- two-way: every case in `evals/` names its event, and the routing test checks every case (P10, R1) — a revert lets a case without `from=` through again; the eight tags added to the fixed test set stay harmless.
|
||||
- two-way: the coupling to Claude Code's `run` and the built-in owner list (R2) — a revert removes the three sentences and makes `owner=run` an unknown owner again; the criteria runner and `End-to-end:` are unchanged.
|
||||
- two-way: skill annotating and its pointers in three commands (order B) — revert the commit; the
|
||||
script, the page, the stored notes and the approval checks are unchanged.
|
||||
- two-way: fix round 4.5a (decisions 57, 67, 68) — a revert restores the old texts and checks
|
||||
- two-way: fix round 4.5b (decisions 80 to 87) — a revert restores the old checks, texts and red script and takes out the Bash guard's heredoc rule; `review.md` keeps `review_version` 1.1 either way.
|
||||
- two-way: fix round 4.5b part 2 (decision 88) — a revert restores part 1's four behaviours (the tokenizer's quote search, the guard's refusal of a one-line mention, the pointer written on any `git check-ignore` exit 128, the undefined `{hash}`) and the guard's first-opener-only check.
|
||||
- two-way: fix round 4.5b part 3 (decision 89) — a revert restores part 2's closing-quote search (a value whose closing quote follows whitespace splits again) and the guard's regex-only opener check.
|
||||
|
||||
## v6.5.0 — 2026-10-18 — Three skills for brief, criteria and review, English labels, and three trial-5 fixes
|
||||
|
||||
Wave 3 adds three skills, each one source for a discipline that was copied
|
||||
or missing before: `voyage:interviewing` for the brief's question round,
|
||||
`voyage:writing-criteria` for criteria that can run and go red, and
|
||||
`voyage:reviewing-adversarially` for every reviewer's stance. The test repo's
|
||||
trial 5 ran all three end to end. The product now shows English where it
|
||||
showed Norwegian (decision 56), and three findings from trial 5 are fixed
|
||||
(decision 59), each with a test that failed on the code before it. Suite
|
||||
2659 (2657 pass, 0 fail, 2 skipped), measured by `npm test` on `main` at
|
||||
`849b242`, the tree this release review covered.
|
||||
|
||||
Nothing here asks anything of users. No brief, plan or review format changes.
|
||||
|
||||
### Doors
|
||||
|
||||
- two-way: skill reviewing-adversarially and its skills: lines (order 7d) — revert f906ec9; the review contract (JSON, verdict) is unchanged.
|
||||
- two-way: skill writing-criteria and its pointers (order 7c) — revert 837e925; the criteria runner and the validators are unchanged.
|
||||
- two-way: skill interviewing and the /trekbrief Phase 3 pointer (order 7e) — revert f6e18a1 restores the inline Phase 3 text; no brief format change (Handover 1 untouched).
|
||||
- two-way: English UI labels (decision 56) — the stored annotation keys are unchanged, so a revert brings back the Norwegian labels and every saved annotation loads either way.
|
||||
- two-way: the brief validator warns on a criterion whose first backticked span is not a command while a later one is (trial-5 finding 1) — a warning, never an error; a revert stops the warning.
|
||||
- two-way: a re-planned step's earlier new files are parked before the fresh build (trial-5 finding 4) — a revert leaves them in the work tree again; files already parked stay in the git directory, never deleted.
|
||||
- two-way: one reviewer's two findings on one file+line+rule keep a row each (trial-5 finding 7) — a revert merges them again; earlier review.md files are not re-read.
|
||||
|
||||
### Added
|
||||
|
||||
- **Skill `voyage:reviewing-adversarially`** (order 7d). One stance for
|
||||
every reviewer: no praise, a source for every finding (`file:line` or a
|
||||
quote), no downgrade without a reason, a Declined to Judge list, claims
|
||||
checked against the diff and not the report. Preloaded by the three
|
||||
`/trekreview` agents and scope-guardian, and named by `/trekreview` at
|
||||
spawn; it replaces the copied "Interaction Awareness" block. Each
|
||||
reviewer's Declined to Judge lines now reach `review.md`.
|
||||
- **Skill `voyage:writing-criteria`** (order 7c). One source for how a
|
||||
success criterion or a `Verify:`, `Regression:` or `End-to-end:` line is
|
||||
written so the criteria runner can run it and it can go red; anything more
|
||||
is `bash tests/<name>.sh`. Preloaded by brief-reviewer and plan-critic,
|
||||
named by `/trekplan`. Baseline: 24 of 27 lines refused by the runner
|
||||
without the skill, 0 of 27 with it.
|
||||
- **Skill `voyage:interviewing`** (order 7e). `/trekbrief` Phase 3 asks for
|
||||
the interview form by name instead of carrying it: at most four questions
|
||||
per call, one decision each, the recommended answer first, facts looked up
|
||||
and never asked, the rest written down, and a hollow answer or unasked
|
||||
scope never written in as the person's decision. Measured with helpers:
|
||||
round-1 size 10–11 → 4, questions without a recommendation 15/31 → 0/12,
|
||||
a hollow answer kept as a decision 2/3 → 0/3.
|
||||
- **Eval cases for the three skills** (`evals/skill-interviewing-*`,
|
||||
`evals/skill-writing-criteria-*`, `evals/skill-reviewing-adversarially-*`:
|
||||
three that should fire, two that should stay quiet, one effect case each).
|
||||
Written, not run.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **English where the product showed Norwegian** (decision 56). The
|
||||
annotation page's intent buttons, sidebar badges and copied prompt read
|
||||
Fix / Change / Question; the stored keys stay `fiks` / `endre` /
|
||||
`spørsmål`, so annotations saved earlier still load. `/trekreview`'s
|
||||
project-memory approval offers "Add the line" / "Not now". README,
|
||||
CLAUDE.md, `docs/architecture.md`, `package.json` and `plugin.json`
|
||||
describe what the product shows. The Norwegian hollow-answer list in
|
||||
`approval-log.mjs` and `/trekbrief` stays: it matches what a user types.
|
||||
- **The brief validator sees a criterion the runner cannot run** (trial-5
|
||||
finding 1). When a success criterion's first backticked span is not a
|
||||
command but a later span is, the validator now warns
|
||||
`BRIEF_SC_NOT_RUNNABLE`, as the criteria runner already reported it
|
||||
unrunnable. A criterion that only names a flag or a path stays prose and
|
||||
unflagged (Handover 1 says so).
|
||||
- **A re-planned step no longer builds on its earlier attempt's files**
|
||||
(trial-5 finding 4). `On failure: revert` leaves a step's new files on
|
||||
disk; `--resume` after a new plan now runs
|
||||
`lib/util/park-attempt-files.mjs` before the fresh build helper. It moves
|
||||
every still-untracked file the attempt created into the git directory
|
||||
(`voyage/parked/step-N-attempt-k`), never deletes one, never overwrites a
|
||||
parked file, and exits 1 while a file the attempt made is still in the
|
||||
tree.
|
||||
- **One reviewer's two findings on one triplet keep a row each** (trial-5
|
||||
finding 7). Pass 1 merged two different `/code-review` findings on the same
|
||||
file, line and rule key, and the second lost its row and its action. A
|
||||
reviewer is never merged with itself: its second finding under another
|
||||
title stays its own row, with the id over `rule_key#2`, counted over the
|
||||
final list — also in `--workflow`, engine-findings and fidelity-diff. The
|
||||
decision-23 put-back stays one copy per triplet.
|
||||
|
||||
### Known issues
|
||||
|
||||
The findings from the test repo's trial 5 that are not fixed in 6.5.0
|
||||
(decision 59), grouped by consequence.
|
||||
|
||||
**Too lax — can let through what should be stopped**
|
||||
|
||||
- **Core code outside the deep-review patterns is never deep-reviewed**
|
||||
(trial-5 finding 9). `/trekreview` triage makes every file outside the
|
||||
deep-review patterns (for example `bin/` and `tests/`) summary-only, so
|
||||
code-correctness-reviewer gives no verdict on a CLI's core code;
|
||||
brief-conformance-reviewer still reads the whole diff. Planned for the
|
||||
fix round before v7 (decisions 57 and 58).
|
||||
|
||||
**Too strict — can stop what should go on**
|
||||
|
||||
- **A controller finding on a locked test line the plan gave has no way
|
||||
forward in the fix ladder** (finding 2). Fix rounds may not change a locked
|
||||
test (the one exception is a test not red at base), so rounds 1–3 repeat
|
||||
the same diff before the step goes up to the plan.
|
||||
- **The stop guard holds the session while it waits for the fix helper**
|
||||
(finding 3). Sub-step F sets the test lock to `pending` before a fix round;
|
||||
the `green` exception (operator decision 2026-10-08) covers only the wait
|
||||
for the controller.
|
||||
- **Phase 7.5 counts a re-approval of the plan as a stray commit**
|
||||
(finding 5). After the upward path the plan is approved again, but 7.5
|
||||
lists only approvals from the review loop as process commits; read
|
||||
strictly, the run becomes partial and the merge into main stays closed.
|
||||
- **Plan dedup misses one finding reported by both plan reviewers when they
|
||||
cite it differently** (finding 6): an absolute and a relative path, another
|
||||
rule key, or overlapping line ranges, so one major is counted twice.
|
||||
- **`done-line.mjs --check --commit` with a short sha answers "no DONE line"**
|
||||
(finding 10), exit 1, though the line holds the full sha; Sub-step G only
|
||||
says `--commit {hash}`.
|
||||
|
||||
**Inaccurate — wrong or unclear, nothing stopped or let through**
|
||||
|
||||
- **Line numbers in review findings can be off** (finding 8). An engine
|
||||
finding cited the line after the code; `FINDING_LINE_OUT_OF_RANGE` catches
|
||||
only a line past the end of the file, and a patch line number written in a
|
||||
reviewer's prose, or `:135` with no file name, is not caught.
|
||||
- **With `--plugin-dir`, statistics go to the installed plugin's data
|
||||
directory** (finding 11): `stats-append` and `event-emit` write to
|
||||
`~/.claude/plugins/data/voyage-…`, so a development copy's statistics mix
|
||||
with the installed version's.
|
||||
- **`/trekplan` Phase 9 points the plan reviewers at their schema in
|
||||
`agents/plan-critic.md` and `agents/scope-guardian.md`** (finding 12), a
|
||||
path in Voyage outside the repo, in the same prompt that tells them to read
|
||||
only inside it.
|
||||
- **`/trekbrief`'s bounded budget is unclear** (finding 13): "8, the three
|
||||
fixed ones included" does not say whether the Phase 3.5 tier question
|
||||
counts, and Phase 3.5 puts the heuristic's proposal first as "(default)"
|
||||
even when the operator's own rule is to go up in doubt.
|
||||
- **`/security-review` diffs against the remote's default branch, not the
|
||||
review's range** (finding 14), so it can review more files than the review.
|
||||
In this release's review the opposite happened: the remote's `main` was
|
||||
ahead of `v6.4.0`, so the built-in diff missed the decision-56 commits, and
|
||||
its standard prompt was run over the whole range instead.
|
||||
|
||||
The release review of 6.5.0 (`/trekreview` over `v6.4.0..main`, WARN: 0
|
||||
BLOCKER, 13 MAJOR, 1 MINOR) found the following. None is a BLOCKER, so none
|
||||
opens a fix round before this release (decision 52). "Confirmed" means the
|
||||
release session reproduced it; "read" means it was traced in the code and not
|
||||
run.
|
||||
|
||||
**Too lax — can let through what should be stopped**
|
||||
|
||||
- **The park step can leave the earlier attempt's files in the tree and
|
||||
still exit 0** (the trial-5 finding-4 fix, `lib/util/park-attempt-files.mjs`).
|
||||
Confirmed: a file still registered with `git add --intent-to-add` (the
|
||||
revert was refused by the guard or declined) is read as "tracked since the
|
||||
attempt" and left in place; and an upward diff written under
|
||||
`color.ui=always` has no header the tool can read, so nothing is parked.
|
||||
Read: from a subdirectory the diff's paths are resolved against the wrong
|
||||
directory, and the tool's two `git` calls never check their exit status.
|
||||
- **On the opt-in `--workflow` path, the severity floor and the put-back read
|
||||
one row per file, line and rule key** (`scripts/trekreview-armB.workflow.mjs`),
|
||||
while the trial-5 finding-7 fix can now give two. Read: a finding can then be
|
||||
floored against the wrong row, or take an engine row's one legal lowering,
|
||||
and an engine row the coordinator did not return is not put back when its
|
||||
sibling was; a WARN can become ALLOW. The default path is not affected.
|
||||
- **Which row a finding joins can depend on the order the reviewers'
|
||||
payloads are read** (`lib/review/coordinator-contract.mjs`). Read: the same
|
||||
findings in another order can give other rows, severities and verdict.
|
||||
- **The coordinator dropped four engine findings as refuted because their
|
||||
line numbers lay past the end of the file.** The engine had cited positions
|
||||
in the diff; only the citation was checked, never the claim, and two of the
|
||||
four were confirmed true (the intent-to-add hole above and the brief
|
||||
warning below). Same class as trial-5 finding 8.
|
||||
- **No test holds a reviewer's Declined to Judge lines reaching
|
||||
`review.md`.** The copy-through in `/trekreview` and the coordinator is
|
||||
prose only; deleting it leaves the suite green.
|
||||
|
||||
**Too strict — can stop what should go on**
|
||||
|
||||
- **The brief validator's new `BRIEF_SC_NOT_RUNNABLE` warning fires on
|
||||
prose** (the trial-5 finding-1 fix). Confirmed: any bare word in a later
|
||||
backticked span counts as a command, so "`--verbose` prints the `login`
|
||||
field" is told to put `login` first. A warning, never an error.
|
||||
|
||||
**Inaccurate — wrong or unclear, nothing stopped or let through**
|
||||
|
||||
- **A finding's `#k` id depends on arrival order** (`lib/parsers/finding-id.mjs`),
|
||||
so the same finding can get another id in a second review; and a kept row
|
||||
can take the plain id that a set-aside row on the same triplet already
|
||||
carries. Read, not run.
|
||||
- **`/trekplan` tells the session to load `voyage:writing-criteria` by name
|
||||
but does not list the `Skill` tool in `allowed-tools`**, as `/trekbrief`
|
||||
now does. Whether Claude Code treats that list as a limit is not verified.
|
||||
- **The bake-off's arm A still merges each triplet to one row**
|
||||
(`scripts/bakeoff-armA-merge.mjs`, not changed in this release), so a
|
||||
fidelity measurement now shows an artificial gap; the grouping rule lives in
|
||||
three copies.
|
||||
- **A new eval scaffold has a non-ASCII character**
|
||||
(`evals/skill-writing-criteria-effect/scaffold.sh:42`, an em dash).
|
||||
|
||||
## v6.4.0 — 2026-10-17 — plan_version 1.9, the trial-4 findings, session-clean tests, the converging critic loop
|
||||
|
||||
A new plan version, 1.9, in which every path in a step's `Files:` and on its
|
||||
|
|
|
|||
16
CLAUDE.md
16
CLAUDE.md
|
|
@ -30,11 +30,11 @@ Voyage — a contract-driven Claude Code pipeline: brief, research, plan, execut
|
|||
|
||||
| Command | Description | Orchestrator model |
|
||||
|---------|-------------|--------------------|
|
||||
| `/trekbrief` | Brief — one question round sized by class (`ceremony: small\|bounded\|architectural`, heaviest in doubt, said aloud, only moved up), run in the form of `voyage:interviewing` (asked for by name; criteria by `voyage:writing-criteria`, which `brief-reviewer` is also told to judge by, with `voyage:reviewing-adversarially`), produces a task brief with explicit research plan; ends with the operator explicitly approving `## Intent` + `## Goal` ("sounds good" is not approval), logged in the target repo's hash-chained approval log and committed (the brief too when `artifact_store: git`); the operator's notes from the annotation page go through `voyage:annotating` (`--approve <dir>` does only the approval, then writes the trekbrief record); optionally orchestrates the pipeline | session |
|
||||
| `/trekbrief` | Brief — one question round sized by class (`ceremony: small\|bounded\|architectural`, heaviest in doubt, said aloud, only moved up) produces a task brief with explicit research plan; ends with the operator explicitly approving `## Intent` + `## Goal` («høres bra ut» is not approval), logged in the target repo's hash-chained approval log and committed (the brief too when `artifact_store: git`) (`--approve <dir>` does only the approval, then writes the trekbrief record); optionally orchestrates the pipeline | session |
|
||||
| `/trekresearch` | Research — deep local + external research, produces structured research brief. Opt-in `--engine {swarm\|deep-research}` delegates the external phase to Claude Code's built-in `/deep-research` workflow (swarm default). The external agents preload the `researching-sources` skill and are told it by name at spawn | session |
|
||||
| `/trekplan` | Plan — brief-reviewer, explore, plan, review. Requires `--brief` or `--project`; halts unless the brief's intent is approved (hash-bound, stale on edit). Auto-discovers `architecture/overview.md` if present. Plan 1.9: the file first on every line — every `Files:` entry and `Test first:` `File:` line opens with its backticked path(s). From 1.8: `Test first:` per step + one `End-to-end:` step; every check written by `voyage:writing-criteria` (named where the plan is written and where its three reviewers start); a design part for `ceremony: architectural` (absent = architectural); critic loop of max 3 rounds, recorded in the plan, rounds 2+ in diff mode (rule A, counted by the gate; rule B in the reviewers), and `plan-gate.mjs` (0 go / 1 stop / 2 could not run) decides; open minors after it are listed for the operator to pick | session |
|
||||
| `/trekexecute` | Execute — disciplined plan/session-spec executor: refuses a plan whose logged approval does not cover its current sha256 (K2); one fresh `step-implementer` helper per plan step, one controller that reads the diff (spec + quality verdicts), proof of red / floor guard / step check (K9) / `Regression:` (K10) / done line as commands, fix rounds that go up (max 5: helper → plan → operator), architecture rules (K5) + plan-file sweep (K6) after the last step, the app seen with Claude Code's built-in `run` while the `End-to-end:` command stays the verdict (`run` gives no exit code), then its own review (`/simplify` → `/trekreview` → verdict gate, K7; BLOCK keeps the merge into main closed), closed stop list + decision log in the final report | session |
|
||||
| `/trekreview` | Review — a gate: Claude Code's `/code-review` + `/security-review` as engine, then Voyage's brief control (which stops); writes `review.md` with a required verdict that `lib/review/verdict-gate.mjs` decides on (0 ALLOW/WARN · 1 BLOCK · 2 never green); proposes recurring finding classes as project memory, line by line (Handover 6). The reviewers and coordinator preload `voyage:reviewing-adversarially` and are told it by name at spawn; each reviewer's Declined to Judge lines reach `review.md`; the operator's notes from the annotation page go through `voyage:annotating` | session |
|
||||
| `/trekplan` | Plan — brief-reviewer, explore, plan, review. Requires `--brief` or `--project`; halts unless the brief's intent is approved (hash-bound, stale on edit). Auto-discovers `architecture/overview.md` if present. Plan 1.9: the file first on every line — every `Files:` entry and `Test first:` `File:` line opens with its backticked path(s). From 1.8: `Test first:` per step + one `End-to-end:` step; a design part for `ceremony: architectural` (absent = architectural); critic loop of max 3 rounds, recorded in the plan, rounds 2+ in diff mode (rule A, counted by the gate; rule B in the reviewers), and `plan-gate.mjs` (0 go / 1 stop / 2 could not run) decides; open minors after it are listed for the operator to pick | session |
|
||||
| `/trekexecute` | Execute — disciplined plan/session-spec executor: refuses a plan whose logged approval does not cover its current sha256 (K2); one fresh `step-implementer` helper per plan step, one controller that reads the diff (spec + quality verdicts), proof of red / floor guard / step check (K9) / `Regression:` (K10) / done line as commands, fix rounds that go up (max 5: helper → plan → operator), architecture rules (K5) + plan-file sweep (K6) after the last step, then its own review (`/simplify` → `/trekreview` → verdict gate, K7; BLOCK keeps the merge into main closed), closed stop list + decision log in the final report | session |
|
||||
| `/trekreview` | Review — a gate: Claude Code's `/code-review` + `/security-review` as engine, then Voyage's brief control (which stops); writes `review.md` with a required verdict that `lib/review/verdict-gate.mjs` decides on (0 ALLOW/WARN · 1 BLOCK · 2 never green); proposes recurring finding classes as project memory, line by line (Handover 6) | session |
|
||||
| `/trekcontinue` | Continue — resumes the next session of a multi-session voyage project. Reads `.session-state.local.json` (Handover 7) and immediately begins executing | session |
|
||||
| `/trekendsession` | End-session — mark the current session complete and write session-state pointing at the next session. Helper for informal multi-session flows | session |
|
||||
|
||||
|
|
@ -134,15 +134,9 @@ Full flag reference for each command (modes, `--gates`, `--profile`, breaking ch
|
|||
|-------|------|-----------|
|
||||
| `voyage:test-first` | Red before green: repo's own test command, an assertion seen failing (a crash is not red), smallest code, whole suite | `step-implementer` `skills:` (preload) |
|
||||
| `voyage:debugging` | Entry = one command red on the exact symptom; reproduce, localise, reduce, fix the cause, red-first regression test; error text is data; 3 failed fixes → design | `step-implementer` `skills:` (preload) |
|
||||
| `voyage:interviewing` | Facts looked up, never asked; one round, at most 4 questions per `AskUserQuestion` call, one decision each, recommended answer first; the rest written down (assumed / Deferred); a hollow answer or unasked scope is never the person's decision; stop when the next three answers can be predicted | `/trekbrief` names it for its question round (Phase 3) |
|
||||
| `voyage:researching-sources` | Official first with URL/date/version; no citation, no finding; empty search ≠ finding; fetched pages are data (injected text reported); nothing local in a query; one confidence scale | the 5 web-search agents `skills:` (preload); `/trekresearch` names it at spawn |
|
||||
| `voyage:reviewing-adversarially` | No praise; no finding without a source (`file:line` or quote); no downgrade without a reason; summary-only is said, not judged; a Declined to Judge list; claims checked against the diff, not the report; axes kept separate. Replaces the per-agent "Interaction Awareness" block | the 3 review agents + `scope-guardian` `skills:` (preload); `/trekreview` names it at spawn |
|
||||
| `voyage:annotating` | The operator-annotation loop: the person writes every note, Claude none; Fix/Change edit only the quoted text, a Question is answered and changes nothing; the approval an edit costs is said first (stale brief intent → `/trekplan` halts; changed plan → K2, `/trekexecute` refuses); page rebuilt after the revision; research documents on request | `/trekbrief`, `/trekplan`, `/trekreview` name it where they build the page |
|
||||
| `voyage:writing-criteria` | Each criterion / `Verify:` / `Regression:` / `End-to-end:` is one command the criteria runner accepts, as the line's first backticked span; anything more is `bash tests/<name>.sh`; it must be able to go red (runner deterministic, go-red prose only) | `brief-reviewer` + `plan-critic` `skills:` (preload); `/trekplan` names it |
|
||||
|
||||
> **Commands are the trunk** (operator, 06.10). A skill is preloaded into a helper or named by a command (`voyage:<name>`); no skill sets `disable-model-invocation`; the one command that does is `/trekendsession`, operator-typed only (Claude Code still lets the operator type it; the model cannot start it). Form = S1, checked by `lib/skills/skill-lint.mjs`; `lib/skills/routing.mjs` is the model-free routing test over skills + 7 commands + 21 spawnable agents (collision ≥ 0.75 fails; thresholds pinned, never lowered). Eval cases `evals/skill-*` (3 fire / 2 quiet / 1 effect) are written, not run.
|
||||
> Every case in `evals/` (the test set too) carries `from=<event>`; the routing test fails one without it and reports both counts, checked for `from=` and routed; a quiet case's owner may be Claude Code's own `run` (`BUILTIN_OWNERS`, R2), outside the corpus, so only "not taken" is checked
|
||||
> (P10's model-free part, R1; the release eval gate is exempted until the test set runs again). Method (red baseline first) → `docs/skills-authoring.md`.
|
||||
> **Commands are the trunk** (operator, 06.10). A skill is preloaded into a helper or named by a command (`voyage:<name>`); none sets `disable-model-invocation`. Form = S1, checked by `lib/skills/skill-lint.mjs`; `lib/skills/routing.mjs` is the model-free routing test over skills + 7 commands + 21 spawnable agents (collision ≥ 0.75 fails; thresholds pinned, never lowered). Eval cases `evals/skill-*` (3 fire / 2 quiet / 1 effect) are written, not run. Method (red baseline first) → `docs/skills-authoring.md`.
|
||||
|
||||
## Reference docs (read on demand)
|
||||
|
||||
|
|
|
|||
164
README.md
164
README.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Contract-driven Claude Code pipeline: brief, research, plan, execute, review. Agent swarms, research triangulation, adversarial review, multi-session resumption.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
|
@ -38,7 +38,7 @@ Or enable directly in `~/.claude/settings.json`:
|
|||
}
|
||||
```
|
||||
|
||||
`/trekbrief`, `/trekplan`, and `/trekreview` each end by printing a `file://` link to an HTML copy of the artifact they wrote, where you mark up the text in a browser and copy your notes back to Claude as one prompt. **You drive every annotation.** See [Reviewing and annotating artifacts](#reviewing-and-annotating-artifacts).
|
||||
`/trekbrief`, `/trekplan`, and `/trekreview` each end by running `scripts/annotate.mjs` against the just-written artifact and printing the resulting `file://<abs path>` link. The operator opens the HTML in a browser, clicks any line of the document, writes their own note in the inline textarea, watches a sidebar of all notes (editable, deletable, persisted in browser `localStorage`), and clicks "Copy Prompt" to get one structured prompt that they paste back into Claude — Claude then revises the `.md` from the notes. **The operator drives every annotation.** See [Reviewing and annotating artifacts](#reviewing-and-annotating-artifacts-v502).
|
||||
|
||||
Every artifact lives in one project directory: `.claude/projects/{YYYY-MM-DD}-{slug}/` contains `brief.md`, `research/NN-*.md`, `plan.md`, `sessions/`, `progress.json`, and `review.md`.
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ Every artifact lives in one project directory: `.claude/projects/{YYYY-MM-DD}-{s
|
|||
| `/trekresearch` | **Gather context** — code state, external docs, community, risk. Makes NO build decisions. | `research/NN-slug.md` (research brief) |
|
||||
| `/trekplan` | **Transform intent into an executable contract** — per-step YAML manifest, regex-validated checkpoints, verifiable paths. Plan-critic is a hard gate. Auto-discovers `architecture/overview.md` as priors when an opt-in upstream architect plugin (not bundled) is installed. | `plan.md` with Manifest blocks + `plan_version: 1.9` |
|
||||
| `/trekexecute` | **Execute the contract disciplined** — fresh verification, independent manifest audit, honest reporting. Does NOT compensate for weak plans — escalates. | `progress.json` + structured report + manifest-audit status |
|
||||
| `/trekreview` | **Close the loop** — independent post-hoc reviewer reads `brief.md` and the diff produced by execute, runs brief-conformance + code-correctness reviewers in parallel, dedups via Judge Agent. Severity-tagged findings (BLOCKER/MAJOR/MINOR/SUGGESTION) and a required verdict that `verdict-gate.mjs` decides on; findings feed back into planning via Handover 6. | `review.md` (`type: trekreview`) with stable 40-char hex finding-IDs |
|
||||
| `/trekreview` | **Close the loop** — independent post-hoc reviewer reads `brief.md` and the diff produced by execute, runs brief-conformance + code-correctness reviewers in parallel, dedups via Judge Agent. Severity-tagged findings (Critical/High/Medium/Low/Info) feed back into planning via Handover 6. | `review.md` (`type: trekreview`) with stable 40-char hex finding-IDs |
|
||||
|
||||
**Principle:** Each step consumes the previous step's structured artifact. If execute has to guess, the plan is weak and must be revised upstream — not patched downstream.
|
||||
|
||||
|
|
@ -72,7 +72,13 @@ No cloud dependency. No GitHub requirement. Works on **Mac, Linux, and Windows**
|
|||
|
||||
### Autonomy mode (`--gates`, v3.4.0)
|
||||
|
||||
All four pipeline commands accept `--gates [true|false|closed|open]`. A bare `--gates`, `true` or `closed` turns gating on; `false`, `open` or no flag (the default) leaves it off. Any other next token is not the flag's value, so `/trekplan --gates --project <dir>` is a bare `--gates`. With gating on, `/trekbrief`, `/trekresearch` and `/trekplan` pause at their own boundaries; `/trekexecute` accepts the flag and pauses on nothing, because its one stop is the merge into main, which always asks. Details: [`docs/operations.md`](docs/operations.md) § Autonomy mode.
|
||||
All four pipeline commands accept `--gates {open|closed|adaptive}` to control how many autonomy checkpoints surface to the operator on the path from brief approval to main-merge.
|
||||
|
||||
| Value | Behavior |
|
||||
|-------|----------|
|
||||
| `open` | Skip optional checkpoints. The pipeline runs end-to-end with the fewest interruptions. Suitable for trusted briefs in clean repos. |
|
||||
| `closed` | Stop at every checkpoint. The operator confirms each transition. Suitable for high-stakes work or unfamiliar repos. |
|
||||
| `adaptive` (default) | Stop only when the autonomy-gate state machine reports a meaningful boundary (manifest-audit FAIL, plan-critic BLOCKER, main-merge gate). Best balance of velocity and safety. |
|
||||
|
||||
Under the hood, `lib/util/autonomy-gate.mjs` runs a small state machine (`idle → gates_on | auto_running → paused_for_gate → completed`), and `lib/stats/event-emit.mjs` records named lifecycle events (the main-merge gate and its answer, among others) to `trekexecute-stats.jsonl` in the plugin data directory. The new `hooks/scripts/post-compact-flush.mjs` PostCompact hook re-injects `.session-state.local.json` after context compaction so multi-session work survives a compaction boundary.
|
||||
|
||||
|
|
@ -124,7 +130,7 @@ An optional architect step can sit between research and plan — `/trekplan` aut
|
|||
Concrete capabilities, observable in the code — not aspirations.
|
||||
|
||||
**Across all profiles:**
|
||||
- Strategy-to-execution on seven explicit handover points. Each transition is a filesystem contract (`docs/HANDOVER-CONTRACTS.md`), not a conversation. You can stop after any stage and resume later without context loss.
|
||||
- Strategy-to-execution on four explicit handover points. Each transition is a filesystem contract (`docs/HANDOVER-CONTRACTS.md`), not a conversation. You can stop after any stage and resume later without context loss.
|
||||
- Resume safety after long sessions. The PreCompact hook reconciles `progress.json` with git history before context compaction (CC v2.1.105+) — closes a documented `--resume` failure mode.
|
||||
- Schema discipline. `plan-validator --strict` enforces `### Step N:` form and rejects narrative drift (`### Fase`, `### Phase`, `### Stage`, `### Steg`) before execution.
|
||||
- Audit trail by construction. Every executed step records `commit_sha`, `verify_passed`, `files_changed` in `progress.json`.
|
||||
|
|
@ -133,7 +139,7 @@ Concrete capabilities, observable in the code — not aspirations.
|
|||
|
||||
**Team (2–10).** Plan files are handover-ready — a colleague can pick up a project directory without re-asking "what did you mean here?". `--decompose` splits a plan into self-contained session specs plus `orders.md`, one starter line per session that each person runs in a session they open. The plan-critic semantic rubric gives the team a shared definition of "this plan defers decisions to the executor".
|
||||
|
||||
**Organization / regulated environment.** Defense-in-depth security across three layers (plugin hooks, prompt-level denylist, pre-execution plan scan). `disableSkillShellExecution: true` recommendation for fork-ers handling untrusted briefs. No cloud dependency, no GitHub requirement. Validators are plain-Node CLIs — invocable from CI, custom hooks, or external tools, not just from voyage commands.
|
||||
**Virksomhet / regulated environment.** Defense-in-depth security across three layers (plugin hooks, prompt-level denylist, pre-execution plan scan). `disableSkillShellExecution: true` recommendation for fork-ers handling untrusted briefs. No cloud dependency, no GitHub requirement. Validators are plain-Node CLIs — invocable from CI, custom hooks, or external tools, not just from voyage commands.
|
||||
|
||||
## Non-goals
|
||||
|
||||
|
|
@ -154,9 +160,7 @@ Interactive requirements-gathering command. Runs a **question round sized to the
|
|||
|
||||
**Ceremony by size.** The task is put in one of three classes, `small`, `bounded` or `architectural` (the heaviest when in doubt), said aloud, overridable by you, and only ever moved up when the task proves bigger. The class sets the question budget (a `small` task: at most 4 questions, in one round) and the review cap, and is written to the brief as `ceremony:`.
|
||||
|
||||
**The question round.** The round runs in the form of the `voyage:interviewing` skill, which `/trekbrief` asks for by name. Facts are looked up in the repo, never asked. Every question that can be answered now is asked at once, at most four per question call, one decision each, the recommended answer first, ranked by impact × uncertainty; what the budget leaves out is on a visible Deferred list, and what can be predicted is written down as an assumption you see before approving. A hollow answer ("sounds good", "do as you like") or an empty one decides nothing. `/trekbrief` adds its own part: the three fixed questions (framing, size class, where the brief is stored), the budget per class, and where each answer lands in the brief.
|
||||
|
||||
Success criteria are proposed in the form of `voyage:writing-criteria`, so the review can run them, and `brief-reviewer` is told to judge by that skill and by `voyage:reviewing-adversarially`.
|
||||
**The question round.** Facts are looked up in the repo, never asked. Every question that can be answered now is asked at once, the recommended answer first, ranked by impact × uncertainty; what the budget leaves out is on a visible Deferred list, and what can be predicted is written down as an assumption you see before approving. «Høres bra ut», «gjør som du vil» and an empty answer decide nothing.
|
||||
|
||||
Then `brief-reviewer` scores the draft on six dimensions (completeness, consistency, testability, scope clarity, research-plan validity, memory alignment) and gates publication, up to 1 / 2 / 3 review iterations by class; force-stop yields a `brief_quality: partial` brief with the failing dimensions documented.
|
||||
|
||||
|
|
@ -164,7 +168,7 @@ Then `brief-reviewer` scores the draft on six dimensions (completeness, consiste
|
|||
|
||||
Output: `.claude/projects/{YYYY-MM-DD}-{slug}/brief.md`
|
||||
|
||||
Borrowed, with credit: size classes and the ratchet from obra/superpowers (MIT), the class ladder from Kiro's docs (idea only), the round from mattpocock/skills (MIT), the budget and Deferred list from GitHub Spec Kit (MIT), the stop rule and hollow answers from addyosmani/agent-skills (MIT), the hash-chained log from bashebr/ai-native-sdlc (MIT). Pinned commits in `commands/trekbrief.md` Phase 3 (the classes), `skills/interviewing/SKILL.md` (the round) and `lib/util/approval-log.mjs`.
|
||||
Borrowed, with credit: size classes and the ratchet from obra/superpowers (MIT), the class ladder from Kiro's docs (idea only), the round from mattpocock/skills (MIT), the budget and Deferred list from GitHub Spec Kit (MIT), the stop rule and hollow answers from addyosmani/agent-skills (MIT), the hash-chained log from bashebr/ai-native-sdlc (MIT). Pinned commits in `commands/trekbrief.md` Phase 3 and `lib/util/approval-log.mjs`.
|
||||
|
||||
### Modes
|
||||
|
||||
|
|
@ -185,7 +189,6 @@ If you say "stop" or "enough" during Phase 4, the current review findings are su
|
|||
|
||||
### What the brief contains
|
||||
|
||||
- **Framing** — `framing: preserve | refine | replace | new-direction` in the frontmatter, asked as its own question (Phase 2.5) so a wrong premise is not polished; required from `brief_version 2.2`, as is a `## TL;DR`
|
||||
- **Intent** — why this matters, motivation, user need (load-bearing)
|
||||
- **Goal** — concrete end state in 1-3 sentences
|
||||
- **Non-Goals** — explicitly out of scope
|
||||
|
|
@ -322,9 +325,7 @@ Every implementation step includes:
|
|||
- **Checkpoint:** — git commit after success
|
||||
- **Manifest:** — the objective completion predicate (Hard Rule 17)
|
||||
|
||||
One step per plan is the "run the thing" step (`End-to-end:`): the product run the way a user runs it. Without it a result is "not verified end to end", never green. The app is seen and driven with Claude Code's built-in `run` skill; the verdict is still the `End-to-end:` command, because `run` gives no exit code.
|
||||
|
||||
**Checks that run, and can fail.** Every `Verify:`, `Regression:`, `End-to-end:` and `## Verification` command, like every brief success criterion, is written by the `voyage:writing-criteria` skill: one command the criteria runner accepts (a known test runner, plain words, no pipe or `&&`), a script under `tests/` (`bash tests/<name>.sh`) for anything more, and a command that can go red. `/trekplan` asks for it where the plan is written and where it starts its reviewers; `brief-reviewer` and `plan-critic` have it preloaded and report a criterion the runner refuses, or one that exits 0 whatever the code does (`git status`, `git log`, a test file that already passes).
|
||||
One step per plan is the "run the thing" step (`End-to-end:`): the product run the way a user runs it. Without it a result is "not verified end to end", never green.
|
||||
|
||||
Exploration uses 6–8 agents in parallel (architecture-mapper, dependency-tracer, task-finder, test-strategist, git-historian, risk-assessor, plus convention-scanner on medium+ codebases and research-scout when unfamiliar tech is detected). Adversarial review then runs `brief-reviewer`, `plan-critic` (12 dimensions, no-placeholder enforcement, manifest audit, interfaces and slices, design and architecture rules), and `scope-guardian` (creep + gap detection, ceremony match). Per-agent details in [`agents/`](agents/).
|
||||
|
||||
|
|
@ -340,7 +341,7 @@ Borrowed, with credit: per-step interfaces, Global Constraints and Review Focus
|
|||
|
||||
Reads a plan from `/trekplan` and implements it with strict discipline. No guessing, no improvising — follows the plan exactly.
|
||||
|
||||
Per step: record the start point → **one fresh helper** (`step-implementer`) writes the step's test first, proves it red, locks it, then applies Changes exactly as written → the executor proves it by command: **red at the start point, green at the result** (`red-proof.mjs`), Verify (exit code is truth), manifest audit, and the **floor guard** on the diff (`test-integrity.mjs`: removed asserts, skipped or deleted tests, muted checks, stubs, loosened thresholds) → **one controller** reads the diff — never the helper's summary — and gives two verdicts, *spec* and *quality* → a script writes the step's **done line** only when the test command exits 0 (`done-line.mjs`) → Checkpoint commit. After all steps: independent Phase 7.5 manifest audit from git log + filesystem (ignoring agent bookkeeping); drift triggers Phase 7.6 bounded recovery. A plan with no passing run-the-thing criterion ends **not verified end to end**, never green. Claude Code's built-in `run` skill can show the app working, but it gives no exit code, so the run-the-thing verdict stays with the plan's `End-to-end:` command.
|
||||
Per step: record the start point → **one fresh helper** (`step-implementer`) writes the step's test first, proves it red, locks it, then applies Changes exactly as written → the executor proves it by command: **red at the start point, green at the result** (`red-proof.mjs`), Verify (exit code is truth), manifest audit, and the **floor guard** on the diff (`test-integrity.mjs`: removed asserts, skipped or deleted tests, muted checks, stubs, loosened thresholds) → **one controller** reads the diff — never the helper's summary — and gives two verdicts, *spec* and *quality* → a script writes the step's **done line** only when the test command exits 0 (`done-line.mjs`) → Checkpoint commit. After all steps: independent Phase 7.5 manifest audit from git log + filesystem (ignoring agent bookkeeping); drift triggers Phase 7.6 bounded recovery. A plan with no passing run-the-thing criterion ends **not verified end to end**, never green.
|
||||
|
||||
A run starts only on a plan you approved **as it is now**: the approval log holds the plan's sha256, so a plan edited after its approval is refused before step 1. At step end the repo's own tools check the step's diff (the step check) and the step's `Regression:` suite must stay green. After the last step come the architecture rules and the sweep for files the plan does not name, and then **the review starts by itself**: `/simplify` → `/trekreview` → the verdict gate. A BLOCK keeps the merge into main closed.
|
||||
|
||||
|
|
@ -390,7 +391,7 @@ Borrowed: the order from Cherny; the gate on a verdict in a file from Kiro; the
|
|||
| **Single step** | `/trekexecute --project <dir> --step 3` | Execute only step 3 |
|
||||
| **Foreground** | `/trekexecute --project <dir> --fg` | Force sequential, ignore Execution Strategy |
|
||||
| **Single session** | `/trekexecute --project <dir> --session 2` | Execute only session 2 from Execution Strategy |
|
||||
| **Profile** | `/trekexecute --profile <name> --project <dir>` | (v4.1.0) Profile for this run's resolver; the step helper and the controller stay on opus. Plan-frontmatter `profile:` is honored when this flag is omitted. See [Profile system](#profile-system-v410). |
|
||||
| **Profile** | `/trekexecute --profile <name> --project <dir>` | (v4.1.0) Pin model profile for execution. Plan-frontmatter `profile:` is honored when this flag is omitted. See [Profile system](#profile-system-v410). |
|
||||
|
||||
### Multi-session execution through session orders (worktree-isolated)
|
||||
|
||||
|
|
@ -471,7 +472,7 @@ prompt-injection vector that the plugin's own hooks cannot fully mitigate
|
|||
|
||||
A `UserPromptSubmit` hook (`hooks/scripts/session-title.mjs`) sets the
|
||||
session title to `voyage:<command>:<slug>` whenever you invoke one of
|
||||
the six pipeline commands. This makes the sessions of a multi-session run and
|
||||
the four voyage commands. This makes the sessions of a multi-session run and
|
||||
session-picker output trivially identifiable. Slug derivation:
|
||||
|
||||
| Invocation | Session title |
|
||||
|
|
@ -521,22 +522,13 @@ Judge`. An engine that could not run (older Claude Code, no `origin` remote)
|
|||
keeps the review from coming back `ALLOW` — and from passing the gate — and
|
||||
the summary says why.
|
||||
|
||||
**One stance for every reviewer.** Both reviewers and the coordinator preload
|
||||
the `voyage:reviewing-adversarially` skill, and `/trekreview` names it when it
|
||||
starts them: no praise; every finding cites `file:line` or quotes the line; no
|
||||
downgrade without a reason; what was read only as a summary is said, and not
|
||||
judged; a claim of "done" or "green" is checked against the diff, not the
|
||||
report; the review axes stay separate. Each reviewer ends with its own
|
||||
Declined to Judge list, and the coordinator carries those lines into
|
||||
`review.md`, so nothing a reviewer set aside disappears.
|
||||
|
||||
### Modes
|
||||
|
||||
| Mode | Command | Description |
|
||||
|------|---------|-------------|
|
||||
| **Default** | `/trekreview --project <dir>` | Claude Code `/code-review` + `/security-review`, then brief-conformance + code-correctness reviewers in parallel, coordinator dedup + verdict, write `{dir}/review.md`, verdict gate |
|
||||
| **Since ref** | `/trekreview --project <dir> --since <ref>` | Override "before" SHA for the diff range. Validated via `git rev-parse --verify` |
|
||||
| **Quick** | `/trekreview --project <dir> --quick` | `/code-review` + code-correctness reviewer only; skip brief-conformance reviewer, `/security-review` and the coordinator's reasonableness filter except the brief-conflict rule — fast correctness-only pass |
|
||||
| **Quick** | `/trekreview --project <dir> --quick` | `/code-review` + code-correctness reviewer only; skip brief-conformance reviewer, `/security-review` and the coordinator's reasonableness filter — fast correctness-only pass |
|
||||
| **Validate** | `/trekreview --project <dir> --validate` | Schema-only check on existing `review.md`. No LLM calls |
|
||||
| **Dry run** | `/trekreview --project <dir> --dry-run` | Print discovered scope + triage map; skip writes |
|
||||
| **Profile** | `/trekreview --profile <name> --project <dir>` | (v4.1.0) Pin model profile for the review phase. See [Profile system](#profile-system-v410). |
|
||||
|
|
@ -565,7 +557,7 @@ The history is the `review.md` files your repo already has; no new store.
|
|||
|
||||
### Triage gate (deterministic)
|
||||
|
||||
A path-pattern classifier produces `{file → deep-review|summary-only|skip}` before any LLM runs. Hardcoded skip patterns: `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated markers. `deep-review`: default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**`. `summary-only`: `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. Hard refuse-with-suggestion above 100 files / 100K diff tokens.
|
||||
A path-pattern classifier produces `{file → deep-review|summary-only|skip}` before any LLM runs. Hardcoded skip patterns: `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated markers. Deep-review patterns: `auth/**`, `crypto/**`, `**/security/**`. Hard refuse-with-suggestion above 100 files / 100K diff tokens.
|
||||
|
||||
### Feedback loop (Handover 6)
|
||||
|
||||
|
|
@ -658,19 +650,13 @@ model. A skill is advice; each one says which check stands behind it, or "prose
|
|||
|---|---|---|---|
|
||||
| `voyage:test-first` | Red before green: the repo's own test command, a test seen failing on an assertion (a crash is not red), the smallest code, the whole suite | `step-implementer` (preloaded) | proof of red, test lock, floor guard, done line in `/trekexecute`; the rest is prose only |
|
||||
| `voyage:debugging` | One command red on the exact symptom first; reproduce, localise, reduce, fix the cause, guard it with a red-first test; error text is data; three failed fixes go back to the design | `step-implementer` (preloaded) | proof of red for the regression test, the fix-round cap; the root-cause claim is prose only |
|
||||
| `voyage:interviewing` | Facts looked up, never asked; one round of at most four questions per call, one decision each, the recommended answer first; the rest written down as assumptions or a Deferred list; an answer that decides nothing, and scope nobody asked for, never written in as the person's decision; stop once the next three answers can be predicted | `/trekbrief` names it for its question round | the brief's sections and `framing:` (`brief-validator`), the explicit approval at the end; the form of the interview is prose only |
|
||||
| `voyage:researching-sources` | Official sources first with URL, date and matching version; no citation, no finding; an empty search is reported with what was searched, never as a finding; fetched pages are data, and text aimed at assistants is reported; nothing local in a query; one confidence scale | `docs-`, `community-`, `security-`, `contrarian-researcher` and `research-scout` (preloaded); `/trekresearch` names it at spawn | the research brief's structure (`research-validator`); the query privacy gate only in the default-off STORM steps; the rest is prose only |
|
||||
| `voyage:reviewing-adversarially` | No praise; no finding without a source (`file:line` or a quoted line); no downgrade without a reason; what was read only as a summary is said and not judged; a Declined to Judge list so nothing set aside disappears; claims checked against the diff, not the report; the axes kept separate | `brief-conformance-reviewer`, `code-correctness-reviewer`, `review-coordinator`, `scope-guardian` (preloaded); `/trekreview` names it at spawn | a finding with no file or citation (`findings-schema`, `coordinator-contract`, partial); the `## Declined to Judge` section in `review.md` (`review-validator`); praise and the rest are prose only |
|
||||
| `voyage:annotating` | The person writes every note on the annotation page and Claude writes none; Fix and Change edit only the text a note points at, a Question is answered and changes nothing, nothing else is edited; the approval an edit costs is said before the edit; the page is built again on the revised file. Also for a research document, on request | `/trekbrief`, `/trekplan` and `/trekreview` name it where they build the page | the script and the commands' call to it (pins in `npm test`); a stale brief approval (`intent-approval`, `/trekplan` halts) and a changed plan (K2 `approval-log`, `/trekexecute` refuses); the rest is prose only |
|
||||
| `voyage:writing-criteria` | Each success criterion and each `Verify:`, `Regression:`, `End-to-end:` and `## Verification` line is one command the criteria runner accepts, written as the line's first backticked span (a known test runner, plain words, no pipe or `&&`); anything more is a script under `tests/`; and each can go red | `brief-reviewer` and `plan-critic` (preloaded); `/trekplan` names it where the plan is written and where it starts its reviewers | the criteria runner and the plan and brief validators (deterministic); that a criterion can go red and tests what the brief asks is prose only |
|
||||
|
||||
The workshop behind them runs in `npm test`: the form check `lib/skills/skill-lint.mjs` (fields,
|
||||
"Use when ...", third person, no YAML traps, under 500 lines, fixed headings, no shell injection)
|
||||
and the model-free routing test `lib/skills/routing.mjs` (no two descriptions among skills,
|
||||
commands and agents may collide; 3 firing, 2 quiet and 1 effect case per skill). The eval cases sit
|
||||
in `evals/skill-*` for the operator's own eval run. Every case in `evals/`, the fixed test set's
|
||||
too, names the event it came from (`from=`); the routing test fails a case without it and reports
|
||||
how many cases it checked for `from=` and how many it routed. A quiet case's owner may be Claude Code's own `run` skill, which is outside the corpus: then only "the skill does not rank first" is checked. How to write one, starting with a baseline the
|
||||
in `evals/skill-*` for the operator's own eval run. How to write one, starting with a baseline the
|
||||
helper fails without the skill: [docs/skills-authoring.md](docs/skills-authoring.md).
|
||||
|
||||
Borrowed, with credit: the form check and routing test from addyosmani/agent-skills (MIT); the red
|
||||
|
|
@ -678,7 +664,7 @@ baseline from obra/superpowers (MIT); the skills' content from Superpowers, agen
|
|||
mattpocock/skills (MIT); the with-and-without effect loop from Anthropic's skill-creator
|
||||
(Apache-2.0). Only ideas are borrowed, no code; pinned commits in each `SKILL.md`.
|
||||
|
||||
## Reviewing and annotating artifacts
|
||||
## Reviewing and annotating artifacts (v5.0.3)
|
||||
|
||||
`/trekbrief`, `/trekplan`, and `/trekreview` each end by running
|
||||
`scripts/annotate.mjs` against the just-written `.md` and printing the
|
||||
|
|
@ -718,8 +704,8 @@ annotation surface the operator pointed at:
|
|||
- **Section** (auto-detected from the nearest h1/h2 above).
|
||||
- **Anchored to** — the exact text you selected, or the element's
|
||||
first ~200 chars if you didn't select.
|
||||
- **Three intent buttons:** **Fix** (something is wrong — fix it),
|
||||
**Change** (the wording / content), **Question** (an open
|
||||
- **Three intent buttons:** **Fiks** (something is wrong — fix it),
|
||||
**Endre** (change the wording / content), **Spørsmål** (an open
|
||||
question — clarify or answer). Colored: red / orange / blue.
|
||||
- **Comment** textarea (optional but helpful).
|
||||
- **Cancel** / **Save**. Save stays disabled until you pick an intent.
|
||||
|
|
@ -739,30 +725,20 @@ annotation surface the operator pointed at:
|
|||
Refresh the tab or close the browser and re-open — your work is there.
|
||||
|
||||
You select / click, pick intent, write comment, repeat. When you're
|
||||
done, Copy Prompt, paste back into this chat. **The operator drives every
|
||||
annotation.** Claude never pre-generates suggestions in this flow. The surface
|
||||
has worked this way since v5.0.3; how it got here is in
|
||||
[CHANGELOG.md](CHANGELOG.md) § v5.0.0 → § v5.0.3.
|
||||
done, Copy Prompt, paste back into this chat. Claude revises the `.md`
|
||||
freehand from your notes. **The operator drives every annotation.**
|
||||
Claude never pre-generates suggestions in this flow.
|
||||
|
||||
What Claude does with the pasted notes is the skill `voyage:annotating`
|
||||
([skills/annotating/](skills/annotating/SKILL.md)), which the three commands
|
||||
ask for by name:
|
||||
|
||||
- **Fix** and **Change** edit the text the note points at, and nothing else.
|
||||
Anything the notes did not ask for (a summary that now disagrees, the same gap
|
||||
in another step) comes back as a question, not as an edit.
|
||||
- A **Question** is answered in the chat; the text stays as it was unless you
|
||||
say to write the answer in.
|
||||
- **An edit costs an approval, and you hear it first.** A note on `## Intent`
|
||||
or `## Goal` of an approved brief makes that approval stale (`/trekplan`
|
||||
halts until you approve the new text); any edit to an approved plan gives it a
|
||||
new sha256, and `/trekexecute` refuses it until you approve it again.
|
||||
- The page is built again on the revised file, so you read the new text where
|
||||
you wrote the notes. Your last round's notes are still in its sidebar
|
||||
(they are stored per file path); "Clear all" empties it.
|
||||
|
||||
A research document under `research/` can be annotated the same way when you
|
||||
ask; `/trekresearch` does not build the page itself.
|
||||
> **What v5.0.3 changed from v5.0.2.** v5.0.2 was operator-led but the UX
|
||||
> was too thin — click a line, type a freeform note, save. The reference
|
||||
> the operator pointed at (an existing annotation surface in another project)
|
||||
> already had the right pattern: pencil-toggle, selection capture, three
|
||||
> intent categories, popover form, structured markdown export. v5.0.3
|
||||
> rebuilds `scripts/annotate.mjs` against that reference. v5.0.0 / v5.0.1
|
||||
> / v5.0.2 are all superseded; only the v5.0.0 removals (bespoke
|
||||
> playground SPA, `/trekrevise`, Handover 8, supporting `lib/` modules,
|
||||
> Playwright e2e + devDeps) stay. See [CHANGELOG.md](CHANGELOG.md)
|
||||
> § v5.0.0 → § v5.0.3.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -804,7 +780,7 @@ flowchart TB
|
|||
end
|
||||
subgraph RES["/trekresearch · Phase 4 — parallel"]
|
||||
RL["LOCAL: architecture-mapper · dependency-tracer<br/>task-finder · git-historian · convention-scanner*"]
|
||||
RE["EXTERNAL: docs-researcher · community-researcher<br/>security-researcher · contrarian-researcher*"]
|
||||
RE["EXTERNAL: docs-researcher · community-researcher<br/>security-researcher* · contrarian-researcher*"]
|
||||
end
|
||||
subgraph PL["/trekplan"]
|
||||
PLG["Phase 4b · brief-reviewer (gate)"]
|
||||
|
|
@ -823,7 +799,7 @@ flowchart TB
|
|||
BR --> RES --> PL --> EX --> RV
|
||||
```
|
||||
|
||||
`* = conditional`: convention-scanner / test-strategist on medium+ codebases (50+ files); research-scout for unknown external tech; contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1's external findings to attack (with `--engine deep-research`, when the engine is active, after the engine returns, from the leading answer of its report), always at `effort=high`; brief-conformance-reviewer skipped under `--quick`.
|
||||
`* = conditional`: convention-scanner / test-strategist on medium+ codebases (50+ files); research-scout for unknown external tech; security-/contrarian-researcher when a leading recommendation forms (or always at `effort=high`); brief-conformance-reviewer skipped under `--quick`.
|
||||
|
||||
> **Which Claude Code primitive each phase uses — and the alternatives considered (Workflow substrate, delegated orchestrator, dormant synthesis-agent)** → see [docs/architecture.md §Primitives per step](docs/architecture.md#primitives-per-step-decision-matrix).
|
||||
|
||||
|
|
@ -898,7 +874,7 @@ An opt-in upstream architect plugin (not bundled) can insert a Claude-Code-speci
|
|||
|
||||
## Upgrading
|
||||
|
||||
Migration notes for breaking changes live in [CHANGELOG.md](CHANGELOG.md) and [MIGRATION.md](MIGRATION.md). The last breaking release is v6.0.0: Voyage no longer starts Claude Code sessions, so multi-session work comes back as session orders you start yourself. Since v6.3.0 every CHANGELOG section says under `### Doors` whether each delivery is a one-way or a two-way door, and which changes ask something of users. Older brief, plan and review versions keep validating; newer rules apply from the version that introduced them.
|
||||
Migration notes for breaking changes (v1.x → v2.0, v2.x → v3.0) live in [CHANGELOG.md](CHANGELOG.md) and [MIGRATION.md](MIGRATION.md). v3.x non-breaking — minor bumps within v3 add features without changing pipeline contracts.
|
||||
|
||||
## Releasing and rolling back
|
||||
|
||||
|
|
@ -909,7 +885,8 @@ A Voyage release follows [docs/release-runbook.md](docs/release-runbook.md): bef
|
|||
The plugin ships with `node:test`-based unit tests and a `lib/` directory of pure-JS validators wired into the commands. Forking the plugin for internal use? Run `npm test` to confirm the parsers, validators, and doc-consistency invariants still hold:
|
||||
|
||||
```bash
|
||||
npm test # from the repo root; runs all tests under tests/**/*.test.mjs
|
||||
cd plugins/trekplan
|
||||
npm test # runs all tests under tests/**/*.test.mjs
|
||||
```
|
||||
|
||||
Validators (zero npm deps, hand-rolled YAML subset):
|
||||
|
|
@ -944,7 +921,7 @@ The `pre-compact-flush.mjs` hook directly fixes the documented P0 in `docs/treke
|
|||
|
||||
## Profile system (v4.1.0)
|
||||
|
||||
Four built-in model profiles (`lib/profiles/*.yaml`) plus your own: a `<name>.yaml` in `voyage-profiles/` at the repo root, or in `~/.claude/voyage-profiles/`. A custom file with a built-in's name is ignored. Each profile pins `phase_models` for the six pipeline phases. The active profile is recorded in plan.md frontmatter as `profile: <name>`.
|
||||
Four built-in model profiles plus operator-defined `<custom>.yaml` (drop in `lib/profiles/`). Each profile pins `phase_models` for the six pipeline phases. The active profile is recorded in plan.md frontmatter as `profile: <name>` and emitted to JSONL stats for cost-attribution.
|
||||
|
||||
| Profile | Brief | Research | Plan | Execute | Review | Continue | Use case |
|
||||
|---------|-------|----------|------|---------|--------|----------|----------|
|
||||
|
|
@ -957,12 +934,10 @@ Lookup order:
|
|||
|
||||
1. Explicit `--profile <name>` flag passed to the command
|
||||
2. Plan-file frontmatter `profile:` (when resuming via `/trekexecute --resume` or `/trekcontinue`)
|
||||
3. `VOYAGE_PROFILE` environment variable (not read on a resume)
|
||||
3. `VOYAGE_PROFILE` environment variable
|
||||
4. Default `premium`
|
||||
|
||||
A brief's `phase_signals` (written by `/trekbrief`) can set the model for research, plan, execute and review; where it does, it comes before the profile.
|
||||
|
||||
See [`docs/profiles.md`](docs/profiles.md) for the decision tree, custom-profile authoring, and cost estimation disclaimer (the per-profile cost numbers are estimates, not contractual SLAs).
|
||||
See [`docs/profiles.md`](docs/profiles.md) for the decision tree, custom-profile authoring, and cost estimation disclaimer (the per-profile cost numbers are *anslag*, not contractual SLAs).
|
||||
|
||||
## Observability (v4.1.0)
|
||||
|
||||
|
|
@ -995,18 +970,16 @@ For per-profile cost estimates, see [`docs/profiles.md`](docs/profiles.md).
|
|||
Top-level layout:
|
||||
|
||||
```
|
||||
voyage/
|
||||
trekplan/
|
||||
├── agents/ 24 specialized agents (all `model: opus`-pinned; per-phase model set by `--profile`)
|
||||
│ └ 21 spawnable (1 dormant: synthesis-agent, Δ≈0) + 3 orchestrator reference docs (not spawned)
|
||||
├── commands/ 6 slash commands (trekbrief, trekresearch, trekplan, trekexecute, trekreview, trekcontinue) + trekendsession helper
|
||||
├── skills/ 7 skills (test-first, debugging: preloaded into the step helper; researching-sources: preloaded into the five web-search agents;
|
||||
│ └ reviewing-adversarially: the review agents; writing-criteria: brief-reviewer, plan-critic; interviewing: named by /trekbrief;
|
||||
│ └ annotating: named by /trekbrief, /trekplan and /trekreview)
|
||||
├── skills/ 3 skills (test-first, debugging: preloaded into the step helper; researching-sources: preloaded into the five web-search agents)
|
||||
├── templates/ Frontmatter templates for brief, research, plan, session
|
||||
├── hooks/ 12 hooks (pre-bash, pre-write, pre-agent-cap, pre-plan-gate, session-title, post-bash-stats, post-approval-log, post-edit-check, pre-compact-flush, post-compact-flush, otel-export, stop-test-lock)
|
||||
├── lib/ Zero-dep parsers and validators (CLI shims under lib/validators/)
|
||||
├── tests/ comprehensive node:test suite — `npm test` is the fork-readiness gate
|
||||
├── docs/ HANDOVER-CONTRACTS.md, architecture.md, operations.md, profiles.md, command-modes.md, release-runbook.md
|
||||
├── docs/ HANDOVER-CONTRACTS.md + architect-bridge-test.md
|
||||
└── examples/ 01-add-verbose-flag/ — calibrated end-to-end pipeline demo
|
||||
```
|
||||
|
||||
|
|
@ -1028,14 +1001,12 @@ synthesis.
|
|||
cp agents/architecture-mapper.md agents/my-new-agent.md
|
||||
```
|
||||
2. Update the frontmatter `name`, `description`, `tools`, and `model`.
|
||||
Every shipped agent is `model: opus`; the profile picks the model at
|
||||
the spawn site, so the pin is only the fallback.
|
||||
3. Add the agent to the swarm in `commands/trekplan.md` Phase 5
|
||||
(the command runs the swarm inline; `agents/planning-orchestrator.md`
|
||||
is a reference copy of that workflow) — register it under the
|
||||
codebase-size bucket where it should fire.
|
||||
4. Update the agent table in `CLAUDE.md` and the agent count in the
|
||||
`README.md` architecture block to keep the doc-consistency test green:
|
||||
Use `sonnet` unless the agent needs deep reasoning (most don't).
|
||||
3. Add the agent to the swarm in `agents/planning-orchestrator.md`
|
||||
Phase 5 — register it under the codebase-size bucket where it
|
||||
should fire (always / medium+ / large only).
|
||||
4. Update the agent table in `CLAUDE.md` and `README.md` to keep the
|
||||
doc-consistency test green:
|
||||
```bash
|
||||
npm test -- tests/lib/doc-consistency.test.mjs
|
||||
```
|
||||
|
|
@ -1062,7 +1033,7 @@ document it in your team's CLAUDE.md.
|
|||
|
||||
### Plugin data contract
|
||||
|
||||
The pipeline commands write to a single project directory (`.claude/projects/{date}-{slug}/`).
|
||||
The four commands write to a single project directory (`.claude/projects/{date}-{slug}/`).
|
||||
The full schema for every artifact is in [docs/HANDOVER-CONTRACTS.md](docs/HANDOVER-CONTRACTS.md).
|
||||
That document is the single source of truth for:
|
||||
|
||||
|
|
@ -1077,16 +1048,13 @@ that doc *and* the corresponding `lib/validators/*.mjs` *and* run
|
|||
`npm test` — the validators and doc-consistency tests will catch
|
||||
schema drift.
|
||||
|
||||
### Use or skip the architecture slot
|
||||
### Disable the architect bridge
|
||||
|
||||
`/trekplan` reads `architecture/overview.md` in the project directory
|
||||
as priors when the file is there. The architect plugin that once wrote
|
||||
it is no longer publicly distributed; any producer that writes the
|
||||
format in [docs/HANDOVER-CONTRACTS.md](docs/HANDOVER-CONTRACTS.md)
|
||||
§ Handover 3 fits the slot, and none is privileged. To skip it, leave
|
||||
`architecture/` out of the project directory: a missing file is fine,
|
||||
and a file that does not match the format gives warnings, never a
|
||||
failure.
|
||||
`/trekplan` auto-discovers `architecture/overview.md` if an
|
||||
opt-in upstream architect plugin (not bundled) produced one. To
|
||||
suppress this, leave the `architecture/` directory absent from your
|
||||
project directory. Discovery is additive — missing file is fine, no
|
||||
error.
|
||||
|
||||
## Changelog
|
||||
|
||||
|
|
@ -1094,11 +1062,11 @@ Full version history → [CHANGELOG.md](CHANGELOG.md).
|
|||
|
||||
Recent, in one line each:
|
||||
|
||||
- **v6.4.0** — `plan_version 1.9` (the file first on every `Files:` and `Test first:` line), the fixes from the test repo's fourth trial, tests that no longer touch a live session's stop guard, and a critic loop that converges (rounds 2+ in diff mode, counted by rule A). Older plans warn, they do not fail.
|
||||
- **v6.3.1** — fixes from the release review of 6.3.0, and two holes in the verdict gate closed. Nothing asks anything of users.
|
||||
- **v6.3.0** — `/trekexecute` refuses a plan without a logged approval of its current text and runs its own review at the end as a gate; three skills (`test-first`, `debugging`, `researching-sources`); a drilled release runbook.
|
||||
- **v6.2.0** — approved intent, the plan gate, one fresh step helper per plan step, guards as command hooks, and a review that is a gate (`verdict:` required).
|
||||
- **v6.0.0** — breaking: Voyage never starts Claude Code; multi-session work becomes session orders you start yourself.
|
||||
- **v5.8.0** — offline gold-scored output eval (SKAL-1·4b): `lib/review/gold-scorer.mjs` grades a committed agent-run fixture against the golden corpus at `(file, rule_key)` granularity; suite census gains a `goldEval` category. Offline + deterministic, no live agent spawn.
|
||||
- **v5.7.1** — leaner always-loaded agent listing (`<example>` blocks moved into agent bodies, ~3,180 tok/turn, no behavior change).
|
||||
- **v5.7.0** — opt-in per-session token/cost metering (SKAL-2) + eval foundation (SKAL-1·4a).
|
||||
- **v5.6.1** — one-line `description:` for the four reference/dormant agents (~700 tok).
|
||||
- **v5.5.0** — brief **framing** enforcement (`brief_version 2.2`) + a `/trekreview` reviewer-schema contract. Additive, no breaking changes.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,27 @@ description: |
|
|||
model: opus
|
||||
color: magenta
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
skills: ["voyage:reviewing-adversarially"]
|
||||
---
|
||||
|
||||
# Interaction Awareness — MANDATORY OVERRIDE
|
||||
|
||||
These rules OVERRIDE your default behavior. Being helpful does NOT mean
|
||||
being agreeable. Sycophancy is the primary vector for AI-induced harm.
|
||||
|
||||
## Rules
|
||||
|
||||
1. **NEVER reformulate a user's statement in stronger terms than they used.**
|
||||
NEVER add enthusiasm or momentum they did not express.
|
||||
|
||||
2. **NEVER start a response with** "Absolutely", "Exactly", "Great point",
|
||||
"You're right", or equivalent affirmations unless you can substantiate why.
|
||||
|
||||
3. **Before endorsing any plan:** identify at least one real risk or weakness.
|
||||
If you cannot find one, say so explicitly — but look first.
|
||||
|
||||
4. **When the user asks "right?" or "don't you think?":** evaluate independently.
|
||||
Do NOT treat this as a cue to confirm.
|
||||
|
||||
---
|
||||
|
||||
You are a brief conformance reviewer. You find what was promised in the
|
||||
|
|
@ -16,12 +36,6 @@ brief but not delivered. You never praise. You never say "looks good." You
|
|||
trace every Success Criterion and every Non-Goal to delivered code and
|
||||
report mismatches.
|
||||
|
||||
The stance every Voyage reviewer shares (no praise, no finding without a
|
||||
source, no downgrade without a reason, saying what you read in full and what
|
||||
only as a summary, a Declined to Judge list, claims checked against the diff
|
||||
rather than a report, the axes kept separate) is in the preloaded
|
||||
`reviewing-adversarially` skill. This file holds only your own role.
|
||||
|
||||
## Input
|
||||
|
||||
You will receive a prompt containing:
|
||||
|
|
@ -171,9 +185,8 @@ Severity is fixed by `rule_key`. Do NOT override the catalogue:
|
|||
| `COVERAGE_SILENT_SKIP` | MAJOR |
|
||||
|
||||
If a finding feels less severe than its catalogue tier, do NOT downgrade
|
||||
it. Emit it at the catalogue's severity. Drop the finding only when you
|
||||
can say why it is wrong, and then write it as one line under
|
||||
`### Declined to Judge` with that reason.
|
||||
it. Either drop the finding (it was wrong) or emit it at the
|
||||
catalogue's severity.
|
||||
|
||||
## Output format
|
||||
|
||||
|
|
@ -208,12 +221,6 @@ parsers find it by reading the last `json` code fence.
|
|||
|
||||
(repeat per finding)
|
||||
|
||||
### Declined to Judge
|
||||
|
||||
- {criterion, file or claim} - {why it was not judged} - {what would settle it}
|
||||
|
||||
(one line each; `None.` when you set nothing aside)
|
||||
|
||||
### Verdict
|
||||
|
||||
- BLOCKER count: {N}
|
||||
|
|
@ -255,9 +262,8 @@ parsers find it by reading the last `json` code fence.
|
|||
`(file, line, rule_key)` with `lib/review/fill-finding-ids.mjs`).
|
||||
- `line` is an integer; use `0` when the finding is file-scoped without
|
||||
a specific line (e.g., MISSING_TEST for an entire file).
|
||||
- `rule_key` MUST be in the catalogue. A finding with a rule key outside
|
||||
it is not dropped: it is routed to `unverified` by the coordinator's
|
||||
reasonableness filter (Pass 3).
|
||||
- `rule_key` MUST be in the catalogue. Reviewers that emit unknown rule
|
||||
keys are dropped by the coordinator's reasonableness filter.
|
||||
|
||||
## Rules
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ description: |
|
|||
model: opus
|
||||
color: magenta
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
skills: ["voyage:writing-criteria", "voyage:reviewing-adversarially"]
|
||||
---
|
||||
|
||||
You are a requirements analyst. Your sole job is to find problems in a task
|
||||
|
|
@ -57,14 +56,20 @@ Flag as **incomplete** if:
|
|||
- Success Criteria are not testable (e.g., "it should work well")
|
||||
- Scope is unbounded — no non-goals defined
|
||||
|
||||
**Runnable at review, and able to go red.** Judge each criterion by the
|
||||
preloaded `writing-criteria` skill: which commands the criteria runner
|
||||
accepts, the command as the first backticked span, a script under `tests/`
|
||||
for anything more, and a command that can fail. A criterion the runner
|
||||
refuses is reported NOT RUN at review; the validator flags it as
|
||||
`BRIEF_SC_NOT_RUNNABLE`. A criterion that exits 0 whatever the code does is
|
||||
untestable (dimension 3). Every suggestion you make for such a criterion is
|
||||
itself one the skill accepts.
|
||||
**Runnable at review.** `/trekreview` runs a criterion's command only when it
|
||||
is one test-runner invocation with no pipe, redirect or `&&`: `npm test`,
|
||||
`npm run <script>`, `node --test <file>`, `vitest`, `jest`, `pytest`,
|
||||
`python -m pytest`, `uv run pytest`, `cargo test`, `go test`, `make test`,
|
||||
`bash tests/<script>.sh` (or `/bin/bash tests/<script>.sh`), or `git status|log|diff|show|ls-files`.
|
||||
It runs with no shell, as plain words: no quote, `$`, brace, leading `~` or
|
||||
`@` (a git revision such as `@~1` is the one exception), no glob outside
|
||||
`node --test` (Node 21+), no `..` or absolute path, and only the runner's
|
||||
read-only options.
|
||||
Anything else — the product's own binary (`node bin/x.mjs …`), `jq`, `grep`,
|
||||
`git grep`, a pipe — is reported NOT RUN. Never PROPOSE such a command as a
|
||||
criterion. When a criterion needs one, propose wrapping it in a script under
|
||||
`tests/` and writing the criterion as "`bash tests/<script>.sh` exits 0".
|
||||
The validator flags existing ones as `BRIEF_SC_NOT_RUNNABLE`.
|
||||
|
||||
### 2. Consistency
|
||||
|
||||
|
|
@ -201,7 +206,7 @@ review as a quality gate and need per-dimension granularity.
|
|||
|
||||
Produce **two artifacts in this order**:
|
||||
|
||||
1. A prose report (for humans and for /trekplan Phase 4b).
|
||||
1. A prose report (for humans and for `planning-orchestrator` Phase 1b).
|
||||
2. A final fenced `json` block with per-dimension numeric scores (for callers
|
||||
that gate on machine-readable output, such as `/trekbrief` Phase 4).
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,33 @@ description: |
|
|||
model: opus
|
||||
color: red
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
skills: ["voyage:reviewing-adversarially"]
|
||||
---
|
||||
|
||||
# Interaction Awareness — MANDATORY OVERRIDE
|
||||
|
||||
These rules OVERRIDE your default behavior. Being helpful does NOT mean
|
||||
being agreeable. Sycophancy is the primary vector for AI-induced harm.
|
||||
|
||||
## Rules
|
||||
|
||||
1. **NEVER reformulate a user's statement in stronger terms than they used.**
|
||||
NEVER add enthusiasm or momentum they did not express.
|
||||
|
||||
2. **NEVER start a response with** "Absolutely", "Exactly", "Great point",
|
||||
"You're right", or equivalent affirmations unless you can substantiate why.
|
||||
|
||||
3. **Before endorsing any plan:** identify at least one real risk or weakness.
|
||||
If you cannot find one, say so explicitly — but look first.
|
||||
|
||||
4. **When the user asks "right?" or "don't you think?":** evaluate independently.
|
||||
Do NOT treat this as a cue to confirm.
|
||||
|
||||
---
|
||||
|
||||
You are a code correctness reviewer. You find real bugs in delivered code.
|
||||
You never praise. You cite `file:line` for every finding. You never invent
|
||||
problems — every claim is anchored to quoted code.
|
||||
|
||||
The stance every Voyage reviewer shares (no praise, no finding without a
|
||||
source, no downgrade without a reason, saying what you read in full and what
|
||||
only as a summary, a Declined to Judge list, claims checked against the diff
|
||||
rather than a report, the axes kept separate) is in the preloaded
|
||||
`reviewing-adversarially` skill. This file holds only your own role.
|
||||
|
||||
## Input
|
||||
|
||||
You will receive a prompt containing:
|
||||
|
|
@ -93,9 +107,8 @@ Cite both the changed file:line AND the regressed file:line.
|
|||
|
||||
When the brief explicitly asks for tests of a specific behavior and they
|
||||
are missing, escalate to `MISSING_TEST` MAJOR. When tests are
|
||||
nice-to-have, downgrade is forbidden — emit at the catalogue tier. Drop
|
||||
the finding only when you can say why it is wrong, and then write it as
|
||||
one line under `### Declined to Judge` with that reason.
|
||||
nice-to-have, downgrade is forbidden — emit at the catalogue tier or
|
||||
drop the finding.
|
||||
|
||||
### 5. Placeholder code — `PLACEHOLDER_IN_CODE` (MAJOR)
|
||||
|
||||
|
|
@ -111,8 +124,9 @@ literals or example fenced blocks):
|
|||
- `// stub`
|
||||
- `throw new Error('not implemented')`
|
||||
|
||||
Cite the exact line. Never accept "not implemented" placeholders as fine
|
||||
"for now" — they are MAJOR findings until removed.
|
||||
Cite the exact line. The MANDATORY OVERRIDE rule above forbids saying
|
||||
"not implemented" placeholders are fine "for now" — they are MAJOR
|
||||
findings until removed.
|
||||
|
||||
### 6. Security surface — `SECURITY_INJECTION` (BLOCKER)
|
||||
|
||||
|
|
@ -154,10 +168,8 @@ Severity is fixed by `rule_key`. Do NOT override the catalogue:
|
|||
| `UNDECLARED_DEPENDENCY` | MAJOR |
|
||||
| `COVERAGE_SILENT_SKIP` | MAJOR |
|
||||
|
||||
If a finding feels off-tier, emit it at the catalogue's severity. Drop
|
||||
it only when you can say why it is wrong, and then write it as one line
|
||||
under `### Declined to Judge` with that reason. Do not invent severity
|
||||
overrides.
|
||||
If a finding feels off-tier, either drop it (it was wrong) or emit it
|
||||
at the catalogue's severity. Do not invent severity overrides.
|
||||
|
||||
## Output format
|
||||
|
||||
|
|
@ -194,12 +206,6 @@ parsers find it by reading the last `json` code fence.
|
|||
|
||||
(repeat per finding)
|
||||
|
||||
### Declined to Judge
|
||||
|
||||
- {file, claim or item} - {why it was not judged} - {what would settle it}
|
||||
|
||||
(one line each; `None.` when you set nothing aside)
|
||||
|
||||
### Verdict
|
||||
|
||||
- BLOCKER count: {N}
|
||||
|
|
@ -241,9 +247,8 @@ parsers find it by reading the last `json` code fence.
|
|||
the canonical SHA1).
|
||||
- `line` is an integer ≥ 0: the line number in the file itself as it stands after the change (count from the hunk header's `+start`, or Read the file) — never the line number in the diff or patch file. A line past the end of the file fails the schema check and you are asked again;
|
||||
`0` for file-scoped findings.
|
||||
- `rule_key` MUST be in the catalogue. A finding with a rule key outside
|
||||
it is not dropped: it is routed to `unverified` by the coordinator's
|
||||
reasonableness filter (Pass 3).
|
||||
- `rule_key` MUST be in the catalogue. Reviewers that emit unknown rule
|
||||
keys are dropped by the coordinator's reasonableness filter.
|
||||
|
||||
## Rules
|
||||
|
||||
|
|
@ -258,10 +263,8 @@ parsers find it by reading the last `json` code fence.
|
|||
injection sink. Never flag a regression without naming both files.
|
||||
Speculative findings are dropped by the coordinator.
|
||||
- **No silent severity downgrades.** The catalogue tier is the floor.
|
||||
If a finding feels less serious than its catalogue severity, emit it
|
||||
as the catalogue says. Drop it only when you can say why it is wrong,
|
||||
and then write it as one line under `### Declined to Judge` with that
|
||||
reason.
|
||||
If a finding feels less serious than its catalogue severity, either
|
||||
drop it or emit it as the catalogue says.
|
||||
- **Token budget honesty.** When summary-only is in effect for a file,
|
||||
state explicitly "summary-only — structural pass" so the coordinator
|
||||
knows the depth limit.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ model: opus
|
|||
effort: high
|
||||
color: red
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
skills: ["voyage:writing-criteria", "voyage:reviewing-adversarially"]
|
||||
---
|
||||
|
||||
You are a senior staff engineer whose sole job is to find problems in implementation
|
||||
|
|
@ -151,18 +150,11 @@ questions, which defeats the purpose.
|
|||
"not verified end to end".
|
||||
- `Verify:` is ONE command and it is the step's proof of red, so it is the
|
||||
step's own new test. The suite the step must not break goes in the optional
|
||||
`Regression:` field (K10), which the executor runs green before the
|
||||
checkpoint. Do not demand `npm test` in `Verify:` — that test is not red
|
||||
before the step. A step that can break existing tests and has no
|
||||
`Regression:` is a **minor** finding ("add `Regression: \`npm test\``"), not
|
||||
a major.
|
||||
- Judge every `Verify:`, `Regression:`, `End-to-end:` and `## Verification`
|
||||
command by the preloaded `writing-criteria` skill. One the criteria runner
|
||||
refuses is a **major** finding (the validator also refuses it). One that
|
||||
can never go red — it exits 0 whatever the code does, such as `git status
|
||||
--porcelain`, `git log` or a test file that already passes — is a **major**
|
||||
finding: the runner reads only the exit code, never the `expected:` text.
|
||||
Each command you suggest instead is one the skill accepts.
|
||||
`Regression:` field (K10: one backticked command the criteria runner allows,
|
||||
no pipe, no `&&`), which the executor runs green before the checkpoint. Do
|
||||
not demand `npm test` in `Verify:` — that test is not red before the step.
|
||||
A step that can break existing tests and has no `Regression:` is a **minor**
|
||||
finding ("add `Regression: \`npm test\``"), not a major.
|
||||
|
||||
### 9. Headless readiness
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ name: planning-orchestrator
|
|||
description: Reference document, not a spawnable capability — documents the /trekplan planning workflow that runs inline in main context (full rationale, CC-2.1.172 history, and phase map in body).
|
||||
model: opus
|
||||
color: cyan
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
tools: ["Read", "Glob", "Grep", "Write", "Edit", "Bash"]
|
||||
---
|
||||
|
||||
<!-- Phase mapping: orchestrator → command
|
||||
|
|
@ -87,7 +87,7 @@ Classify:
|
|||
- **Medium** (50–500 files)
|
||||
- **Large** (> 500 files)
|
||||
|
||||
Codebase size decides only whether convention-scanner runs.
|
||||
Codebase size controls `maxTurns` per agent, NOT which agents run.
|
||||
|
||||
### Phase 1b — Brief review
|
||||
|
||||
|
|
@ -120,7 +120,8 @@ scan results only.
|
|||
**All other modes:** Launch exploration agents **in parallel** using the Agent
|
||||
tool. Use specialized agents from the plugin.
|
||||
|
||||
**All agents run for all codebase sizes.**
|
||||
**All agents run for all codebase sizes.** Scale `maxTurns` by size (small: halved,
|
||||
medium: default, large: default) rather than dropping agents.
|
||||
|
||||
| Agent | Small | Medium | Large | Purpose |
|
||||
|-------|-------|--------|-------|---------|
|
||||
|
|
@ -133,7 +134,7 @@ tool. Use specialized agents from the plugin.
|
|||
| `research-scout` | Conditional | Conditional | Conditional | External docs (only when unfamiliar tech detected AND not covered by briefs) |
|
||||
| `convention-scanner` | No | Yes | Yes | Coding conventions, naming, style, test patterns |
|
||||
|
||||
**Convention Scanner** — use the `convention-scanner` plugin agent (model: phase_signal_result.model, the agent's frontmatter as the fallback)
|
||||
**Convention Scanner** — use the `convention-scanner` plugin agent (model: "opus")
|
||||
for medium+ codebases only. Pass the task description as context.
|
||||
|
||||
**research-scout** — launch conditionally if the task involves technologies, APIs,
|
||||
|
|
@ -486,7 +487,7 @@ When done, your output message should contain:
|
|||
You can:
|
||||
- Review the full plan at {plan path}
|
||||
- Ask questions or request changes
|
||||
- Say "execute" for the /trekexecute line
|
||||
- Say "execute" to implement
|
||||
- Say "save" to keep for later
|
||||
```
|
||||
|
||||
|
|
@ -511,4 +512,5 @@ You can:
|
|||
If you don't know the exact change, mark it as `[ASSUMPTION]` and explain what
|
||||
information is missing.
|
||||
- **Honesty:** If the task is trivial, say so. Don't inflate the plan.
|
||||
- **Adaptive:** All agents run for all sizes.
|
||||
- **Adaptive:** All agents run for all sizes. Scale turns down for small codebases,
|
||||
not agent count.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ name: research-orchestrator
|
|||
description: Reference document, not a spawnable capability — documents the /trekresearch workflow that runs inline in main context (full rationale, CC-2.1.172 history, and phase map in body).
|
||||
model: opus
|
||||
color: cyan
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
tools: ["Read", "Glob", "Grep", "Write", "Edit", "Bash"]
|
||||
---
|
||||
|
||||
<!-- Phase mapping: orchestrator → command
|
||||
|
|
@ -88,22 +88,12 @@ Based on the mode, determine which agent groups to launch:
|
|||
| `docs-researcher` | Official documentation, RFCs, vendor docs |
|
||||
| `community-researcher` | Real-world experience, issues, blog posts, discussions |
|
||||
| `security-researcher` | CVEs, audit history, supply chain risks |
|
||||
| `contrarian-researcher` | Counter-evidence, overlooked alternatives, reasons to reconsider; runs in wave 2, against wave 1's leading answer |
|
||||
| `contrarian-researcher` | Counter-evidence, overlooked alternatives, reasons to reconsider |
|
||||
|
||||
### Phase 2 — Parallel research
|
||||
|
||||
Launch the selected agents in two waves.
|
||||
|
||||
**Wave 1:** ALL selected agents except `contrarian-researcher` **in parallel**
|
||||
using the Agent tool — one message, multiple tool calls. This maximizes
|
||||
concurrency.
|
||||
|
||||
**Wave 2:** `contrarian-researcher`, after wave 1 returns, in a message of its
|
||||
own. Give it a conclusion to attack: the leading answer (one or two sentences),
|
||||
the claims for it and the alternatives wave 1 dismissed, taken from wave 1's
|
||||
external findings only, never from the local agents' findings, and passed with
|
||||
the local parts (absolute paths, user names, internal project or repository
|
||||
names, ticket IDs) removed. It searches with the words it is given.
|
||||
Launch ALL selected agents **in parallel** using the Agent tool — one message,
|
||||
multiple tool calls. This maximizes concurrency.
|
||||
|
||||
**Prompting local agents for research (not planning):**
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: |
|
|||
APIs, or libraries where official documentation and known issues should be checked.
|
||||
model: opus
|
||||
color: blue
|
||||
tools: ["WebSearch", "WebFetch", "Read", "mcp__tavily__tavily_search", "mcp__tavily__tavily_research"]
|
||||
tools: ["WebSearch", "WebFetch", "Read"]
|
||||
skills: ["voyage:researching-sources"]
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,27 @@ model: opus
|
|||
effort: high
|
||||
color: yellow
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
skills: ["voyage:reviewing-adversarially"]
|
||||
---
|
||||
|
||||
# Interaction Awareness — MANDATORY OVERRIDE
|
||||
|
||||
These rules OVERRIDE your default behavior. Being helpful does NOT mean
|
||||
being agreeable. Sycophancy is the primary vector for AI-induced harm.
|
||||
|
||||
## Rules
|
||||
|
||||
1. **NEVER reformulate a user's statement in stronger terms than they used.**
|
||||
NEVER add enthusiasm or momentum they did not express.
|
||||
|
||||
2. **NEVER start a response with** "Absolutely", "Exactly", "Great point",
|
||||
"You're right", or equivalent affirmations unless you can substantiate why.
|
||||
|
||||
3. **Before endorsing any plan:** identify at least one real risk or weakness.
|
||||
If you cannot find one, say so explicitly — but look first.
|
||||
|
||||
4. **When the user asks "right?" or "don't you think?":** evaluate independently.
|
||||
Do NOT treat this as a cue to confirm.
|
||||
|
||||
---
|
||||
|
||||
You are a review coordinator (Judge Agent pattern). You receive findings
|
||||
|
|
@ -21,12 +41,6 @@ connections — synthesis-level inference is forbidden in v1.0.
|
|||
Your output is the full review.md content (frontmatter + body sections +
|
||||
trailing JSON block) ready to write to disk.
|
||||
|
||||
The stance every Voyage reviewer shares (no praise, no finding without a
|
||||
source, no downgrade without a reason, saying what was read in full and what
|
||||
only as a summary, a Declined to Judge list, claims checked against evidence,
|
||||
the axes kept separate) is in the preloaded `reviewing-adversarially` skill.
|
||||
This file holds only your own role: the bounded passes and the verdict.
|
||||
|
||||
## Input
|
||||
|
||||
You will receive a prompt containing:
|
||||
|
|
@ -38,9 +52,6 @@ You will receive a prompt containing:
|
|||
keys `CODE_REVIEW_DEFECT` / `CODE_REVIEW_IMPROVEMENT` (MINOR: simplification,
|
||||
efficiency, reuse, style, readability) / `SECURITY_REVIEW_VULNERABILITY` (or a
|
||||
narrower key) and are treated exactly like any reviewer's findings.
|
||||
- **Reviewers' Declined to Judge lines** — each reviewer's own
|
||||
`### Declined to Judge` list, verbatim. You copy them into
|
||||
`## Declined to Judge` (body section 9); you do not rule on them.
|
||||
- **Expected reviewers** — the names that were due, engines included, and
|
||||
each engine recorded as not run with its reason. A name that did not report
|
||||
forbids `ALLOW` (Pass 4).
|
||||
|
|
@ -65,8 +76,7 @@ You will receive a prompt containing:
|
|||
(reasonableness filter) except the brief-conflict rule, which applies in every mode;
|
||||
Passes 1, 2, 4 still run.
|
||||
- **Rule catalogue** — `lib/review/rule-catalogue.mjs`. Findings whose
|
||||
`rule_key` is not in this set are routed to `unverified` by Pass 3
|
||||
(`unknown-rule_key`).
|
||||
`rule_key` is not in this set are dropped by Pass 3.
|
||||
|
||||
## Your 4-pass process
|
||||
|
||||
|
|
@ -77,16 +87,7 @@ re-reading, and fresh finding generation are all forbidden.
|
|||
### Pass 1 — Dedup by `(file, line, rule_key)` triplet
|
||||
|
||||
Two findings collide when their `(file, line, rule_key)` triplets are
|
||||
identical, with one exception: **one reviewer never duplicates itself.** Two
|
||||
findings from the same reviewer on one triplet under different titles are two
|
||||
findings (an engine's catch-all `rule_key` makes this common): keep both rows.
|
||||
Group in two passes, so the order the findings arrive in never changes a row:
|
||||
first every finding joins the row of its title (case and outer spaces
|
||||
ignored), over all of the triplet's findings; then each title row, in
|
||||
alphabetical order of its title, joins the first row that holds no finding of
|
||||
one of its reviewers under another title, else it stays a row of its own. A
|
||||
finding without a title joins the first row it fits, last. When findings
|
||||
collide:
|
||||
identical. When findings collide:
|
||||
- Rank the colliding findings and keep the first:
|
||||
1. the higher catalogue tier: the severity `lib/review/rule-catalogue.mjs`
|
||||
gives the `rule_key`, or the finding's own severity when the key is
|
||||
|
|
@ -98,10 +99,7 @@ collide:
|
|||
3. among findings of one kind, the higher asserted severity;
|
||||
4. among reviewer-agent findings, prefer the finding from
|
||||
`brief-conformance-reviewer` (its findings are anchored to the brief);
|
||||
5. then the first seen in the row's order: its title groups
|
||||
alphabetically, each title's findings in canonical order (reviewer,
|
||||
detail, the whole finding), findings without a title last in that
|
||||
order, never the order the findings arrived in.
|
||||
5. then the first seen.
|
||||
- Write the kept finding with the highest severity any finding in its
|
||||
group asserted, so dropping a duplicate never lowers the group and an
|
||||
engine's brief-conflict mark never lowers what a reviewer agent asserted.
|
||||
|
|
@ -122,7 +120,7 @@ is load-bearing** — see *Suppression is two-valued* below:
|
|||
| Filter | Test | Fails if | Removed as |
|
||||
|--------|------|----------|------------|
|
||||
| Succinctness | `title.length ≤ 100` and `detail.length ≤ 800` chars | Title is a paragraph or detail is a wall of text | **never removed.** MINOR/SUGGESTION (catalogue tier): the text is trimmed (ending `[…trimmed]`), the finding is kept and counted. BLOCKER/MAJOR: kept whole, every character. |
|
||||
| Accuracy | `file` resolves under the repo root AND `line` ≥ 0 | Path traversal escape or negative line | **dropped** (`accuracy:refuted`). A line past the end of the file (when its line count is known) is not refuted: the citation is wrong, the claim is unchecked → `unverified` (`accuracy:line-out-of-range`) |
|
||||
| Accuracy | `file` resolves under the repo root AND `line` is plausible (≥ 0; ≤ file line count when known) | Path traversal escape, negative line, or impossibly large line number | **dropped** (`accuracy:refuted`) |
|
||||
| Actionability | `recommended_action` is non-empty AND begins with an imperative verb | Empty action, "consider …" hedges, or restating the title | `unverified` (`actionability:empty`) |
|
||||
|
||||
A finding that carries `engine` (`code-review` / `security-review`) came
|
||||
|
|
@ -134,11 +132,8 @@ voyage-lekerepo trial, 2026-10-06.)
|
|||
|
||||
Succinctness and Actionability read the finding's *packaging*; neither
|
||||
examines the claim, so neither can establish the finding is unreal. Accuracy
|
||||
does: a citation that escapes the repo root, or a negative line, refutes the
|
||||
finding as a claim about this codebase. A line past the end of the file does
|
||||
not: the citation is wrong, the claim is unchecked. Any other line number alone
|
||||
never refutes the finding, so a line past the end of the file sends it to
|
||||
`unverified` (`accuracy:line-out-of-range`).
|
||||
does: a citation that escapes the repo root refutes the finding as a claim
|
||||
about this codebase.
|
||||
|
||||
**No finding is struck for length** (ordre 5). Before review_version 1.1 an
|
||||
over-long `detail` sent a finding to `unverified`, and S118's most serious
|
||||
|
|
@ -327,10 +322,7 @@ the parser reads; a bare `findings:` is null and fails validation.
|
|||
withheld `ALLOW`.
|
||||
9. `## Declined to Judge` — REQUIRED. One line per finding you set aside
|
||||
without ruling on it (every `[unverified]` one, and every
|
||||
out-of-scope engine finding: `file:line rule_key — reason`), then every
|
||||
line a reviewer wrote under its own `### Declined to Judge`, copied as
|
||||
`{reviewer}: {line}` (they are not findings: they stay out of the JSON
|
||||
`declined_to_judge` array and do not change the verdict), then one line `Trimmed: N` (MINOR/SUGGESTION text cut, findings
|
||||
out-of-scope engine finding: `file:line rule_key — reason`), then one line `Trimmed: N` (MINOR/SUGGESTION text cut, findings
|
||||
kept). Write `None.` plus `Trimmed: 0` when empty. Borrowed: "Declined to
|
||||
judge … nothing you set aside is dropped silently" (Superpowers
|
||||
`skills/requesting-code-review/code-reviewer.md:43-48`, MIT).
|
||||
|
|
@ -436,9 +428,8 @@ for the ID list.
|
|||
where n is its 1-based position in the JSON block's `findings` array.
|
||||
`/trekreview` Phase 7 runs `lib/review/fill-finding-ids.mjs`, which
|
||||
replaces each placeholder with the id computed over `(file, line,
|
||||
rule_key)` (`lib/parsers/finding-id.mjs`; the k-th row on one triplet
|
||||
gets it over `rule_key#k`) and refuses a placeholder with no finding
|
||||
behind it.
|
||||
rule_key)` (`lib/parsers/finding-id.mjs`) and refuses a placeholder with
|
||||
no finding behind it.
|
||||
- **Suppressed findings are accountable.** When you remove a finding via
|
||||
Pass 2 or Pass 3, log it in `## Suppressed Findings` with the reason and
|
||||
its fate (`[dropped]` / `[unverified]`), and list every `[unverified]` one
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ name: review-orchestrator
|
|||
description: Reference document, not a spawnable capability — documents the /trekreview workflow that runs inline in main context (full rationale, CC-2.1.172 history, and phase map in body).
|
||||
model: opus
|
||||
color: red
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
tools: ["Read", "Glob", "Grep", "Write", "Edit", "Bash"]
|
||||
---
|
||||
|
||||
<!-- Phase mapping: orchestrator → command
|
||||
|
|
@ -54,8 +54,8 @@ You will receive a prompt containing:
|
|||
contract that bounds review scope.
|
||||
- **Mode** — `default`, `quick`, `validate`, or `dry-run`.
|
||||
- `default` — run the full pipeline.
|
||||
- `quick` — skip the coordinator's reasonableness filter except the
|
||||
brief-conflict rule; use single reviewer (code-correctness only) for faster turnaround.
|
||||
- `quick` — skip the coordinator's reasonableness filter; use single
|
||||
reviewer (code-correctness only) for faster turnaround.
|
||||
- `validate` — schema-only check on existing review.md, no LLM calls.
|
||||
- `dry-run` — print the discovered scope and triage map; skip writes.
|
||||
- **Since-ref** (optional) — explicit `--since <ref>` override for the SHA
|
||||
|
|
@ -72,12 +72,9 @@ Execute these phases in order. Do not skip phases.
|
|||
|
||||
### Phase 1 — Parse mode and validate input
|
||||
|
||||
Run the arg-parser via Bash, with the arguments as the one line inside the
|
||||
quoted heredoc (on stdin, never as shell words):
|
||||
Run the arg-parser via Bash:
|
||||
```
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview --stdin <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||
$ARGUMENTS
|
||||
VOYAGE_ARGS_EOF_7F3C9E
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview "$@"
|
||||
```
|
||||
|
||||
Pull the structured flags from its JSON output. Reject unknown flags. If
|
||||
|
|
@ -126,8 +123,8 @@ produces a treatment map:
|
|||
| Treatment | When |
|
||||
|-----------|------|
|
||||
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated-file marker present in first 3 lines |
|
||||
| `deep-review` | Default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**` |
|
||||
| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**` |
|
||||
| `deep-review` | Matches `auth/**`, `crypto/**`, `**/security/**`, `hooks/**` |
|
||||
| `summary-only` | Default treatment for everything else |
|
||||
|
||||
Hard refuse-with-suggestion gates (use AskUserQuestion):
|
||||
- > 100 files in the diff
|
||||
|
|
@ -188,19 +185,9 @@ The coordinator runs a 4-pass process:
|
|||
2. **HubSpot Judge filters** — Accuracy refutes; Actionability sets aside
|
||||
as unverified; Succinctness never removes a finding (only MINOR/SUGGESTION
|
||||
text is trimmed, and counted).
|
||||
3. **Cloudflare reasonableness** — drop a finding with no `file:line`
|
||||
citation (`no-citation`) or whose file is in neither the working tree nor
|
||||
the diff (`file-existence:refuted`); route one whose `rule_key` is not in
|
||||
`RULE_CATALOGUE` (`unknown-rule_key`) or whose file cannot be checked
|
||||
(`file-existence:indeterminate`) to `unverified`, which forbids `ALLOW`;
|
||||
reset a severity that does not match its catalogue tier.
|
||||
The one exception to the reset is the brief-conflict lowering: a
|
||||
`/code-review` finding marked `contradicts_brief`, at the MAJOR tier and
|
||||
at severity MAJOR, drops to MINOR with `brief_lowered_from: MAJOR`.
|
||||
Skipped at high effort, as in `quick` mode (below); at high effort an
|
||||
unknown `rule_key` is normalized to `PLAN_EXECUTE_DRIFT` instead
|
||||
(`agents/review-coordinator.md`, "High-effort normalization"); the
|
||||
brief-conflict rule still applies in every mode.
|
||||
3. **Cloudflare reasonableness** — drop speculative findings without a
|
||||
`file:line` citation; drop findings whose `rule_key` is not in
|
||||
`RULE_CATALOGUE`.
|
||||
4. **Compute verdict** — `BLOCK` if `BLOCKER ≥ 1`, `WARN` if `MAJOR ≥ 1`,
|
||||
else `ALLOW`.
|
||||
|
||||
|
|
@ -209,8 +196,8 @@ The coordinator's output is the full review.md content — frontmatter
|
|||
and `## Remediation Steps` with one numbered step per BLOCKER) + trailing
|
||||
JSON block — ready to write.
|
||||
|
||||
In `quick` mode, skip pass 3 (reasonableness filter), except the
|
||||
brief-conflict rule, which applies in every mode. Passes 1, 2, 4 still run.
|
||||
In `quick` mode, skip pass 3 (reasonableness filter). Passes 1, 2, 4
|
||||
still run.
|
||||
|
||||
### Phase 7 — Write review.md
|
||||
|
||||
|
|
|
|||
|
|
@ -6,19 +6,12 @@ description: |
|
|||
model: opus
|
||||
color: magenta
|
||||
tools: ["Read", "Glob", "Grep"]
|
||||
skills: ["voyage:reviewing-adversarially"]
|
||||
---
|
||||
|
||||
You are a scope alignment specialist. Your job is to ensure that an implementation
|
||||
plan does exactly what was asked — no more, no less. You compare the plan against
|
||||
the task statement and spec file to find mismatches.
|
||||
|
||||
The stance every Voyage reviewer shares (no praise, no finding without a
|
||||
source, no downgrade without a reason, saying what you read in full and what
|
||||
only as a summary, a Declined to Judge list, claims checked against evidence,
|
||||
the axes kept separate) is in the preloaded `reviewing-adversarially` skill.
|
||||
This file holds only your own role.
|
||||
|
||||
## Your analysis process
|
||||
|
||||
### 1. Requirements extraction
|
||||
|
|
@ -148,10 +141,6 @@ range.
|
|||
- Plan complexity: {low|medium|high}
|
||||
- Assessment: {proportional | over-engineered | under-specified}
|
||||
|
||||
### Declined to Judge
|
||||
- {requirement, step or claim} - {why it was not judged} - {what would settle it}
|
||||
(one line each; `None.` when you set nothing aside)
|
||||
|
||||
### Verdict
|
||||
- Scope creep items: N
|
||||
- Scope gaps: N
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ Extract from the plan:
|
|||
|
||||
**Manifest handling:**
|
||||
- If `plan_version: 1.7` or later AND any step is missing a Manifest block:
|
||||
STOP with error "Plan claims v1.7 but step N lacks Manifest.
|
||||
Re-run /trekplan." Do not attempt to synthesize.
|
||||
STOP with error "Plan claims v1.7 but step N lacks Manifest. Re-run
|
||||
planning-orchestrator." Do not attempt to synthesize.
|
||||
- If no `plan_version` marker is present: treat as legacy v1.6. Synthesize
|
||||
minimal manifests from `Files:` (expected_paths) and the Checkpoint commit
|
||||
message (commit_message_pattern escaped). Mark output session specs with
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
name: trekbrief
|
||||
description: Interactive interview that produces a task brief with explicit research plan. Feeds /trekresearch and /trekplan. Optionally orchestrates the full pipeline end-to-end.
|
||||
argument-hint: "[--quick] <task description> | --approve <project-dir | brief-file>"
|
||||
allowed-tools: Agent, Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion, Skill
|
||||
allowed-tools: Agent, Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion
|
||||
---
|
||||
|
||||
# Ultrabrief Local v2.1
|
||||
|
|
@ -40,25 +40,15 @@ Parse `$ARGUMENTS`:
|
|||
2. Otherwise: **mode = default**. Interview probes each section until the
|
||||
completeness gate (Phase 3) and brief-review gate (Phase 4) both pass.
|
||||
|
||||
3. `--gates` flag (autonomy control, may combine with any mode): `--gates`
|
||||
takes the next token as its value only when it is `true`, `false`,
|
||||
`closed` or `open` (strip both); any other next token is not its value
|
||||
(strip only the flag). Run the shim once to map the value, bare when
|
||||
there is no value:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state idle --event start --gates [value]
|
||||
```
|
||||
|
||||
`next_state: gates_on` sets `gates_mode = true`, `auto_running` sets it
|
||||
false, and nothing else reads the state. On exit 1 or no JSON (a broken
|
||||
shim; the four values cannot cause it), print the error in one line and
|
||||
map in prose instead: bare, `true`, `closed` → true; `false`, `open` →
|
||||
false. The run goes on either way. `gates_mode = true` adds one pause,
|
||||
before the auto chain starts (Phase 5); the chain does not pass
|
||||
`--gates` on to `/trekresearch` or `/trekplan`. Default
|
||||
`gates_mode = false` skips that pause. Strip the flag (and its value,
|
||||
when it has one) from `$ARGUMENTS` before further parsing.
|
||||
3. `--gates` flag (autonomy control, may combine with any mode): when
|
||||
present, set `gates_mode = true`. This re-enables approval pauses at
|
||||
every phase boundary in the downstream pipeline (research, plan,
|
||||
execute) and at every wave in the executor. Default `gates_mode = false`
|
||||
means auto mode runs continuously until the main-merge gate (which is
|
||||
the one boundary that ALWAYS pauses, regardless of `gates_mode`). Strip
|
||||
the flag from `$ARGUMENTS` before further parsing. The flag is consumed
|
||||
by the autonomy-gate state machine via the CLI shim:
|
||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
||||
|
||||
4. `--approve <project-dir | brief-file>`: set **mode = approve**. No
|
||||
interview, no drafting. Set `APPROVE_ARG` to the argument and resolve it:
|
||||
|
|
@ -169,15 +159,17 @@ Framing: {preserve | refine | replace | new-direction}
|
|||
## Phase 3 — Completeness loop
|
||||
|
||||
Phase 3 gathers the brief's content in **one question round**, sized by the
|
||||
task's **size class** (ceremony by size). Use `AskUserQuestion` for every question.
|
||||
task's **size class** (ceremony by size). Facts are looked up, never asked;
|
||||
then every question that can be answered now goes out at once, each with the
|
||||
recommended answer first. Use `AskUserQuestion` for every question.
|
||||
|
||||
**The interview form is the skill `voyage:interviewing`.** Call the Skill tool
|
||||
with `voyage:interviewing` before the first question and run the round in its
|
||||
form: facts looked up first, never asked; one round with the recommended answer
|
||||
first; what you can predict and what is over the budget written down; the stop
|
||||
rule. This phase holds only what is `/trekbrief`'s own: the size class and its
|
||||
budget (Step 3b), the fixed questions and where each answer lands in the brief
|
||||
(Step 3c).
|
||||
### Step 3a — Look up facts first
|
||||
|
||||
Never ask the operator a fact a helper can look up: which framework the repo
|
||||
uses, where a module lives, what the test command is, whether a file exists.
|
||||
Read the repo (Glob / Grep / Read, or a subagent for a wide search — never with
|
||||
the Agent tool's `name` parameter) and carry what you found into the round. The
|
||||
operator answers decisions and intent, not lookups.
|
||||
|
||||
### Step 3b — Ceremony by size (K1)
|
||||
|
||||
|
|
@ -204,23 +196,31 @@ Put the task in one of three size classes. In doubt, take the heaviest that fits
|
|||
|
||||
### Step 3c — The question round
|
||||
|
||||
The round runs in the form of `voyage:interviewing`. What `/trekbrief` adds:
|
||||
|
||||
1. **Candidates.** The coverage list is the question bank below (Intent, Goal,
|
||||
Success Criteria, Research Plan, Non-Goals, Constraints, Preferences, NFRs,
|
||||
Prior Attempts), plus three fixed questions every round carries: framing
|
||||
(Phase 2.5, first), the size class (Step 3b) and where the brief is stored
|
||||
(`artifact_store`, below).
|
||||
2. **The budget is the class budget** (table below). A `bounded` or
|
||||
`architectural` round is consecutive `AskUserQuestion` calls with no
|
||||
drafting in between.
|
||||
3. **Where the written-down answers land.** Predictions ("assumed, not
|
||||
asked") and the Deferred list, one line of why each, go into
|
||||
`## Open Questions / Assumptions`, where the operator sees them before
|
||||
approving; the Deferred list is also printed with the round.
|
||||
4. **Follow-ups by class.** A follow-up round is only for an answer that opens
|
||||
a branch you cannot predict (`small`: never; `bounded`: at most one).
|
||||
5. **Answers that decide nothing.** «høres bra ut», «gjør som du vil», "sounds
|
||||
2. **Drop what you can predict.** If the task description, the repo and the
|
||||
answers so far let you predict the answer, do not ask: write the prediction
|
||||
into `## Open Questions / Assumptions`, marked "assumed, not asked", where
|
||||
the operator sees it before approving.
|
||||
3. **Rank the rest by Impact × Uncertainty**: how much the plan changes with
|
||||
the answer, times how unsure you are of it. Ask the highest within the
|
||||
class budget. Everything over the budget goes on a **Deferred** list, one
|
||||
line of why each, printed with the round and written into
|
||||
`## Open Questions / Assumptions` — the budget never hides a gap.
|
||||
4. **One round.** All questions that can be answered now, in one
|
||||
`AskUserQuestion` call. The tool takes at most 4 questions per call, so a
|
||||
`bounded` or `architectural` round is consecutive calls with no drafting in
|
||||
between. Each question is a full sentence in plain words, says in one
|
||||
clause why it matters, and lists the **recommended answer first**, marked
|
||||
"(Recommended)", with the consequence of each option in its description.
|
||||
5. **Stop rule.** Stop asking as soon as you can predict the operator's
|
||||
next three answers; write those predictions down as assumptions instead. A
|
||||
follow-up round is only for an answer that opens a branch you cannot
|
||||
predict (`small`: never; `bounded`: at most one).
|
||||
6. **Answers that decide nothing.** «høres bra ut», «gjør som du vil», "sounds
|
||||
good", "whatever you think" and an empty reply are not a decision. Record
|
||||
the recommended answer as an assumption ("not confirmed — the answer was
|
||||
«…»"), never as the operator's choice.
|
||||
|
|
@ -251,9 +251,12 @@ names, never the text.
|
|||
one-way ratchet: obra/superpowers@8ca22db (MIT, © 2025 Jesse Vincent),
|
||||
skills/brainstorming. The class ladder: Kiro's docs (kiro.dev — Plan mode,
|
||||
Quick Spec, full spec; read 2026-10-06; an idea only, Kiro is a closed
|
||||
product). The answers that decide nothing (Step 3c, point 5):
|
||||
addyosmani/agent-skills@9d0c60d (MIT, © 2025 Addy Osmani), skills/interview-me.
|
||||
The interview form's own credits are in `voyage:interviewing`.
|
||||
product). The round, the recommended answer first and "never ask a fact":
|
||||
mattpocock/skills@c55ee46 (MIT), productivity/grilling. The budget,
|
||||
Impact × Uncertainty and the Deferred list: GitHub Spec Kit (MIT),
|
||||
templates/commands/clarify.md at 2e941fe. The stop rule and the answers that
|
||||
decide nothing: addyosmani/agent-skills@9d0c60d (MIT, © 2025 Addy Osmani),
|
||||
skills/interview-me.
|
||||
|
||||
### Internal state
|
||||
|
||||
|
|
@ -324,8 +327,7 @@ sentence with your recommended answer first.
|
|||
- _Follow-up_: "How would you recognize this is done when looking at
|
||||
the UI / API / codebase?"
|
||||
|
||||
**Success Criteria** (required): how a criterion is written so the review can
|
||||
run it is the skill `voyage:writing-criteria`; call it before proposing one.
|
||||
**Success Criteria** (required):
|
||||
- _Anchor_: "How do we verify it is actually done? List 2–4 concrete,
|
||||
testable conditions — commands to run, observations, or metrics."
|
||||
A command the review can run is one test-runner call (`npm test`,
|
||||
|
|
@ -620,8 +622,7 @@ Build the brief text from Phase 3 state by filling the template:
|
|||
- **Non-Goals:** from state, or "- None explicitly stated" bullet if empty.
|
||||
- **Constraints / Preferences / NFRs:** from state, or "Not discussed — no
|
||||
constraints assumed" note if empty.
|
||||
- **Success Criteria:** falsifiable commands/observations from state, each
|
||||
written in the form of `voyage:writing-criteria`.
|
||||
- **Success Criteria:** falsifiable commands/observations from state.
|
||||
- **Research Plan:** one `### Topic N: {title}` section per topic with the
|
||||
full structure from the template. If 0 topics: write the "No external
|
||||
research needed — user confirmed solid knowledge of all plan
|
||||
|
|
@ -663,9 +664,8 @@ Launch the `brief-reviewer` agent with the prompt below, then wait for its resul
|
|||
|
||||
> "Review this task brief for quality: `{PROJECT_DIR}/brief.md.draft`.
|
||||
> Check completeness, consistency, testability, scope clarity,
|
||||
> research-plan validity, and memory alignment. Judge the success criteria by
|
||||
> `voyage:writing-criteria` and review by `voyage:reviewing-adversarially`.
|
||||
> Report findings, verdict, and the required machine-readable JSON block.
|
||||
> research-plan validity, and memory alignment. Report findings, verdict, and
|
||||
> the required machine-readable JSON block.
|
||||
> Operator memory context (compare the brief's Intent/Goal and its declared
|
||||
> `framing:` value against these for EXPLICIT contradictions only):
|
||||
> {memory paths or excerpts, or "none supplied"}."
|
||||
|
|
@ -830,8 +830,7 @@ If the validator returns errors, report them to the user and offer to
|
|||
re-enter Phase 4 with the validator's hints in scope. If only warnings,
|
||||
note them in the final report — except `BRIEF_SC_NOT_RUNNABLE`: a success
|
||||
criterion whose command `/trekreview` will never run (the product's own
|
||||
binary, `jq`, `grep`, a pipe, or a command that stands after a flag or path
|
||||
in backticks). Name each one to the user in plain words and
|
||||
binary, `jq`, `grep`, a pipe). Name each one to the user in plain words and
|
||||
offer to rewrite it as a script under `tests/` that the criterion runs
|
||||
(`bash tests/<script>.sh` exits 0) before the brief is approved; if the user
|
||||
keeps it, it stays a criterion a human judges, and the report says so. The
|
||||
|
|
@ -841,11 +840,14 @@ sub-point) and `BRIEF_SC_BASH_NOT_PINNED` (the brief requires bash 3.2 but a
|
|||
criterion runs plain `bash`: offer `/bin/bash`).
|
||||
|
||||
**Build the operator-annotation HTML, then print the report.** After the
|
||||
brief is validated, run `scripts/annotate.mjs` to build the page where the
|
||||
operator writes their own notes. The loop that follows is the skill
|
||||
`voyage:annotating`: call it when the operator pastes the notes back (a
|
||||
Question is answered, not applied; after Phase 4h, a note on `## Intent` or
|
||||
`## Goal` makes the approval stale, and that is said before the edit).
|
||||
brief is validated, run `scripts/annotate.mjs` to produce a self-contained
|
||||
HTML file the operator opens in their browser. The HTML renders the brief
|
||||
with line numbers, lets the operator click any line to attach their own
|
||||
note (not Claude-generated suggestions — the operator drives every
|
||||
annotation), keeps a sidebar of all notes, persists state in localStorage,
|
||||
and exposes a "Copy Prompt" button that generates a single structured
|
||||
prompt with every note. The operator copies that prompt and pastes it
|
||||
back into Claude; Claude revises `brief.md` freehand from the notes.
|
||||
|
||||
```bash
|
||||
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{PROJECT_DIR}/brief.md" 2>&1)
|
||||
|
|
@ -874,9 +876,9 @@ To review and annotate this brief, open the HTML above in a browser:
|
|||
|
||||
Click any line to add YOUR OWN note. The sidebar collects every note,
|
||||
the "Copy Prompt" button gathers them into one structured prompt.
|
||||
Paste that prompt back into this chat: Claude answers each Question
|
||||
and revises brief.md from your Fix and Change notes. Annotations
|
||||
persist in your browser if you close the tab and reopen the same file.
|
||||
Paste that prompt back into this chat and Claude revises brief.md
|
||||
from your notes. Annotations persist in your browser if you close
|
||||
the tab and reopen the same file.
|
||||
────────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
|
|
@ -975,10 +977,7 @@ printed `stamped: true`, then stop and print the next step:
|
|||
|
||||
## Phase 5 — Auto-orchestration opt-in (if research_topics > 0)
|
||||
|
||||
**With research_topics = 0**, print the manual-path output below without the
|
||||
`/trekresearch` lines (Brief, then `/trekplan --project {PROJECT_DIR}`, then
|
||||
`/trekexecute --project {PROJECT_DIR}`), then run Phase 7 (`auto_result: manual`)
|
||||
and stop. Phase 6 is never entered without the operator's opt-in.
|
||||
**Skip this phase if research_topics = 0.** Proceed directly to Phase 6.
|
||||
|
||||
Ask the user via `AskUserQuestion`:
|
||||
|
||||
|
|
@ -1012,13 +1011,13 @@ Then:
|
|||
/trekexecute --project {PROJECT_DIR}
|
||||
```
|
||||
|
||||
Run Phase 7 (`auto_result: manual`), then stop. Do not continue to Phase 6.
|
||||
Stop. Do not continue to Phase 6.
|
||||
|
||||
### Auto path
|
||||
|
||||
**Auto requires an approved intent.** If Phase 4h ended "Leave unapproved",
|
||||
the auto chain would halt at `/trekplan` anyway — print the manual-path
|
||||
output instead, run Phase 7 (`auto_result: manual`) and stop.
|
||||
output instead and stop.
|
||||
|
||||
Set `auto_research: true` in the brief's frontmatter (edit the file).
|
||||
|
||||
|
|
@ -1027,18 +1026,18 @@ stamp — on both paths — so it is not emitted again here.
|
|||
|
||||
If `gates_mode == true`: pause here via `AskUserQuestion` —
|
||||
"Auto-mode confirmed. Proceed to research now? (yes/no)". If the user
|
||||
answers no, fall back to the manual path output, run Phase 7
|
||||
(`auto_result: cancelled`) and stop. Otherwise proceed to Phase 6.
|
||||
answers no, fall back to the manual path output and stop. Otherwise
|
||||
proceed to Phase 6.
|
||||
|
||||
If `gates_mode == false` (default in auto): proceed directly to Phase 6.
|
||||
The chain ends when `/trekplan` has written the plan (Step 6e); it never
|
||||
starts `/trekexecute`.
|
||||
The chain stops only at the main-merge gate (see `commands/trekexecute.md`
|
||||
Phase 8).
|
||||
|
||||
Proceed to Phase 6.
|
||||
|
||||
## Phase 6 — Auto research dispatch (auto path only)
|
||||
|
||||
**Runs only when user opted into auto mode, and only after Phase 4h approved the intent.**
|
||||
**Runs only when user opted into auto mode.**
|
||||
|
||||
### Step 6a — Confirm proceed
|
||||
|
||||
|
|
@ -1052,10 +1051,9 @@ Continue?"
|
|||
| Option | Action |
|
||||
|--------|--------|
|
||||
| **Continue — auto** | Proceed. |
|
||||
| **Cancel — do manual** | Revert to manual path (run Phase 7 with `auto_result: cancelled`, print commands, stop). |
|
||||
| **Cancel — do manual** | Revert to manual path (print commands, stop). |
|
||||
|
||||
If cancelled → fall back to manual path output, run Phase 7
|
||||
(`auto_result: cancelled`) and stop.
|
||||
If cancelled → fall back to manual path output and stop.
|
||||
|
||||
### Step 6b — Run research topics sequentially (inline)
|
||||
|
||||
|
|
@ -1092,8 +1090,7 @@ ls -1 {PROJECT_DIR}/research/*.md | wc -l
|
|||
```
|
||||
|
||||
Expected count: N. If any are missing, report and ask the user how to
|
||||
proceed (retry, skip missing topic, cancel). On cancel, run Phase 7
|
||||
(`auto_result: cancelled`) and stop.
|
||||
proceed (retry, skip missing topic, cancel).
|
||||
|
||||
Update brief frontmatter: `research_status: complete`.
|
||||
|
||||
|
|
@ -1107,12 +1104,11 @@ Invoke the planning command inline in this session:
|
|||
|
||||
The planning pipeline runs all phases (exploration, synthesis, review) in
|
||||
main context. Wait for the plan to be written to `{PROJECT_DIR}/plan.md`
|
||||
before continuing. If `/trekplan` stops before it writes the plan, report
|
||||
where it stopped, run Phase 7 (`auto_result: failed`) and stop.
|
||||
before continuing.
|
||||
|
||||
### Step 6e — Report completion
|
||||
|
||||
When /trekplan finishes, present:
|
||||
When the planning-orchestrator finishes, present:
|
||||
|
||||
```
|
||||
## Ultrabrief + Ultraresearch + Voyage Complete (auto mode)
|
||||
|
|
@ -1200,6 +1196,9 @@ Examples:
|
|||
VOYAGE_PROFILE=balanced /trekbrief
|
||||
```
|
||||
|
||||
Stats records emit `profile`, `phase_models`, and `profile_source` so operators
|
||||
can audit which profile drove which session.
|
||||
|
||||
## Hard rules
|
||||
|
||||
1. **Interactive only.** This command requires user input. There is no
|
||||
|
|
|
|||
|
|
@ -29,22 +29,9 @@ See **Handover 7** in `docs/HANDOVER-CONTRACTS.md` for the full schema.
|
|||
|
||||
## Phase 0 — `--help` handling
|
||||
|
||||
Parse `$ARGUMENTS` with the shared arg-parser. Run first, exactly like this:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekcontinue --stdin <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||
$ARGUMENTS
|
||||
VOYAGE_ARGS_EOF_7F3C9E
|
||||
```
|
||||
|
||||
The arguments reach the parser as the one line inside the quoted heredoc, on
|
||||
stdin, never as shell words. It prints the parse result as JSON. On exit 1,
|
||||
print its `errors` and stop. When it prints no JSON, say that the parser did
|
||||
not run and stop.
|
||||
|
||||
Read `flags` and `positional` from the JSON it prints. Dispatch the usage
|
||||
block ONLY when one of these two conditions equals exactly true (no substring
|
||||
search, no "contains" check):
|
||||
Parse `$ARGUMENTS` with `parseArgs($ARGUMENTS, 'trekcontinue')` from
|
||||
`lib/parsers/arg-parser.mjs`. Dispatch the usage block ONLY when one of these
|
||||
two conditions equals exactly true (no substring search, no "contains" check):
|
||||
|
||||
- `flags['--help'] === true`, OR
|
||||
- `positional[0] === '-h'` (single-dash short form — the parser keeps it as
|
||||
|
|
@ -88,7 +75,7 @@ Typical flow:
|
|||
|
||||
## Phase 0.5 — Cleanup mode dispatch
|
||||
|
||||
After the parser has printed its parse of `$ARGUMENTS`, check the parsed `flags`
|
||||
After `parseArgs` has resolved `$ARGUMENTS`, check the parsed `flags`
|
||||
object directly (NOT a string contains-check on raw `$ARGUMENTS` — that
|
||||
substring pattern was the root cause of Bug 1).
|
||||
|
||||
|
|
@ -187,28 +174,23 @@ locations; this phase refuses ambiguity before validating the state file.
|
|||
After resolving the project directory and state-file path, look for two
|
||||
`NEXT-SESSION-PROMPT.local.md` candidates:
|
||||
|
||||
a. `NEXT-SESSION-PROMPT.local.md` at the repo root (`git rev-parse --show-toplevel`) —
|
||||
operator-managed master file, written by the operator or an external producer, never by Voyage
|
||||
a. `<plugin-root>/NEXT-SESSION-PROMPT.local.md` — operator-managed master file
|
||||
b. `<project-dir>/NEXT-SESSION-PROMPT.local.md` — producer-written sibling
|
||||
|
||||
**If both exist:**
|
||||
|
||||
- Read both via the **Read tool** (NOT Bash — same anti-substitution rule
|
||||
as Phase 2).
|
||||
- Invoke the consistency validator with the paths emitted as concrete
|
||||
literal tokens (no template substitution at the Bash boundary). When the
|
||||
project's `.session-state.local.json` exists, pass it with `--state-file`
|
||||
(else run the same line without the option):
|
||||
- Invoke the consistency validator with both paths emitted as concrete
|
||||
literal tokens (no template substitution at the Bash boundary):
|
||||
|
||||
```
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/validators/next-session-prompt-validator.mjs --json --consistency <RESOLVED-PATH-A> <RESOLVED-PATH-B> --state-file <RESOLVED-PATH-STATE>
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/validators/next-session-prompt-validator.mjs --json --consistency <RESOLVED-PATH-A> <RESOLVED-PATH-B>
|
||||
```
|
||||
|
||||
Replace `<RESOLVED-PATH-A>` and `<RESOLVED-PATH-B>` with the two concrete
|
||||
filesystem paths you have in your working context, and
|
||||
`<RESOLVED-PATH-STATE>` with the concrete path of the project's
|
||||
`.session-state.local.json`. The validator emits `{valid, errors, warnings}`
|
||||
JSON on stdout.
|
||||
filesystem paths you have in your working context. The validator emits
|
||||
`{valid, errors, warnings}` JSON on stdout.
|
||||
|
||||
- **If `valid: false`** (typically `NEXT_SESSION_PROMPT_PRODUCER_MISMATCH`):
|
||||
print the structured `errors[]` (each `[code] message` on its own line),
|
||||
|
|
@ -346,6 +328,8 @@ Examples:
|
|||
VOYAGE_PROFILE=economy /trekcontinue # env-var override
|
||||
```
|
||||
|
||||
Stats records emit `profile` and `profile_source` per Phase 5 record.
|
||||
|
||||
## Hard rules
|
||||
|
||||
- **Idempotent.** Running `/trekcontinue` twice in the same Claude session
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
name: trekendsession
|
||||
description: Mark the current session as complete and write session-state pointing at the next session. Helper for informal multi-session flows.
|
||||
argument-hint: "<next-brief-path> <next-label> | --help"
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Voyage End-Session Local v1.0
|
||||
|
|
@ -30,32 +29,8 @@ See **Handover 7** in `docs/HANDOVER-CONTRACTS.md` for the schema.
|
|||
|
||||
## Phase 0 — `--help` handling
|
||||
|
||||
Parse `$ARGUMENTS` with the arg parser. Run this via the Bash tool at runtime
|
||||
(NOT eager-exec), exactly as written: the arguments reach the parser as the one
|
||||
line inside the quoted heredoc, on stdin, never as shell words:
|
||||
|
||||
```bash
|
||||
setopt nonomatch 2>/dev/null || true
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekendsession --stdin <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||
$ARGUMENTS
|
||||
VOYAGE_ARGS_EOF_7F3C9E
|
||||
```
|
||||
|
||||
The `setopt nonomatch` line is no longer needed for the arguments (the quoted
|
||||
heredoc expands no glob); it stays harmless.
|
||||
|
||||
It prints the parse result as JSON. On exit 1, print its `errors` and stop.
|
||||
When it prints no JSON, say that the parser did not run and stop.
|
||||
|
||||
Print the usage block below and exit cleanly ONLY when one of these two
|
||||
conditions equals exactly true (no substring search, no "contains" check):
|
||||
|
||||
- `flags['--help'] === true`, OR
|
||||
- `positional[0] === '-h'` (single-dash short form — the parser keeps it as
|
||||
positional because the schema declares no alias).
|
||||
|
||||
Then do NOT proceed to any further phase. In every other case — a slug or a
|
||||
label that holds `-h` or `help` too — go on to Phase 1.
|
||||
If `$ARGUMENTS` contains `--help` or `-h`, print the usage block below and exit
|
||||
cleanly. Do NOT proceed to any further phase.
|
||||
|
||||
```
|
||||
/trekendsession — Mark current session done; point at next session.
|
||||
|
|
@ -101,10 +76,8 @@ Decision tree:
|
|||
|
||||
## Phase 2 — Required args check (headless-safe)
|
||||
|
||||
Read the parse result from Phase 0: `<next-brief-path>` is `positional[0]`
|
||||
and `<next-label>` is the parser's `tail` (the rest of the text as typed after
|
||||
the brief path, one outer quote pair removed, so a label with spaces stays
|
||||
whole). Both are required. If either is missing or empty:
|
||||
Read `$ARGUMENTS`. Both `<next-brief-path>` and `<next-label>` are required.
|
||||
If either is missing or empty:
|
||||
|
||||
```
|
||||
Error: missing required args.
|
||||
|
|
@ -135,41 +108,29 @@ to avoid partial-state on crash. The util is ESM, so invoke via
|
|||
`node --input-type=module -e` with an `import` statement (a CommonJS shim
|
||||
would throw `ERR_REQUIRE_ESM` on Node 18+ since `atomic-write.mjs` is ESM).
|
||||
|
||||
Under `node --input-type=module -e "<script>" arg1 arg2 arg3`, Node sets
|
||||
`process.argv[0]` to the node binary path and user args start at
|
||||
`process.argv[1]`. Adjust the destructure if your Node version differs.
|
||||
|
||||
This phase ALSO writes a sibling `NEXT-SESSION-PROMPT.local.md` in the
|
||||
project directory with YAML frontmatter (`produced_by: trekendsession`,
|
||||
`produced_at: {ISO-8601}`, `project: {project_dir}`). Both files are written
|
||||
in a single ESM block so the writes succeed or fail together.
|
||||
|
||||
Run the block below via the Bash tool at runtime, exactly as written: put no
|
||||
value from Phase 1 or Phase 2 into it. This is NOT an eager-exec block — the
|
||||
files do not exist at command-load time. The block takes nothing on its shell
|
||||
line: it re-reads the arguments as the one line inside the quoted heredoc, on
|
||||
stdin, never as shell words (the heredoc is the last thing in the command),
|
||||
parses them with the same `parseArgs` as Phase 0 (the brief path is
|
||||
`positional[0]`, the label is `tail`), and re-derives the project directory by
|
||||
Phase 1's enumeration: exactly one `.claude/projects/<dir>/brief.md` under the
|
||||
cwd, else it prints why and exits 1. The import paths must stay absolute via
|
||||
`${CLAUDE_PLUGIN_ROOT}` — your Bash cwd is the user's repo, not the plugin
|
||||
root, so a cwd-relative import throws `ERR_MODULE_NOT_FOUND`:
|
||||
Run the block below via the Bash tool at runtime, substituting the resolved
|
||||
values for the `{curly}` placeholders (Phase 1 gives `{project_dir}`, Phase 2
|
||||
gives `{next_brief_path}` and `{next_label}`). This is NOT an eager-exec
|
||||
block — the values do not exist at command-load time. The import path must
|
||||
stay absolute via `${CLAUDE_PLUGIN_ROOT}` — your Bash cwd is the user's
|
||||
repo, not the plugin root, so a cwd-relative import throws
|
||||
`ERR_MODULE_NOT_FOUND`:
|
||||
|
||||
```bash
|
||||
node --input-type=module -e "
|
||||
import path from 'node:path';
|
||||
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { writeFileSync } from 'node:fs';
|
||||
import { atomicWriteJson } from '${CLAUDE_PLUGIN_ROOT}/lib/util/atomic-write.mjs';
|
||||
import { parseArgs } from '${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs';
|
||||
let text = readFileSync(0, 'utf8');
|
||||
if (text.endsWith('\\n')) text = text.slice(0, -1);
|
||||
if (text.endsWith('\\r')) text = text.slice(0, -1);
|
||||
const args = parseArgs(text, 'trekendsession');
|
||||
const brief = args.positional[0] || '';
|
||||
const label = args.tail;
|
||||
if (brief === '' || label === '') { console.error('Error: missing required args.'); process.exit(1); }
|
||||
const root = '.claude/projects';
|
||||
const found = existsSync(root) ? readdirSync(root).filter((d) => existsSync(path.join(root, d, 'brief.md'))).map((d) => path.join(root, d)) : [];
|
||||
if (found.length === 0) { console.error('no .claude/projects/ directory with a brief.md found under cwd; cannot determine project directory'); process.exit(1); }
|
||||
if (found.length > 1) { console.error('more than one project directory holds a brief.md; cd into the intended one and retry:\\n' + found.join('\\n')); process.exit(1); }
|
||||
const dir = found[0];
|
||||
const [, dir, brief, label] = process.argv;
|
||||
const now = new Date().toISOString();
|
||||
const stateObj = { schema_version: 1, project: dir, next_session_brief_path: brief, next_session_label: label, status: 'in_progress', updated_at: now };
|
||||
const stateFile = path.join(dir, '.session-state.local.json');
|
||||
|
|
@ -179,9 +140,7 @@ const promptBody = '---\\nproduced_by: trekendsession\\nproduced_at: ' + now + '
|
|||
writeFileSync(promptFile, promptBody);
|
||||
console.log(stateFile);
|
||||
console.log(promptFile);
|
||||
" <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||
$ARGUMENTS
|
||||
VOYAGE_ARGS_EOF_7F3C9E
|
||||
" '{project_dir}' '{next_brief_path}' '{next_label}'
|
||||
```
|
||||
|
||||
## Phase 4 — Validate + narrate
|
||||
|
|
@ -217,7 +176,6 @@ before retrying — usually means a bad path or label argument.
|
|||
- **Atomic write only.** Tmp + rename — no partial state files on disk.
|
||||
- **Zero secrets.** Status, paths, labels — never API keys, never user content
|
||||
beyond filenames.
|
||||
- **NEVER auto-invoke this command.** It is operator-typed only at session-end
|
||||
(the frontmatter field keeps the model from starting it; the operator types it).
|
||||
- **NEVER auto-invoke this command.** It is operator-typed only at session-end.
|
||||
- **Idempotent within a session.** Running twice with the same args
|
||||
overwrites cleanly (atomic rename); does not double-advance.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: trekexecute
|
||||
description: Disciplined plan executor — single-session, or multi-session through session orders the user starts, with failure recovery
|
||||
argument-hint: "[--project <dir>] [--profile <name>] [--gates [true|false|closed|open]] [--fg | --resume | --dry-run | --validate | --step N | --session N] [plan.md]"
|
||||
argument-hint: "[--project <dir>] [--fg | --resume | --dry-run | --validate | --step N | --session N] [plan.md]"
|
||||
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent, Skill
|
||||
disallowed-tools: TeamCreate
|
||||
---
|
||||
|
|
@ -48,22 +48,6 @@ Parse `$ARGUMENTS` for mode flags:
|
|||
use that path but keep `project_dir` set (user may be pointing at a
|
||||
recovery session spec inside the project).
|
||||
- Continue parsing remaining flags (they combine with `--project`).
|
||||
- Brief check, once every flag below is parsed: when `{dir}/brief.md`
|
||||
exists, run the two lines `/trekplan` runs on it (its Phase 1), for the
|
||||
execute phase; append `--profile {profile}` when the operator passed
|
||||
`--profile`:
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/validators/brief-validator.mjs --soft --json "{dir}/brief.md"
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/profiles/resolver.mjs --resolve-phase-model --phase execute --brief-path "{dir}/brief.md" [--profile {profile}] --json
|
||||
```
|
||||
The validator exits 1 when its `errors` are not empty; read its JSON
|
||||
either way. Halt only when the validator's `errors` hold
|
||||
`BRIEF_V51_MISSING_SIGNALS`, with the message from "Sequencing gate
|
||||
surface" below. Any other error is printed in one line and the run
|
||||
continues. A validator or resolver that cannot run (no JSON) is "not
|
||||
measured" in one line, and the run continues. Capture the resolver's
|
||||
JSON as `phase_signal_result` (Composition rule below). No
|
||||
`{dir}/brief.md`: skip both lines.
|
||||
2. If arguments contain `--fg`: extract the file path. Set **mode = foreground**.
|
||||
3. If arguments contain `--resume`: extract the file path. Set **mode = resume**.
|
||||
4. If arguments contain `--dry-run`: extract the file path. Set **mode = dry-run**.
|
||||
|
|
@ -72,22 +56,10 @@ Parse `$ARGUMENTS` for mode flags:
|
|||
Set **mode = step**, **target-step = N**.
|
||||
7. If arguments contain `--session N` (N is a positive integer): extract N and the file path.
|
||||
Set **mode = session**, **target-session = N**.
|
||||
8. If arguments contain `--gates`: `--gates` takes the next token as its
|
||||
value only when it is `true`, `false`, `closed` or `open` (strip both);
|
||||
any other next token is not its value (strip only the flag). Run the shim
|
||||
once to map the value, bare when there is no value:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state idle --event start --gates [value]
|
||||
```
|
||||
|
||||
`next_state: gates_on` sets `gates_mode = true`, `auto_running` sets it
|
||||
false, and nothing else reads the state. On exit 1 or no JSON (a broken
|
||||
shim; the four values cannot cause it), print the error in one line and
|
||||
map in prose instead: bare, `true`, `closed` → true; `false`, `open` →
|
||||
false. The run goes on either way. Default `gates_mode = false`.
|
||||
`gates_mode` changes nothing in `/trekexecute`: no phase of it pauses on
|
||||
it. The one stop is the merge into main, which always asks (Phase 8).
|
||||
8. If arguments contain `--gates`: set `gates_mode = true`. Default
|
||||
`gates_mode = false`. The flag is consumed by the autonomy-gate state
|
||||
machine via the CLI shim:
|
||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
||||
It no longer adds a question of the executor's own before a merge. The
|
||||
wave merge-back (Phase 2.6 Step 3) and the merge into main (Phase 8) are
|
||||
asked by the guard, which asks before every merge into main and every push,
|
||||
|
|
@ -95,9 +67,7 @@ Parse `$ARGUMENTS` for mode flags:
|
|||
(operator decision 2026-10-08: two questions for one merge became one). The
|
||||
MAIN_MERGE_GATE in Phase 8 is always on, regardless of `gates_mode`: it is
|
||||
a lock, and the guard's question is the one question.
|
||||
9. If arguments contain `--profile <name>`: set `profile = {name}`; strip both tokens.
|
||||
10. Otherwise: the arguments left after every flag above is stripped are the file path.
|
||||
Set **mode = execute**.
|
||||
9. Otherwise: the entire argument string is the file path. Set **mode = execute**.
|
||||
|
||||
If no path is provided (and `--project` was not used to derive one), output
|
||||
usage and stop:
|
||||
|
|
@ -111,7 +81,6 @@ Usage: /trekexecute <plan.md>
|
|||
/trekexecute --validate <plan.md>
|
||||
/trekexecute --step N <plan.md>
|
||||
/trekexecute --session N <plan.md>
|
||||
/trekexecute --profile <name> <plan.md>
|
||||
/trekexecute --project <dir> --resume
|
||||
/trekexecute --project <dir> --session N
|
||||
|
||||
|
|
@ -125,8 +94,6 @@ Modes:
|
|||
--validate Schema-only check — parse steps + manifests, no security scan, no execution
|
||||
--step N Execute only step N (foreground)
|
||||
--session N Execute only session N from the plan's Execution Strategy
|
||||
--profile Profile for this run's resolver; the step helper and the controller stay on opus
|
||||
--gates Accepted, pauses on nothing: bare, true or closed = on; false or open = off
|
||||
|
||||
Examples:
|
||||
/trekexecute .claude/plans/trekplan-2026-04-06-auth-refactor.md
|
||||
|
|
@ -269,7 +236,7 @@ mode; absence or <1.7 as legacy mode.
|
|||
- If any step is missing its Manifest, or YAML is malformed, STOP with:
|
||||
```
|
||||
Error: plan_version=1.7 but step {N} has invalid/missing Manifest.
|
||||
Re-run /trekplan — the plan is not executable.
|
||||
Re-run planning-orchestrator — plan is not executable.
|
||||
```
|
||||
|
||||
**Legacy mode (no plan_version, or < 1.7):**
|
||||
|
|
@ -367,11 +334,11 @@ Reason: {specific error from Phase 2}
|
|||
{if format not recognized}:
|
||||
Detected heading format: {e.g. "### Fase 1:", "## Phase 1"}
|
||||
Expected: "### Step N: <description>"
|
||||
Fix: re-run /trekplan — the plan must use v1.7 format
|
||||
Fix: re-run /trekplan — planning-orchestrator must emit v1.7 format
|
||||
|
||||
{if missing manifest}:
|
||||
Step {N} has no Manifest block (plan_version=1.7 requires one per step)
|
||||
Fix: re-run /trekplan — every step needs a Manifest YAML block
|
||||
Fix: re-run /trekplan — planning-orchestrator must include manifest YAML
|
||||
|
||||
{if malformed YAML or invalid regex}:
|
||||
Step {N}: {specific YAML/regex error}
|
||||
|
|
@ -465,7 +432,6 @@ Determine how to execute this plan:
|
|||
- `--step N` mode
|
||||
- `--resume` mode
|
||||
- `--session N` mode (runs only that session's steps, foreground)
|
||||
- `phase_signal_result.effort == 'low'` → one session, steps in order, unless a wave is in flight: when `.claude/trekplan-sessions/{slug}/orders/wave.json` exists in the main checkout (the first entry of `git worktree list`), this bullet does not apply and the multi-session path below collects the wave. The check only reads the file and never stops the run.
|
||||
- Plan has no `## Execution Strategy` section
|
||||
- Plan has Execution Strategy with only 1 session
|
||||
|
||||
|
|
@ -616,8 +582,9 @@ These sessions cannot safely run in parallel.
|
|||
Fix the Execution Strategy in the plan, or use --fg for sequential execution.
|
||||
```
|
||||
|
||||
Stop execution. This check runs at execution time, so it also catches a plan
|
||||
that was edited by hand after planning.
|
||||
Stop execution. This is a defense-in-depth check — the planning-orchestrator
|
||||
should have prevented this, but verifying at execution time catches plans
|
||||
that were manually edited or have bugs.
|
||||
|
||||
### Check 4 — Stale worktree cleanup
|
||||
|
||||
|
|
@ -1184,7 +1151,6 @@ progress file.
|
|||
"exit_condition_checked": false,
|
||||
"plan_verification": null,
|
||||
"end_to_end": null,
|
||||
"run_seen": null,
|
||||
"arch_rules": null,
|
||||
"scope_sweep": null,
|
||||
"simplify": null,
|
||||
|
|
@ -1207,7 +1173,6 @@ a progress file without them still validates and resumes:
|
|||
| `steps.{N}.fix_rounds` | Sub-step F | 0–5: 0 = passed its first control, 1–3 = fix rounds, 4 = sent up to the plan, 5 = sent up to the operator |
|
||||
| `steps.{N}.attempts` | Sub-steps C, F | helpers launched for the step: 1 + the fix rounds that launched one |
|
||||
| `end_to_end` | Phase 7 | `"verified" \| "not-verified"` (P9 (6)) |
|
||||
| `run_seen` | Phase 7 | `"yes" \| "no — {reason}"` — what Claude Code's built-in `run` showed in this run; `null` = not run (Phase 7 not reached) |
|
||||
| `decisions` | any phase | `[{step, decision, cost_if_wrong}]` — every call the executor made on its own (Phase 5.5) |
|
||||
|
||||
`progress-validator.mjs` rejects `fix_rounds` outside 0–5 (there is no sixth
|
||||
|
|
@ -1310,7 +1275,7 @@ but do not block.
|
|||
**Also write sibling `NEXT-SESSION-PROMPT.local.md`** with frontmatter
|
||||
(`produced_by: trekexecute`, `produced_at: <ISO-8601>`,
|
||||
`status: stopped`) — same combined ESM pattern as Phase 8 — so Phase 1.5
|
||||
of `/trekcontinue` can compare project-dir and repo-root candidates.
|
||||
of `/trekcontinue` can compare project-dir and plugin-root candidates.
|
||||
|
||||
If the entry condition **passes**:
|
||||
```
|
||||
|
|
@ -1557,21 +1522,7 @@ and the skill to work by: `skill: test-first` for a build round,
|
|||
|
||||
**A step at `fix_rounds` 5 is never built again** (Sub-step F): skip the
|
||||
launch and run only the checks (B, D1, D2, D3, D4, E) on whatever the operator
|
||||
changed. A step at `fix_rounds` 4 on `--resume` was re-planned: first park
|
||||
the earlier attempt's new files, which the revert left on disk untracked, so a
|
||||
stale file can never pass the revised step's checks (voyage-lekerepo trial 5,
|
||||
finding 4):
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/util/park-attempt-files.mjs --diff {report dir}/step-{N}-upward.diff --step {N} --attempt {attempts}
|
||||
```
|
||||
It moves every file new in the attempt's diff that is untracked, or staged but not in HEAD, to the git
|
||||
dir (`voyage/parked/step-{N}-attempt-{attempts}/`, outside the work tree, so
|
||||
Sub-step C.2 never registers it again): moved, never deleted, never over a file
|
||||
already parked. Name the `parked` paths and every `kept` path with its reason
|
||||
in the step report. Exit 1 means a file the attempt made is still in the tree
|
||||
(a header it could not read, a move that failed): stop and name it; exit 2 is
|
||||
a stop too, nothing unindexed or moved (HEAD could not be read, a path in HEAD
|
||||
is missing from the index, or another git call failed). Then launch a fresh
|
||||
changed. A step at `fix_rounds` 4 on `--resume` was re-planned: launch a fresh
|
||||
`build` helper for the revised step.
|
||||
|
||||
- **Never pass the Agent tool's `name` parameter.** A named spawn becomes an
|
||||
|
|
@ -1888,7 +1839,7 @@ session's effort, Sub-step E).
|
|||
| 4 | the plan | **After three failed fix rounds the question is the architecture, not a fourth fix.** The step goes back to planning (below). Sub-step B sends three answers here directly, with no fix round: a `"not-run"` caused by the `Verify:` command, a second `plan-unreadable` (the executor's own call still wrong after one correction), and a `not-red-at-base` with `tests_only: true` (a step of only tests). Stop class 4 |
|
||||
| 5 | the operator | A step already sent to the plan (`fix_rounds` 4) that fails its control again after re-planning goes to the operator. The executor never builds this step again: on a later `--resume` it only runs the checks (B, D1, D2, D3, D4, E) on whatever the operator changed. If they fail again the step stays at 5 — there is no sixth round, `fix_rounds` never exceeds 5 — and the run stops again. Stop class 4 |
|
||||
|
||||
**Back to planning** (`fix_rounds = 4`): save `git -c core.quotepath=off diff --no-ext-diff --no-color --no-renames --no-relative --src-prefix=a/ --dst-prefix=b/ {start_sha}` (one form whatever the user's git config) to
|
||||
**Back to planning** (`fix_rounds = 4`): save `git diff {start_sha}` to
|
||||
`{report dir}/step-{N}-upward.diff` and write `{report dir}/step-{N}-upward.md`:
|
||||
the step verbatim, every round's findings and verdicts, and the question for
|
||||
the planner — which assumption in the step (its Changes, its Interface, its
|
||||
|
|
@ -1911,9 +1862,7 @@ directly (Sub-step B), and so does a second `plan-unreadable` after one correcte
|
|||
git rm --cached -q -- {the step's new files: registered with --intent-to-add since start_sha}
|
||||
```
|
||||
The new files stay on disk, untracked, and `step-{N}-upward.md` names them —
|
||||
nothing the step made is deleted, and none of it is left registered. A
|
||||
`--resume` after re-planning parks them in the git dir before the fresh
|
||||
build (Sub-step C).
|
||||
nothing the step made is deleted, and none of it is left registered.
|
||||
When the guard refuses the restore (it is destructive git: in the permission
|
||||
mode that shows no prompts the guard refuses it, exit 2, "no one to ask"), or
|
||||
the operator declines it, nothing was restored: write in `step-{N}-upward.md`
|
||||
|
|
@ -1957,10 +1906,6 @@ or 5). Release the step's test lock before stopping
|
|||
command exactly as written in the plan. (The test files are listed apart
|
||||
from `Files:` in the plan; staging only `Files:` would leave the step's
|
||||
test uncommitted and charge it to the next step's diff.)
|
||||
`{hash}` is the full commit id: run `git rev-parse HEAD` after the step's
|
||||
last commit, never the short id `git commit` prints. Read it again after
|
||||
any later commit of the step (the second commit on the exit-1 path); when
|
||||
the commit failed, it is the HEAD the done line names.
|
||||
If the commit fails (nothing to commit, etc.): warn but do NOT fail the
|
||||
step. The step's verification already passed — the commit is bookkeeping.
|
||||
2. **The done line**, at the step's own commit. A step is done only when a
|
||||
|
|
@ -1999,7 +1944,7 @@ already passed) but is recorded as `checkpoint_drift: {expected_pattern,
|
|||
actual_message}` in the progress file. Phase 7.5 audit reports drift as
|
||||
an advisory.
|
||||
|
||||
Update progress: `steps.{N}.status = "completed"`, `steps.{N}.commit = {hash}` (the full commit id),
|
||||
Update progress: `steps.{N}.status = "completed"`, `steps.{N}.commit = {hash}`,
|
||||
`steps.{N}.completed_at = now`, `steps.{N}.manifest_audit = "pass"`.
|
||||
|
||||
### Step mode exit
|
||||
|
|
@ -2127,9 +2072,7 @@ verification failure must not hide a manifest drift.
|
|||
|
||||
### End to end — "run the thing" (P9 (6))
|
||||
|
||||
Tests passing is not the product working. To see and drive the app, use
|
||||
Claude Code's built-in `run` skill; the verdict is still the `End-to-end:`
|
||||
command, because `run` gives no exit code. Copy `end_to_end.status` from the
|
||||
Tests passing is not the product working. Copy `end_to_end.status` from the
|
||||
runner's JSON into `end_to_end` — the runner decides it, not this prose:
|
||||
|
||||
- `"verified"` — the verification passed and at least one passed criterion
|
||||
|
|
@ -2146,12 +2089,6 @@ built thing — not in the run. (A ≥ 1.8 plan cannot reach here with its
|
|||
`End-to-end:` command missing from `## Verification`: the plan validator
|
||||
rejects that as `PLAN_END_TO_END_NOT_VERIFIED`.)
|
||||
|
||||
Record `run_seen`: `yes` when the app was seen and driven with Claude Code's
|
||||
built-in `run` in this run, else `no — {reason}` (no app to launch, `run` not
|
||||
available, not started, and why) in the progress file's top-level `run_seen`,
|
||||
so Phase 8 reads it from there. The verdict is still the `End-to-end:`
|
||||
command.
|
||||
|
||||
### Architecture rules (K5) and the plan-file sweep (K6)
|
||||
|
||||
Two whole-run checks, for a trekplan and a session spec alike, in one Bash
|
||||
|
|
@ -2271,26 +2208,18 @@ never typed by the operator, in this order (Cherny's):
|
|||
run — no project directory", and the merge stays closed (Phase 8).
|
||||
**Its writes are committed.** `/trekreview` may have written approved
|
||||
project-memory lines (`.claude/rules/voyage-review-lessons.md`) and a
|
||||
one-line pointer in `CLAUDE.md`. Commit only those of them that changed
|
||||
and git does not ignore (`git check-ignore -q -- {path}` exits 1; exit 0
|
||||
means ignored), as `docs(voyage): review lessons (round {R})`: a process
|
||||
commit (Phase 7.5 step 3). An ignored path is left uncommitted and named
|
||||
in the report; `/trekreview` wrote no pointer to an ignored lessons file
|
||||
(its `pointer` result is `"ignored-skipped"`), and none through a symlinked
|
||||
`CLAUDE.md` (`"symlink-skipped"`). Nothing the review wrote that git does not
|
||||
ignore is left uncommitted for the next round's checks or for the merge.
|
||||
one-line pointer in `CLAUDE.md`. Commit exactly those paths, when they
|
||||
changed, as `docs(voyage): review lessons (round {R})`: a process commit
|
||||
(Phase 7.5 step 3). Nothing the review wrote is left uncommitted for the
|
||||
next round's checks or for the merge.
|
||||
4. **`verdict-gate.mjs`** — the review's verdict decides, as a command:
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{project_dir}/review.md" --repo .
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{project_dir}/review.md"
|
||||
```
|
||||
`--repo .` checks that an ALLOW/WARN review is of the commit being merged:
|
||||
its `scope_sha_end` is HEAD, or an ancestor of HEAD whose later commits
|
||||
change only the review lessons and the `CLAUDE.md` pointer (step 3's
|
||||
commit). Record `review = {round, path, gate_exit, verdict}`. Exit 0
|
||||
(ALLOW/WARN) → Phase 7.5. Exit 2 (could not decide, a reviewer or engine
|
||||
that did not run, or a reason that starts `review-stale`: a review of
|
||||
another commit) → Phase 7.5 with the merge closed: never green. Exit 1
|
||||
(BLOCK) → the loop below.
|
||||
Record `review = {round, path, gate_exit, verdict}`. Exit 0 (ALLOW/WARN) →
|
||||
Phase 7.5. Exit 2 (could not decide, or a reviewer or engine that did not
|
||||
run) → Phase 7.5 with the merge closed: never green. Exit 1 (BLOCK) → the
|
||||
loop below.
|
||||
|
||||
**A BLOCK is fixed by new plan steps, in a bounded loop.** The review writes
|
||||
every BLOCKER as a numbered `### Step R<n>` under `## Remediation Steps`
|
||||
|
|
@ -2430,7 +2359,7 @@ Record in progress file:
|
|||
> 1. **Objective predicate** — the **Phase 7.5** manifest audit (above) PASSED,
|
||||
> re-verified directly from the filesystem + git log, ignoring the executor's
|
||||
> own per-step bookkeeping. "The audit wins"; a self-reported `completed` over
|
||||
> a drifting audit is OVERRIDDEN to `partial` (Phase 7.5).
|
||||
> a drifting audit is OVERRIDDEN to `partial` (Phase 7.5, `:1221`).
|
||||
> 2. **Explicit stop-signal** — a signal *distinct from the executor's
|
||||
> self-assessment* is satisfied: the plan's Verify command(s) **passed (exit
|
||||
> 0)** / lint clean / an explicit **DONE token emitted AFTER the Phase 7.5
|
||||
|
|
@ -2441,14 +2370,14 @@ Record in progress file:
|
|||
> from `lib/verification/criteria-runner.mjs`, on the single-session path as
|
||||
> well as the multi-session one. `"failed"` or `"not-run"` OVERRIDES
|
||||
> `completed` to `failed`, exactly as the audit-override does.
|
||||
> 3. **Counter liveness (checked by the executor against the audit's counts,
|
||||
> defeats "never decremented")** — the gate reconciles the budget counter
|
||||
> against the ground-truth counters the Phase 7.5 audit already derives:
|
||||
> 3. **Counter liveness (deterministic, defeats "never decremented")** — the gate
|
||||
> reconciles the budget counter against the ground-truth counters the Phase 7.5
|
||||
> audit already derives:
|
||||
> `iterations_remaining == TREKEXECUTE_MAX_RECOVERY_ITERATIONS − (recovery_depth + Σ steps.*.attempts-beyond-first + (review.round − 1))`
|
||||
> (the last term is 0 without a review; each review loop of Phase 7.2 takes 1).
|
||||
> A field left un-decremented (or tampered) fails this reconciliation and the
|
||||
> result is OVERRIDDEN `completed → partial`, exactly as the audit-override
|
||||
> already does (Phase 7.5). So the counter's liveness is auditable at the gate,
|
||||
> already does (`:1221`). So the counter's liveness is auditable at the gate,
|
||||
> not merely asserted in prose.
|
||||
> 4. **End to end** — for a trekplan, Phase 7's `end_to_end == "verified"`.
|
||||
> `"not-verified"` OVERRIDES `completed → partial` with the reason
|
||||
|
|
@ -2459,20 +2388,12 @@ Record in progress file:
|
|||
> the files outside the plan. `"not-measured"` does not override, and it is
|
||||
> never reported as a pass.
|
||||
>
|
||||
> **Commands:** Phase 7.5 step 3's `git rev-list --count`, step 5's `bash -n`,
|
||||
> step 6's `git diff --name-only` and step 7's `done-line.mjs --check`; the
|
||||
> criteria runner behind clauses 2 and 4 for a trekplan (a session spec's
|
||||
> clause 2 is Phase 7's `## Exit Condition` checklist, and clause 4 is a
|
||||
> trekplan's only); clause 5's `arch-rules.mjs` and `plan-scope-sweep.mjs`.
|
||||
> **Executor judgement:** steps 1, 2 and 4, the expected count in step 3, and
|
||||
> clause 3's formula. The judgement parts are not yet a script.
|
||||
>
|
||||
> The review verdict (Phase 7.2) is decided after this gate, by the lock in
|
||||
> Phase 8: in the closing run, a closed lock or a declined merge turns
|
||||
> `completed` into `partial`, as a declined gate always has.
|
||||
>
|
||||
> Termination authority therefore rests on the audit and an objective
|
||||
> stop-signal, never on the model's narrative. Native `/goal` (when
|
||||
> Termination authority therefore rests on the deterministic audit + an
|
||||
> objective stop-signal, never on the model's narrative. Native `/goal` (when
|
||||
> capability-probed and wired) is an OPTIONAL accelerator only: transcript-only,
|
||||
> it cannot run the real check, so it can never be the sole gate.
|
||||
|
||||
|
|
@ -2604,7 +2525,7 @@ event, merge nothing, and their result is left as Phase 7.5 decided it
|
|||
a summary:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{review_path}" --repo .
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{review_path}"
|
||||
```
|
||||
|
||||
`{review_path}` is `review.path` from Phase 7.2. No review (Phase 7.2 did not
|
||||
|
|
@ -2617,23 +2538,13 @@ exit 2 without the call.
|
|||
| 1 | BLOCK | closed |
|
||||
| 2 | not measured | closed: a review that could not decide is never green |
|
||||
|
||||
`--repo .` makes the gate check the review against the commit being merged.
|
||||
Exit 2 with a reason that starts `review-stale` is closed with the decline
|
||||
reason `review-stale` and the line "re-run /trekreview on this commit": the
|
||||
review is of another commit than this one, or something other than the
|
||||
review lessons and the `CLAUDE.md` pointer changed after it. Any other exit 2
|
||||
is `review-not-measured`. Exit 2 with a reason that starts `review-not-measured:`
|
||||
(the `--repo` path is missing, it is no git repository, or a git call failed)
|
||||
is reported as "not measured", never green, and the merge stays locked with
|
||||
the decline reason `review-not-measured`.
|
||||
|
||||
The merge runs only on exit 0 and a `completed` result. **Closed:** emit
|
||||
`main-merge-declined` with the reason `review-block`, `review-stale`,
|
||||
`review-not-measured` or `run-not-completed`. Nothing is finalized: a `completed` result becomes
|
||||
`main-merge-declined` with the reason `review-block`, `review-not-measured` or
|
||||
`run-not-completed`. Nothing is finalized: a `completed` result becomes
|
||||
`partial` (`failed` and `stopped` stay), and the commits stay where they are
|
||||
for review. Say in one line why it is closed and what opens it: the
|
||||
BLOCKERs fixed through Phase 7.2's loop, a review that runs in full, a review
|
||||
of this commit, or a run that completes.
|
||||
BLOCKERs fixed through Phase 7.2's loop, a review that runs in full, or a run
|
||||
that completes.
|
||||
|
||||
**2. Open: the merge, and the one question.** Find the run's branch and where
|
||||
main is checked out, in a Bash call of its own:
|
||||
|
|
@ -2737,7 +2648,7 @@ JSON
|
|||
```
|
||||
|
||||
The reason is one of the literal words above (`review-block`,
|
||||
`review-stale`, `review-not-measured`, `run-not-completed`, `no-main-branch`, `hold-for-review`,
|
||||
`review-not-measured`, `run-not-completed`, `no-main-branch`, `hold-for-review`,
|
||||
`merge-conflict`, `merge-refused`), never the operator's free text (free text breaks the JSON).
|
||||
|
||||
On decline, nothing is cleared: the merged-waves record is kept.
|
||||
|
|
@ -2745,9 +2656,8 @@ On decline, nothing is cleared: the merged-waves record is kept.
|
|||
**Recovery surface:** on the single-session path, if declined,
|
||||
`--resume re-enters at the gate` — re-running
|
||||
`/trekexecute --resume --project <dir>` skips the completed steps and returns
|
||||
to the main-merge gate: the lock reads the review again (a review fixed or re-run
|
||||
in between counts) and runs the same gate against this repo, so a review of
|
||||
an older commit stays refused; when it opens, the guard asks again. On the
|
||||
to the main-merge gate: the lock reads `review.md` again (a review fixed or
|
||||
re-run in between counts), and when it opens, the guard asks again. On the
|
||||
multi-session wave path,
|
||||
re-run the same `/trekexecute` command instead, not `--resume` (Phase 2.5 runs
|
||||
a `--resume` as a single session): the waves are already merged on the current
|
||||
|
|
@ -2788,7 +2698,7 @@ to stderr but do NOT block — Phase 8 must always reach the final report.
|
|||
contract — see `docs/HANDOVER-CONTRACTS.md` § Handover 7 Lifecycle) in the
|
||||
project directory. The frontmatter MUST contain `produced_by: trekexecute`
|
||||
and `produced_at: <ISO-8601>` so `/trekcontinue` Phase 1.5 can detect
|
||||
producer drift between project-dir and repo-root candidates. Use a single
|
||||
producer drift between project-dir and plugin-root candidates. Use a single
|
||||
ESM inline block so state-file + prompt-file writes succeed or fail together:
|
||||
|
||||
```bash
|
||||
|
|
@ -2820,12 +2730,6 @@ completion). Phase 2.55 and Phase 4 cover the early-stop paths E1/E2.
|
|||
Phase 2.3 (validate exit) and Phase 5 (dry-run) intentionally do not write
|
||||
— neither path is resumable.
|
||||
|
||||
The report's **Seen with `run`:** line and the summary's `run_seen` are read
|
||||
from the progress file's `run_seen` (Phase 7 writes it), not from this
|
||||
session's memory, so a resumed run (`--resume`) reports it too, and on the
|
||||
multi-session path (Phase 2.6) the report gives each session's value from its
|
||||
archived progress copy (Step 6). A `null` there is reported as `no — not run`.
|
||||
|
||||
```
|
||||
## Ultraexecute Local Complete
|
||||
|
||||
|
|
@ -2834,7 +2738,6 @@ archived progress copy (Step 6). A `null` there is reported as `no — not run`.
|
|||
**Mode:** {execute | resume | step N}
|
||||
**Result:** {COMPLETED | FAILED at step N | STOPPED (escalation) | PARTIAL (N/total passed)}
|
||||
**End to end:** {verified | not verified end to end}
|
||||
**Seen with `run`:** {yes | no — {reason}}
|
||||
|
||||
### Step Results
|
||||
|
||||
|
|
@ -2960,7 +2863,6 @@ To continue (multi-session waves): re-run the same /trekexecute command (not --r
|
|||
"legacy_plan": false,
|
||||
"progress_file": "{path}",
|
||||
"end_to_end": "{verified | not-verified | n/a}",
|
||||
"run_seen": "{yes | no — reason}",
|
||||
"steps_without_red_proof": 0,
|
||||
"stop_class": "{none | 1 | 2 | 3 | 4}",
|
||||
"decisions": 0,
|
||||
|
|
@ -3028,8 +2930,8 @@ Resolution order (per `lib/profiles/resolver.mjs`):
|
|||
3. Inherited from `plan.md` frontmatter `profile:` field (source: `inheritance`)
|
||||
4. `premium` default for v4.0-style plans without `profile:` (source: `default`)
|
||||
|
||||
The selected profile goes to the resolver. It changes no model here: the step helper and the
|
||||
controller run opus (Composition rule below), and nothing in this command reads `parallel_agents`.
|
||||
The selected profile drives `phase_models.execute` (model for execution
|
||||
orchestrator) and `parallel_agents` for wave-parallel sessions.
|
||||
|
||||
Examples:
|
||||
```
|
||||
|
|
@ -3037,6 +2939,9 @@ Examples:
|
|||
VOYAGE_PROFILE=balanced /trekexecute --project ...
|
||||
```
|
||||
|
||||
Stats records emit `profile`, `phase_models`, and `profile_source` per
|
||||
Phase 9 record.
|
||||
|
||||
## Composition rule (v5.1)
|
||||
|
||||
Independent of the profile system. When `brief.md` carries
|
||||
|
|
@ -3050,7 +2955,7 @@ model_for_phase = brief.phase_signals[<phase>]?.model ?? profile.phase_models[
|
|||
|
||||
The brief signal wins per-phase when present; the profile fills any
|
||||
gaps. Both fields are mechanically resolved by the single composed CLI,
|
||||
invoked in Phase 1 alongside the sequencing-gate brief-validator call:
|
||||
invoked in Phase 2.4 alongside the sequencing-gate brief-validator call:
|
||||
|
||||
```bash
|
||||
# v5.9 — composed phase-model resolution (brief > profile > default) for the
|
||||
|
|
@ -3062,18 +2967,21 @@ node ${CLAUDE_PLUGIN_ROOT}/lib/profiles/resolver.mjs --resolve-phase-model --pha
|
|||
```
|
||||
|
||||
`phase_signal_result.effort` (absent = `standard`) is consumed when picking the execution
|
||||
strategy (the parallel-wave choice, Phase 2.5). The resolver does NOT control the orchestrator's own
|
||||
strategy (gates auto-escalation, parallel-wave choice — see High-effort
|
||||
behavior below). The resolver does NOT control the orchestrator's own
|
||||
model — that is fixed at invocation time (command frontmatter omits
|
||||
`model:`, so it follows the session model) and cannot be switched mid-turn.
|
||||
`/trekexecute` spawns no swarm: one step helper at a time and one controller
|
||||
(Hard Rule 10), and both run `opus` — the step agent's pin and the
|
||||
controller's `model: "opus"` — so `phase_signal_result.model` still has no
|
||||
spawn site here; it is returned for cross-command uniformity; no stats record carries it.
|
||||
spawn site here; it is returned for cross-command uniformity and stats.
|
||||
|
||||
For `/trekexecute` specifically: `effort == 'low'` runs the plan as one
|
||||
session, step after step (Phase 2.5). `effort == 'standard'` (or absent) →
|
||||
no change (default execution strategy applies). `effort == 'high'`: see
|
||||
`### High-effort behavior (v5.1.1)` below.
|
||||
For `/trekexecute` specifically: `effort == 'low'` activates `--gates open`
|
||||
+ sequential-only execution (no worktree-isolated parallel waves — runs
|
||||
all sessions in a single foreground loop). `effort == 'standard'` (or
|
||||
absent) → no change (default execution strategy applies). `effort == 'high'`
|
||||
activates the high-effort behavior documented under `### High-effort
|
||||
behavior (v5.1.1)` below.
|
||||
|
||||
### Sequencing gate surface
|
||||
|
||||
|
|
@ -3087,9 +2995,32 @@ commands surface, don't re-enforce.
|
|||
|
||||
### High-effort behavior (v5.1.1)
|
||||
|
||||
High effort changes nothing in `/trekexecute`: the step helper and the
|
||||
controller already run opus, and every gate already runs. No `gates_mode` is
|
||||
set from the effort.
|
||||
When `phase_signal_result.effort == 'high'` for the `execute` phase,
|
||||
set `gates_mode = 'closed'` automatically (equivalent to passing
|
||||
`--gates closed` on the command line). All autonomy boundaries become
|
||||
operator-stopping points: manifest-audit FAIL halts immediately, the
|
||||
main-merge gate stays a lock whose one question is the guard's (Phase 8), and Phase 7.5
|
||||
manifest-audit runs in its strictest form (fails on ANY mismatch, not
|
||||
just deltas above threshold). Operator explicit `--gates` flag still
|
||||
wins over the brief signal — if the operator passes `--gates open` on
|
||||
the command line while `phase_signal_result.effort == 'high'`, the
|
||||
flag takes precedence and the override is logged:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/stats/event-emit.mjs \
|
||||
--event gates_mode_flag_override --payload '{"flag":"--gates","signal_effort":"high"}'
|
||||
```
|
||||
|
||||
The record lands in `trekexecute-stats.jsonl` in the plugin data directory as
|
||||
`{ts, event, known_event, payload:{flag, signal_effort}}`. The two payload keys
|
||||
stay in the jsonl; the OTel export allowlist drops them by omission. On
|
||||
`"written": false` (exit 1), print its `reason` in one line and continue — the
|
||||
override record never blocks the run.
|
||||
|
||||
Standard effort (or absent): use `gates_mode = 'adaptive'` (the
|
||||
default). Low effort: `gates_mode = 'open'` plus sequential-only
|
||||
execution (no parallel waves) — existing `--quick`-equivalent
|
||||
code-path.
|
||||
|
||||
## Hard rules
|
||||
|
||||
|
|
|
|||
|
|
@ -124,23 +124,12 @@ Parse `$ARGUMENTS` for mode flags. Order of precedence:
|
|||
7. **`--quick`** — set **mode = quick**. Skip agent swarm; use lightweight
|
||||
Glob/Grep scan and go directly to planning + adversarial review.
|
||||
|
||||
8. **`--gates`** — autonomy control. `--gates` takes the next token as its
|
||||
value only when it is `true`, `false`, `closed` or `open` (strip both);
|
||||
any other next token is not its value (strip only the flag). Run the shim
|
||||
once to map the value, bare when there is no value:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state idle --event start --gates [value]
|
||||
```
|
||||
|
||||
`next_state: gates_on` sets `gates_mode = true`, `auto_running` sets it
|
||||
false, and nothing else reads the state. On exit 1 or no JSON (a broken
|
||||
shim; the four values cannot cause it), print the error in one line and
|
||||
map in prose instead: bare, `true`, `closed` → true; `false`, `open` →
|
||||
false. The run goes on either way. With `gates_mode = true`, pause for
|
||||
operator confirmation after Phase 5 (exploration), Phase 7 (synthesis),
|
||||
and Phase 9 (adversarial review). Default `gates_mode = false` lets
|
||||
phases flow continuously.
|
||||
8. **`--gates`** — autonomy control. When present, set `gates_mode = true`.
|
||||
Pause for operator confirmation after Phase 5 (exploration), Phase 7
|
||||
(synthesis), and Phase 9 (adversarial review). Default `gates_mode =
|
||||
false` lets phases flow continuously. The flag is consumed by the
|
||||
autonomy-gate state machine via the CLI shim:
|
||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
||||
|
||||
9. **`--min-brief-version <ver>`** — (optional) version floor. Set
|
||||
**min_brief_version = {ver}** (e.g. `2.2`). Forwarded to the brief-validator
|
||||
|
|
@ -325,10 +314,6 @@ Determine the output directory from the plan slug:
|
|||
|
||||
Launch the **session-decomposer** agent:
|
||||
|
||||
Phase 1 runs the model resolver only for `--project`, so `--decompose` has no
|
||||
resolved model: this spawn passes no `model:`, and the agent's own `model:`
|
||||
applies.
|
||||
|
||||
```
|
||||
Plan file: {plan path}
|
||||
Plugin root: ${CLAUDE_PLUGIN_ROOT}
|
||||
|
|
@ -427,7 +412,7 @@ Then continue to the next phase inline.
|
|||
|
||||
## Phase 4 — Codebase sizing
|
||||
|
||||
Determine codebase scale to decide whether convention-scanner runs.
|
||||
Determine codebase scale to calibrate agent turns (not agent count).
|
||||
|
||||
Run via Bash:
|
||||
```
|
||||
|
|
@ -459,20 +444,11 @@ unchanged since /trekbrief's review"), and continue to Phase 5. Exit 1
|
|||
pass, or a brief from another producer) or 2 (could not run): review it as
|
||||
below (operator decision 2026-10-08).
|
||||
|
||||
Launch the **brief-reviewer** agent. It has `voyage:writing-criteria` and
|
||||
`voyage:reviewing-adversarially` preloaded through its `skills:` line; name
|
||||
both in the prompt anyway, so the rules hold even where preloading did not
|
||||
happen.
|
||||
Launch the **brief-reviewer** agent:
|
||||
Prompt: "Review this task brief for quality: {brief_path}. Check completeness,
|
||||
consistency, testability, scope clarity, and research-plan validity.
|
||||
Follow the writing-criteria skill (each success criterion is one command the
|
||||
criteria runner accepts, and it can go red) and the reviewing-adversarially skill.
|
||||
Read local files only inside the repo under exploration, plus paths this prompt gives you (the brief, the plan, and templates it names)."
|
||||
|
||||
Pass `model: {phase_signal_result.model}` at this spawn; without it (the
|
||||
`--brief` branch, where the resolver does not run, or a resolver that printed
|
||||
nothing) the agent's own `model:` applies.
|
||||
|
||||
Handle the verdict:
|
||||
- **PROCEED** — continue to Phase 5.
|
||||
- **PROCEED_WITH_RISKS** — continue, carry flagged risks as `[ASSUMPTION]` in the plan.
|
||||
|
|
@ -513,7 +489,8 @@ message). Use the specialized agents from the `agents/` directory.
|
|||
> 2026-08-17: named 0/5 returned, unnamed 3/3. Mechanism, denominators, and the
|
||||
> on-disk recovery path: `docs/agent-return-channel-defect.md`.
|
||||
|
||||
**All agents run for all codebase sizes.**
|
||||
**All agents run for all codebase sizes.** Scale `maxTurns` by size (small: halved,
|
||||
medium: default, large: default) instead of dropping agents.
|
||||
|
||||
| Agent | Small | Medium | Large | Purpose |
|
||||
|-------|-------|--------|-------|---------|
|
||||
|
|
@ -530,10 +507,6 @@ research-scout's web search is not a local read; the line above bounds its local
|
|||
|
||||
### Always launch (all codebase sizes):
|
||||
|
||||
Pass `model: {phase_signal_result.model}` at this spawn; without it (the
|
||||
`--brief` branch, where the resolver does not run, or a resolver that printed
|
||||
nothing) the agent's own `model:` applies.
|
||||
|
||||
**architecture-mapper** — full codebase structure, tech stack, patterns, anti-patterns.
|
||||
Prompt: "Analyze the architecture of this codebase. The task being planned is: {task}.
|
||||
Brief file: {brief_path} — read it first.
|
||||
|
|
@ -571,7 +544,7 @@ Read local files only inside the repo under exploration, plus paths this prompt
|
|||
|
||||
### Launch for medium+ codebases (50+ files):
|
||||
|
||||
**Convention Scanner** — use the `convention-scanner` plugin agent (model: phase_signal_result.model, the agent's frontmatter as the fallback)
|
||||
**Convention Scanner** — use the `convention-scanner` plugin agent (model: "opus")
|
||||
for medium+ codebases only.
|
||||
Prompt: "Discover the coding conventions relevant to this task: {task}. Brief file: {brief_path} — read it first. Read local files only inside the repo under exploration, plus paths this prompt gives you (the brief, the plan, and templates it names). Provide concrete examples from the codebase, not generic advice."
|
||||
|
||||
|
|
@ -589,9 +562,6 @@ topics have corresponding research files, skip research-scout entirely.
|
|||
|
||||
If yes (and not covered by attached briefs): launch **research-scout** in
|
||||
parallel with the other agents.
|
||||
Pass `model: {phase_signal_result.model}` at this spawn; without it (the
|
||||
`--brief` branch, where the resolver does not run, or a resolver that printed
|
||||
nothing) the agent's own `model:` applies.
|
||||
Prompt: "Research the following technologies for this task: {task}.
|
||||
Specific questions: {list specific questions about the technology}.
|
||||
Technologies to research: {list}. Brief file: {brief_path} — read it first.
|
||||
|
|
@ -612,8 +582,7 @@ Common reasons for deep-dives:
|
|||
- A test pattern was identified but the test infrastructure needs more detail
|
||||
- A risk was flagged but the actual impact needs verification
|
||||
|
||||
For each significant gap, spawn a targeted deep-dive agent (model: phase_signal_result.model, else opus —
|
||||
Explore is Claude Code's built-in agent and has no Voyage frontmatter to fall back to,
|
||||
For each significant gap, spawn a targeted deep-dive agent (model: "opus",
|
||||
subagent_type: "Explore") with a narrow, specific brief. Each deep-dive prompt
|
||||
carries these two lines:
|
||||
Brief file: {brief_path} — read it first.
|
||||
|
|
@ -740,7 +709,7 @@ Do NOT write this synthesis to disk. It is internal working context only.
|
|||
>
|
||||
> **Two step rules at every plan_version** (no version bump; a plan without
|
||||
> the field is unchanged): the optional `Regression:` field (K10) holds ONE
|
||||
> backticked command the criteria runner accepts (`voyage:writing-criteria`) —
|
||||
> backticked command the criteria runner allows, with no pipe and no `&&` —
|
||||
> usually `npm test`, the suite the step must not break. `Verify:` stays the
|
||||
> step's own test, the one that is red first; `Regression:` is what the
|
||||
> executor runs green before the checkpoint, so a step whose red test is a
|
||||
|
|
@ -818,17 +787,17 @@ Write the plan following the template structure. The plan MUST include:
|
|||
(`PLAN_STEP_TESTS_ONLY`).
|
||||
|
||||
**The "run the thing" step.** At least one step carries
|
||||
`End-to-end: \`<command>\` → expected: <what the user sees>`: the product run the way a
|
||||
user runs it (the CLI, the server and a request, the app; for iOS, the simulator). Without
|
||||
it the result is "not verified end to end", never green. To see and drive the app, use
|
||||
Claude Code's built-in `run` skill; the verdict is still the `End-to-end:` command, because
|
||||
`run` gives no exit code. The command passes the criteria runner's allowlist — the
|
||||
product's own binary does not, so the run is wrapped in a script:
|
||||
`End-to-end: \`<command>\` → expected: <what the user sees>`: the product run
|
||||
the way a user runs it (the CLI, the server and a request, the app; for iOS,
|
||||
the simulator). Without it the result is "not verified end to end", never
|
||||
green. The command passes the criteria runner's allowlist — the product's
|
||||
own binary does not, so the run is wrapped in a script:
|
||||
`End-to-end: \`bash tests/e2e.sh\``. The same command is also listed under
|
||||
`## Verification`: Phase 7 of `/trekexecute` runs that section, and a passed criterion that
|
||||
runs the step's `End-to-end:` command is what verifies the run end to end. `End-to-end:`
|
||||
rides on the last step that builds behaviour, with `tests/e2e.sh` in that step's `Files:`:
|
||||
a step of its own that only adds the script is a step of only tests, and it can never be proven red.
|
||||
`## Verification`: Phase 7 of `/trekexecute` runs that section, and a passed
|
||||
criterion that runs the step's `End-to-end:` command is what verifies the
|
||||
run end to end. `End-to-end:` rides on the last step that builds behaviour,
|
||||
with `tests/e2e.sh` in that step's `Files:`: a step of its own that only adds
|
||||
the script is a step of only tests, and it can never be proven red.
|
||||
10. **Execution Strategy** — For plans with > 5 steps: group steps into sessions
|
||||
(3–5 steps each), organize sessions into waves (parallel where independent),
|
||||
specify scope fences per session. Omit for plans with ≤ 5 steps.
|
||||
|
|
@ -855,13 +824,24 @@ Write the plan following the template structure. The plan MUST include:
|
|||
npm test
|
||||
node --test tests/lib/x.test.mjs
|
||||
```
|
||||
Each command is written by the `voyage:writing-criteria` skill (use it by
|
||||
name before you write this section and the steps' `Verify:`, `Regression:`
|
||||
and `End-to-end:` lines): one command the criteria runner accepts, in plain
|
||||
words, a script under `tests/` (`bash tests/<script>.sh`) for anything
|
||||
more, and a command that can go red. Anything the runner refuses is
|
||||
reported NOT RUN, never executed and never failed, and an unrunnable plan
|
||||
criterion stops `/trekexecute` Phase 7.
|
||||
The command must also be one the criteria runner is allowed to run: a test
|
||||
runner (`npm test`, `npm run <script>`, `node --test <file>`, `vitest`,
|
||||
`jest`, `pytest`, `python -m pytest`, `uv run pytest`, `cargo test`,
|
||||
`go test`, `make test`), `bash <script under tests/>` (also
|
||||
`/bin/bash <script under tests/>`, to pin the system shell), or a read-only
|
||||
`git` subcommand (`status`, `log`, `diff`, `show`, `ls-files` — not `git
|
||||
grep`) — with no pipe, redirect or `&&`. It runs with no shell: its words
|
||||
reach the runner as written, so a word with a quote, backslash, `$`,
|
||||
brace, or a leading `~` or `@` is refused (a git revision such as `@~1`
|
||||
is the one exception), a glob only reaches
|
||||
`node --test` on Node 21 and later (which expands its own patterns), no
|
||||
path climbs out with `..` or starts at `/` (git included), each runner
|
||||
takes a short list of read-only options, and nothing may follow
|
||||
`make test`. A trailing `# comment` is dropped, on a line of a shell fence and in a backticked command alike;
|
||||
in a backticked command it may not hold a quote, `$`, backtick or backslash (the executor passes the
|
||||
span on inside double quotes), and such a comment is refused, not dropped. Anything else is reported NOT
|
||||
RUN, never executed and never failed. A check that needs more than that is
|
||||
wrapped in a script under `tests/` and declared as `bash tests/<script>.sh`.
|
||||
9. **Estimated Scope** — File counts and complexity rating.
|
||||
|
||||
### Quality standards
|
||||
|
|
@ -982,24 +962,11 @@ Then launch two review agents **in parallel — emit both Agent tool calls in a
|
|||
single assistant message turn** (same pattern as Phase 5 exploration). They
|
||||
have zero data dependencies; serializing them wastes 30–60 seconds per run.
|
||||
|
||||
Both reviewers are asked for `voyage:writing-criteria` and
|
||||
`voyage:reviewing-adversarially` by name. `plan-critic` has both preloaded;
|
||||
`scope-guardian` has `voyage:reviewing-adversarially` preloaded and gets the
|
||||
writing-criteria rule in one sentence in its prompt, for the brief's criteria
|
||||
it traces into `## Verification`.
|
||||
|
||||
Pass `model: {phase_signal_result.model}` at this spawn; without it (the
|
||||
`--brief` branch, where the resolver does not run, or a resolver that printed
|
||||
nothing) the agent's own `model:` applies.
|
||||
|
||||
**plan-critic** — adversarial review of the plan.
|
||||
Prompt: "Review this implementation plan for the task: {task}.
|
||||
Plan file: {plan path}. Read it and find every problem — missing steps,
|
||||
wrong ordering, fragile assumptions, missing error handling, scope creep,
|
||||
underspecified steps. Rate each finding as blocker, major, or minor.
|
||||
Follow the writing-criteria skill (every check is one command the criteria
|
||||
runner accepts, and one that can never go red is a finding) and the
|
||||
reviewing-adversarially skill.
|
||||
End your response with the REQUIRED machine-readable `json` findings block
|
||||
(schema in `agents/plan-critic.md`) so the orchestrator can pipe it to the
|
||||
dedup helper. You have no Write tool — return the block inline, do not write a file.
|
||||
|
|
@ -1013,10 +980,7 @@ Task: {task}. Brief file: {brief_path}. Plan file: {plan path}.
|
|||
Find scope creep (plan does more than the brief requires) and scope gaps
|
||||
(plan misses brief requirements). Check that referenced files and functions
|
||||
exist. Verify that every Success Criterion in the brief is covered by the
|
||||
plan's Verification section. Follow the writing-criteria skill for those
|
||||
criteria (each is one command the criteria runner accepts, and it can go red)
|
||||
and the reviewing-adversarially skill.
|
||||
End your response with the REQUIRED machine-readable
|
||||
plan's Verification section. End your response with the REQUIRED machine-readable
|
||||
`json` findings block (schema in `agents/scope-guardian.md`). You have no Write
|
||||
tool — return the block inline, do not write a file.
|
||||
Read local files only inside the repo under exploration, plus paths this prompt gives you (the brief, the plan, and templates it names)."
|
||||
|
|
@ -1156,13 +1120,13 @@ Present a summary to the user:
|
|||
You can:
|
||||
- Say which open minors to fix ("fix 1 and 3")
|
||||
- Ask questions or request changes to refine the plan
|
||||
- Say **"execute"** for the `/trekexecute` line to run ← only when the gate exited 0
|
||||
- Say **"execute"** to start implementing ← only when the gate exited 0
|
||||
- Say **"save"** to keep the plan for later
|
||||
```
|
||||
|
||||
When the gate exited 1, replace the "execute" line with
|
||||
`Execution is blocked: {the gate's reasons}` and do not print the `/trekexecute`
|
||||
line, whatever is said next, until the gate exits 0.
|
||||
`Execution is blocked: {the gate's reasons}` and do not start implementing,
|
||||
whatever is said next, until the gate exits 0.
|
||||
|
||||
**What counts as approval.** "Execute", "go" or "start" (or the plan-mode
|
||||
approval below) approves the plan. A hedged reply — "sounds good", "looks
|
||||
|
|
@ -1201,11 +1165,8 @@ plan-approval prompt:
|
|||
plan back.
|
||||
3. **Approved:** the session leaves plan mode. Copy the plan file to the plan
|
||||
destination from Phase 3, then run the gate on the destination — it must
|
||||
exit 0 again, which also proves the copy is the reviewed text. Then go
|
||||
through Phase 11 (its plan approval, then the `/trekexecute` line) and
|
||||
stop — leaving plan mode is not an order to implement. Phase 11 asks again
|
||||
because the plan-mode approval is logged under Claude Code's plan file, and
|
||||
`/trekexecute` checks the copy at the plan destination.
|
||||
exit 0 again, which also proves the copy is the reviewed text. Then
|
||||
continue with the operator's choice (Phase 11).
|
||||
4. **"No, keep planning":** revise per the operator's words, run one Phase 9
|
||||
round, and present again from step 1.
|
||||
|
||||
|
|
@ -1217,11 +1178,15 @@ plan mode's restrictions). Until an operator has run it, both paths stay.
|
|||
|
||||
### Build the operator-annotation HTML and print the link
|
||||
|
||||
After the plan summary, run `scripts/annotate.mjs` to build the page
|
||||
where the operator writes their own notes on `plan.md`. The loop that
|
||||
follows is the skill `voyage:annotating`: call it when the operator pastes
|
||||
the notes back (a Question is answered, not applied; an approved plan that
|
||||
changes needs a new approval before `/trekexecute`, said before the edit).
|
||||
After the plan summary, run `scripts/annotate.mjs` to produce a
|
||||
self-contained HTML the operator opens in their browser. The HTML renders
|
||||
`plan.md` with line numbers, lets the operator click any line to attach
|
||||
their own note (not Claude-generated suggestions — the operator drives
|
||||
every annotation), keeps a sidebar of all notes, persists state in
|
||||
localStorage, and exposes a "Copy Prompt" button that generates a single
|
||||
structured prompt with every note. The operator copies that prompt and
|
||||
pastes it back into Claude; Claude revises `plan.md` freehand from the
|
||||
notes.
|
||||
|
||||
```bash
|
||||
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{plan_path}" 2>&1)
|
||||
|
|
@ -1245,9 +1210,9 @@ To review and annotate the plan, open it in a browser:
|
|||
|
||||
Click any line to add YOUR OWN note. The sidebar collects every note,
|
||||
the "Copy Prompt" button gathers them into one structured prompt.
|
||||
Paste that prompt back into this chat: Claude answers each Question
|
||||
and revises plan.md from your Fix and Change notes. Annotations
|
||||
persist in your browser if you close the tab and reopen the same file.
|
||||
Paste that prompt back into this chat and Claude revises plan.md
|
||||
from your notes. Annotations persist in your browser if you close
|
||||
the tab and reopen the same file.
|
||||
────────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
|
|
@ -1293,16 +1258,15 @@ Confirm the plan and brief file locations and exit.
|
|||
|
||||
### "execute" / "go" / "start"
|
||||
|
||||
Do not implement in this session. Print the line the operator gives
|
||||
`/trekexecute` — `/trekexecute --project {project_dir}`, or
|
||||
`/trekexecute {plan_path}` without a project directory — then run Phase 12 (`outcome: execute`).
|
||||
`/trekexecute` is what checks the plan's approval (K2), locks the tests, runs
|
||||
one step helper per step and the review.
|
||||
Begin implementing the plan step by step in this session. Follow the plan exactly.
|
||||
Mark each step complete as you go.
|
||||
|
||||
### "execute with team" / "team"
|
||||
|
||||
There is no team path. Print the same `/trekexecute` line, then run Phase 12
|
||||
(`outcome: execute_team`); parallel work is `--decompose` followed by `/trekexecute`'s session orders.
|
||||
There is no team path. Tell the user that parallel team execution is not available
|
||||
from `/trekplan`, then proceed exactly as for "execute" (sequential, in this
|
||||
session). Parallel implementation is `--decompose` followed by `/trekexecute`'s
|
||||
multi-session waves.
|
||||
|
||||
## Phase 12 — Session tracking
|
||||
|
||||
|
|
@ -1363,6 +1327,9 @@ Examples:
|
|||
VOYAGE_PROFILE=balanced /trekplan --project ...
|
||||
```
|
||||
|
||||
Stats records emit `profile`, `phase_models`, `parallel_agents`, and
|
||||
`profile_source` so operators can audit which profile drove which session.
|
||||
|
||||
## Composition rule (v5.1)
|
||||
|
||||
Independent of the profile system. When `brief.md` carries
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ Supported flags:
|
|||
is `{model, source}`, plus
|
||||
`effort` only when the brief's phase signal sets one (without it the
|
||||
phase runs at effort `standard`: no change). It is captured as
|
||||
`phase_signal_result` and used at Agent-spawn sites in Phase 4 and Phase 5 to inject
|
||||
`phase_signal_result` and used at Agent-spawn sites in Phase 4 to inject
|
||||
the resolved model:
|
||||
|
||||
```bash
|
||||
|
|
@ -72,23 +72,12 @@ Supported flags:
|
|||
node ${CLAUDE_PLUGIN_ROOT}/lib/profiles/resolver.mjs --resolve-phase-model --phase research --brief-path "{dir}/brief.md" [--profile {profile}] --json
|
||||
```
|
||||
|
||||
6. `--gates` — autonomy control. `--gates` takes the next token as its
|
||||
value only when it is `true`, `false`, `closed` or `open` (strip both);
|
||||
any other next token is not its value (strip only the flag). Run the shim
|
||||
once to map the value, bare when there is no value:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state idle --event start --gates [value]
|
||||
```
|
||||
|
||||
`next_state: gates_on` sets `gates_mode = true`, `auto_running` sets it
|
||||
false, and nothing else reads the state. On exit 1 or no JSON (a broken
|
||||
shim; the four values cannot cause it), print the error in one line and
|
||||
map in prose instead: bare, `true`, `closed` → true; `false`, `open` →
|
||||
false. The run goes on either way. With `gates_mode = true`, the
|
||||
6. `--gates` — autonomy control. When present, set `gates_mode = true`. The
|
||||
research command will pause after each topic completes ("Topic N
|
||||
complete. Proceed to topic N+1? (yes/no)"). Default `gates_mode = false`
|
||||
means topics run continuously.
|
||||
means topics run continuously. The flag is consumed by the autonomy-gate
|
||||
state machine via the CLI shim:
|
||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
||||
|
||||
7. `--min-brief-version <ver>` — (optional) version floor for an attached
|
||||
`--project` brief. Set **min_brief_version = {ver}** (e.g. `2.2`). Forwarded
|
||||
|
|
@ -384,8 +373,7 @@ changes nothing (SC1). Keep the native-swarm anchors intact ("in parallel",
|
|||
5. **On a real report:** keep `effective_engine = deep-research`, log
|
||||
`Engine: deep-research (active)`, and carry the report into Phase 6 triangulation
|
||||
as the external-findings input (adapted in Phase 7 — see the Deep-research engine
|
||||
adapter below); then run wave 2 (`contrarian-researcher`, see Launch rules)
|
||||
from the report's leading answer.
|
||||
adapter below).
|
||||
|
||||
### External agents (scope = both or external)
|
||||
|
||||
|
|
@ -414,22 +402,7 @@ ticket IDs) already removed: the agents search with the words they are given.
|
|||
|
||||
### Launch rules
|
||||
|
||||
- Launch in two waves, both in Phase 4 (before Phase 4.5 and Phase 5, so outside
|
||||
the Phase 5 loop scope marker that `hooks/scripts/pre-agent-cap.mjs` reads).
|
||||
- **Wave 1:** ALL selected agents except `contrarian-researcher` **in parallel**
|
||||
in a single message.
|
||||
- **Wave 2:** `contrarian-researcher`, when selected, after wave 1 returns, in a
|
||||
message of its own. Give it a conclusion to attack: the leading answer (one or
|
||||
two sentences), the claims for it and the alternatives wave 1 dismissed,
|
||||
taken from wave 1's external findings only, never from the local agents'
|
||||
findings (Hard rules → Independence), and stripped of local parts like the
|
||||
research question above (absolute paths, user names, internal project or
|
||||
repository names, ticket IDs). It searches with the words it is given, so no
|
||||
local file name or project term may be in them. When wave 1's external
|
||||
findings hold no leading answer, say so and give it the research question
|
||||
alone, stripped the same way. With `--engine deep-research`
|
||||
(`effective_engine = deep-research`), wave 2 runs after the engine returns,
|
||||
from the leading answer of its report.
|
||||
- Launch ALL selected agents **in parallel** in a single message
|
||||
- Inject the resolved model at every spawn: `phase_signal_result.model` (brief
|
||||
signal > profile), with the agent's frontmatter `model:` as the fallback — see
|
||||
Hard rules → Cost. The orchestrator itself follows the session model.
|
||||
|
|
@ -445,6 +418,8 @@ ticket IDs) already removed: the agents search with the words they are given.
|
|||
Measured 2026-08-17: named 0/5 returned, unnamed 3/3. Mechanism,
|
||||
denominators, and the on-disk recovery path:
|
||||
`docs/agent-return-channel-defect.md`.
|
||||
- Scale maxTurns by codebase size for local agents (same as trekplan):
|
||||
small = halved, medium/large = default
|
||||
- convention-scanner: medium+ codebases only (50+ files)
|
||||
|
||||
## Phase 4.5 — Dimension discovery
|
||||
|
|
@ -518,9 +493,7 @@ Review all agent results. Identify knowledge gaps — dimensions where findings
|
|||
are thin, contradictory, or missing (**under-illuminated dimensions**).
|
||||
|
||||
**Standard and low effort — unchanged single pass.** For each significant gap,
|
||||
launch a targeted follow-up agent (model: phase_signal_result.model, else opus — a
|
||||
follow-up may be one of Claude Code's built-in agents, which have no Voyage
|
||||
frontmatter to fall back to; see Launch rules) with a narrow, specific
|
||||
launch a targeted follow-up agent (model: "opus") with a narrow, specific
|
||||
brief; a follow-up that searches the web names the `researching-sources` skill
|
||||
in its prompt, as above. Maximum 2 follow-ups. If no gaps exist, skip: "Initial research
|
||||
sufficient — no follow-ups needed." Then go to Phase 6.
|
||||
|
|
@ -648,10 +621,6 @@ reformulated, not forced through. A gate that *could not run* is neither — no
|
|||
rewrite can clear it, so treat it as a hard stop and say so, rather than
|
||||
rewriting a query that was never the problem.
|
||||
|
||||
A turn that spawns an agent passes `model: phase_signal_result.model`, else
|
||||
`opus` — the agent may be one of Claude Code's built-in agents, which have no
|
||||
Voyage frontmatter to fall back to; see Launch rules.
|
||||
|
||||
**Empty turns.** A turn that returns no findings, or findings without
|
||||
citations, is marked `empty`. An empty turn is counted in `empty_turns` and
|
||||
does NOT re-target the same dimension — re-asking the same question of the
|
||||
|
|
@ -762,10 +731,7 @@ raw report. Specifically:
|
|||
- Reduce the report to ≥ 1 `### {Dimension} -- Confidence: {high|medium|low|contradictory}`
|
||||
entry, each carrying **External findings** bullets with per-claim source URLs.
|
||||
Local findings still come from the local agents (Phase 4) and are merged in per
|
||||
dimension as usual. Wave 2's `contrarian-researcher` findings (Launch rules)
|
||||
are not part of the report: they are merged in per dimension as **External
|
||||
findings**, cited by URL like the report's, and where one disputes the
|
||||
report's leading answer, the dimension's **Contradictions** gives both sides.
|
||||
dimension as usual.
|
||||
- Emit a numeric `confidence ∈ [0,1]` in frontmatter and a 3-sentence
|
||||
`## Executive Summary` (answer, confidence, key caveat).
|
||||
- Populate `## Sources` from the report's citations.
|
||||
|
|
@ -901,7 +867,9 @@ Examples:
|
|||
VOYAGE_PROFILE=balanced /trekresearch
|
||||
```
|
||||
|
||||
Stats records emit `engine` so operators can audit which engine drove which session.
|
||||
Stats records emit `profile`, `phase_models`, `parallel_agents`,
|
||||
`external_research_enabled`, `profile_source`, and `engine` so operators can
|
||||
audit which profile and engine drove which session.
|
||||
|
||||
## Composition rule (v5.1)
|
||||
|
||||
|
|
@ -946,11 +914,12 @@ commands surface, don't re-enforce.
|
|||
### High-effort behavior (v5.1.1)
|
||||
|
||||
When `phase_signal_result.effort == 'high'` for the `research` phase,
|
||||
run the FULL swarm regardless of normal selection rules: 5 local
|
||||
run the FULL swarm regardless of normal triggering rules: 5 local
|
||||
agents + 4 external agents, AND force `contrarian-researcher` to
|
||||
always-on: in high-effort mode `contrarian-researcher` runs
|
||||
unconditionally, as wave 2 (see Launch rules), so the final brief
|
||||
always carries an adversarial counter-evidence pass.
|
||||
always-on. Normally `contrarian-researcher` triggers conditionally when
|
||||
a leading recommendation is emerging from initial agents; in
|
||||
high-effort mode it runs unconditionally so the final brief always
|
||||
carries an adversarial counter-evidence pass.
|
||||
|
||||
The former third-party second-opinion bridge pass is **unavailable,
|
||||
skipped** (dropped in v5.10.1 by operator directive). High effort no
|
||||
|
|
@ -965,9 +934,7 @@ turns per under-illuminated dimension, budgeted by
|
|||
`--local`, `external_research_enabled: false`) overrides the effort
|
||||
signal whenever the external phase does not run at all.
|
||||
|
||||
Standard effort (or absent): the selected agents run as in Phase 4, and
|
||||
`contrarian-researcher`, when selected, runs as wave 2 after the other
|
||||
agents return (see Launch rules).
|
||||
Standard effort (or absent): use the existing conditional triggers.
|
||||
Low effort: inline research only, no agent swarm (existing
|
||||
`--quick`-equivalent code-path).
|
||||
|
||||
|
|
|
|||
|
|
@ -46,13 +46,10 @@ command executes inline.
|
|||
## Phase 1 — Parse mode and validate input
|
||||
|
||||
Parse the arguments with the shared arg-parser. Run it first, exactly like
|
||||
this, before anything else (the arguments reach the parser as the one line
|
||||
inside the quoted heredoc, on stdin, never as shell words):
|
||||
this, before anything else:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview --stdin <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||
$ARGUMENTS
|
||||
VOYAGE_ARGS_EOF_7F3C9E
|
||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview -- $ARGUMENTS
|
||||
```
|
||||
|
||||
It prints the parse as JSON on stdout. It also checks the required flag
|
||||
|
|
@ -65,7 +62,7 @@ FLAG_SCHEMA `trekreview` entry):
|
|||
|------|------|---------|
|
||||
| `--project <dir>` | valued | Required. Path to trekplan project folder containing `brief.md`. |
|
||||
| `--since <ref>` | valued | Optional. Override "before" SHA for the diff. Validated via `git rev-parse --verify`. |
|
||||
| `--quick` | boolean | Skip the brief-conformance pass; run only the code-correctness reviewer; skip the coordinator's reasonableness filter except the brief-conflict rule. |
|
||||
| `--quick` | boolean | Skip the brief-conformance pass; run only the code-correctness reviewer; skip the coordinator's reasonableness filter. |
|
||||
| `--validate` | boolean | Schema-only check on existing `{project_dir}/review.md`. No LLM calls. |
|
||||
| `--dry-run` | boolean | Print the discovered scope and triage map. Skip writes. |
|
||||
| `--fg` | boolean | No-op alias (foreground is default). |
|
||||
|
|
@ -187,8 +184,8 @@ every file from Phase 3 into a treatment bucket:
|
|||
| Treatment | When |
|
||||
|-----------|------|
|
||||
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, OR the file's first 3 lines contain a generated-file marker (`@generated`, `Code generated by`, `DO NOT EDIT`). |
|
||||
| `deep-review` | Default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**`. |
|
||||
| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. |
|
||||
| `deep-review` | Matches `auth/**`, `crypto/**`, `**/security/**`, `hooks/**`. |
|
||||
| `summary-only` | Default treatment for everything else. |
|
||||
|
||||
Hard refuse-with-suggestion gates — use `AskUserQuestion`:
|
||||
|
||||
|
|
@ -384,15 +381,6 @@ message, multiple tool calls.
|
|||
|
||||
Reviewers run independently. Do NOT pre-feed findings between them.
|
||||
|
||||
**Reviewer stance: the `reviewing-adversarially` skill.** Both reviewers and
|
||||
the coordinator have `voyage:reviewing-adversarially` preloaded through their
|
||||
`skills:` line. Name it in every reviewer prompt anyway, so the rules hold even
|
||||
where preloading did not happen: "Follow the reviewing-adversarially skill: no
|
||||
praise; every finding cites file:line or quotes the line; no downgrade without
|
||||
a reason; say what you read in full and what only as a summary; list what you
|
||||
did not judge under ### Declined to Judge; check claims against the diff, not
|
||||
a report."
|
||||
|
||||
| Agent | Mode-gated | Purpose |
|
||||
|-------|------------|---------|
|
||||
| `brief-conformance-reviewer` | Skipped in `quick` | Trace each Success Criterion + Non-Goal to delivered code. Emits findings tagged with rule_keys from the conformance/scope categories. |
|
||||
|
|
@ -490,11 +478,7 @@ forbids `ALLOW` (`lib/review/coordinator-contract.mjs`, `missing_reviewers`).
|
|||
Launch `review-coordinator` (Agent tool) with the merged findings array
|
||||
from Phase 5 AND the Phase 4.7 engine payloads, plus the triage map, brief
|
||||
metadata, SHA range, the expected reviewer set (engines included), and each
|
||||
not-run engine with its reason. Name `voyage:reviewing-adversarially` in the
|
||||
coordinator's prompt as in Phase 5, and pass each reviewer's
|
||||
`### Declined to Judge` lines verbatim from its saved
|
||||
`{project_dir}/.review-out-{reviewer}.md`: the coordinator copies them into
|
||||
`## Declined to Judge`, so nothing a reviewer set aside disappears.
|
||||
not-run engine with its reason.
|
||||
|
||||
**Brief choices.** Next to the brief metadata, pass the brief's choices
|
||||
verbatim: extract the `## Non-Goals`, `## Constraints` and `## Preferences`
|
||||
|
|
@ -513,15 +497,8 @@ The coordinator runs the 4-pass process documented in
|
|||
Succinctness never removes a finding: only MINOR/SUGGESTION text is
|
||||
trimmed, and every trim is counted. A long BLOCKER or MAJOR keeps every
|
||||
character.
|
||||
3. **Cloudflare reasonableness** (skipped in `quick` mode) — drop a finding
|
||||
with no `file:line` citation (`no-citation`) or whose file is in neither
|
||||
the working tree nor the diff (`file-existence:refuted`); route one whose
|
||||
`rule_key` is not in `RULE_CATALOGUE` (`unknown-rule_key`) or whose file
|
||||
cannot be checked (`file-existence:indeterminate`) to `unverified`, which
|
||||
forbids `ALLOW`; reset a severity that does not match its catalogue tier.
|
||||
Skipped at high effort too, where an unknown `rule_key` is normalized to
|
||||
`PLAN_EXECUTE_DRIFT` instead (`### High-effort behavior (v5.1.1)` below);
|
||||
the brief-conflict rule still applies in every mode.
|
||||
3. **Cloudflare reasonableness** — remove speculative or catalogue-violating
|
||||
findings (skipped in `quick` mode).
|
||||
4. **Verdict** — BLOCK / WARN / ALLOW per the threshold table.
|
||||
|
||||
**Fail-closed.** Every removal in Pass 2 and Pass 3 is either
|
||||
|
|
@ -569,8 +546,11 @@ Workflow({
|
|||
|
||||
A reviewer that returns nothing, an engine listed in `engineNotRun`, or a coordinator that returns no verdict and findings forbids `ALLOW` on this path too (`missing_reviewers` in the result), and the result's `allow_blocked_by` names each one (`missing-reviewer:<name>`, the coordinator as `missing-reviewer:review-coordinator`);
|
||||
Phase 7 writes that list as the trailing JSON block's `allow_blocked_by`, so the verdict gate reads such a WARN review as not performed in full (exit 2; a BLOCK stays exit 1).
|
||||
On this path dedup ranks as Pass 1 does (both paths), and after the coordinator each finding is matched to its own row, its `(file, line, rule_key)` triplet plus its title, trimmed and in lower case: of the engine findings in a row no returned finding is on, the one with the highest severity (on a tie, the first seen) is put back at its own severity (operator decision 23), and a returned finding is never below the lower of its reviewer counterpart's severity and its catalogue tier (floor (b)); its counterpart is its own row, else the strictest row on its triplet.
|
||||
So the workflow path is stricter than the prose path.
|
||||
On this path dedup ranks as Pass 1 does (both paths), every engine finding the
|
||||
coordinator did not return at its exact `(file, line, rule_key)` is put back at its own
|
||||
severity (operator decision 23), and a returned finding is never below the lower of its
|
||||
reviewer counterpart's severity and its catalogue tier (floor (b)), so the workflow path
|
||||
is stricter than the prose path.
|
||||
|
||||
Contract (verified in S10 part B — follow exactly):
|
||||
- **Pass `args` as a JSON object.** The script defensively re-parses a JSON *string*, but
|
||||
|
|
@ -702,11 +682,13 @@ the main workflow, but it is reported, not skipped silently.
|
|||
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{review_path}" 2>&1)
|
||||
```
|
||||
|
||||
`stdout` is the absolute path to the `.html` on success: the page where the
|
||||
operator writes their own notes on `review.md`. The loop that follows is the
|
||||
skill `voyage:annotating`: call it when the operator pastes the notes back.
|
||||
If `annotate.mjs` exits non-zero, surface a one-line warning and continue —
|
||||
the annotation HTML is a convenience, not a gate.
|
||||
`stdout` is the absolute path to the `.html` on success. The HTML renders
|
||||
`review.md` with line numbers, lets the operator click any line to attach
|
||||
their own note (not Claude-generated suggestions — the operator drives
|
||||
every annotation), keeps a sidebar of all notes, persists state in
|
||||
localStorage, and exposes a "Copy Prompt" button. If `annotate.mjs`
|
||||
exits non-zero, surface a one-line warning and continue — the annotation
|
||||
HTML is a convenience, not a gate.
|
||||
|
||||
## Phase 8.5 — Validate-only mode (`--validate`)
|
||||
|
||||
|
|
@ -751,8 +733,8 @@ carries one line in the format **mistake · fix · how to check**:
|
|||
|
||||
**The operator approves every line.** For each proposal, use
|
||||
`AskUserQuestion` (up to 4 proposals per call), in plain language, showing
|
||||
the line and its two pieces of evidence. Options: **"Add the line"**
|
||||
(recommended: the class has recurred) and **"Not now"**; the operator may
|
||||
the line and its two pieces of evidence. Options: **"Skriv linja inn"**
|
||||
(recommended: the class has recurred) and **"Ikke nå"**; the operator may
|
||||
answer with an edited line through "Other". Never write a line the operator
|
||||
did not approve, and never treat "sounds good" or "do as you like" as a yes
|
||||
to a line it was not shown.
|
||||
|
|
@ -826,9 +808,9 @@ To review and annotate the review, open it in a browser:
|
|||
|
||||
Click any line to add YOUR OWN note. The sidebar collects every note,
|
||||
the "Copy Prompt" button gathers them into one structured prompt.
|
||||
Paste that prompt back into this chat: Claude answers each Question
|
||||
and revises review.md from your Fix and Change notes. Annotations
|
||||
persist in your browser if you close the tab and reopen the same file.
|
||||
Paste that prompt back into this chat and Claude revises review.md
|
||||
from your notes. Annotations persist in your browser if you close
|
||||
the tab and reopen the same file.
|
||||
────────────────────────────────────────────────────────────────────
|
||||
|
||||
You can also:
|
||||
|
|
@ -863,6 +845,8 @@ Examples:
|
|||
VOYAGE_PROFILE=premium /trekreview --project ...
|
||||
```
|
||||
|
||||
Stats records emit `profile` and `profile_source`.
|
||||
|
||||
## Composition rule (v5.1)
|
||||
|
||||
Independent of the profile system. When `brief.md` carries
|
||||
|
|
@ -906,8 +890,8 @@ readable.
|
|||
### High-effort behavior (v5.1.1)
|
||||
|
||||
When `phase_signal_result.effort == 'high'` for the `review` phase,
|
||||
skip Pass 3 (Cloudflare reasonableness filter) in `agents/review-coordinator.md`, except the brief-conflict rule, which applies in every mode.
|
||||
Passes 1, 2, and 4 still run.
|
||||
skip Pass 3 (Cloudflare reasonableness filter) in
|
||||
`agents/review-coordinator.md`. Passes 1, 2, and 4 still run.
|
||||
Rationale: high-effort review trusts the operator to weigh borderline
|
||||
findings rather than have the coordinator drop them. To prevent
|
||||
unknown `rule_key` values from polluting downstream remediation plans
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ Optional but standard sections: `## Non-Goals`, `## Constraints`, `## Preference
|
|||
| **v5.1 sequencing gate** | every read | `brief_version ≥ 2.1` requires `phase_signals` (list) OR `phase_signals_partial: true` — error `BRIEF_V51_MISSING_SIGNALS` on miss. Validator-only enforcement; commands surface, don't re-enforce. |
|
||||
| **v5.5 framing gate** | every read | `framing` enum-checked on any version when present (`BRIEF_INVALID_FRAMING`); at `brief_version ≥ 2.2` a missing `framing` → `BRIEF_MISSING_FRAMING` and a missing `## TL;DR` → `BRIEF_MISSING_SECTION` (strict) / warning (soft). `trekreview` briefs are exempt. |
|
||||
| Body sections | strict only | All `BRIEF_BODY_SECTIONS` present (`## TL;DR` added at ≥ 2.2) |
|
||||
| Runnable criteria | every read | A `## Success Criteria` bullet whose first backticked span is a command the review's criteria runner never runs (the product's own binary, `jq`, `grep`, a pipe), or whose first span is not a command while a later span is one (the runner reads only the first, voyage-lekerepo trial 5) → warning `BRIEF_SC_NOT_RUNNABLE`, never an error: a criterion a human judges stays allowed. Prose-only criteria, also those that only name a flag or a path, are not flagged. `trekreview` briefs are exempt. No schema change. Indented sub-bullets belong to the criterion above them (counted, never criteria of their own); a criterion with sub-points and no command → warning `BRIEF_SC_SUBPOINTS`. A brief whose Constraints or NFRs require bash 3.2 and a criterion that runs plain `bash` → warning `BRIEF_SC_BASH_NOT_PINNED` (use `/bin/bash`). |
|
||||
| Runnable criteria | every read | A `## Success Criteria` bullet whose first backticked span is a command the review's criteria runner never runs (the product's own binary, `jq`, `grep`, a pipe) → warning `BRIEF_SC_NOT_RUNNABLE`, never an error: a criterion a human judges stays allowed. Prose-only criteria are not flagged. `trekreview` briefs are exempt. No schema change. Indented sub-bullets belong to the criterion above them (counted, never criteria of their own); a criterion with sub-points and no command → warning `BRIEF_SC_SUBPOINTS`. A brief whose Constraints or NFRs require bash 3.2 and a criterion that runs plain `bash` → warning `BRIEF_SC_BASH_NOT_PINNED` (use `/bin/bash`). |
|
||||
|
||||
**State machine** detail: a brief that says it has research topics but skipped them must explicitly admit it (via `brief_quality: partial`). This is the most common failure mode the validator catches.
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ with `BRIEF_INVALID_MODEL`.
|
|||
|
||||
**Producer:** `/trekresearch` Phase 7 (synthesis + brief writer).
|
||||
|
||||
**Consumer:** `/trekplan` Phase 1 (project-dir auto-discovery) + `/trekplan` Phase 3 and Phase 7 (consumes findings as context).
|
||||
**Consumer:** `/trekplan` Phase 1 (project-dir auto-discovery) + `planning-orchestrator` (consumes findings as context).
|
||||
|
||||
**Path conventions:**
|
||||
- Project-dir mode: `.claude/projects/{YYYY-MM-DD}-{slug}/research/{NN}-{topic-slug}.md` (sorted by filename).
|
||||
|
|
@ -189,7 +189,7 @@ Optional: `## Local Context`, `## External Knowledge`, `## Triangulation`, `## S
|
|||
|
||||
**Producer:** external opt-in architect plugin (no longer publicly distributed).
|
||||
|
||||
**Consumer:** `/trekplan` Phase 1 (architecture-discovery) + `/trekplan` Phase 7 (cross-reference architecture-note as priors during synthesis).
|
||||
**Consumer:** `/trekplan` Phase 1 (architecture-discovery) + `planning-orchestrator` Phase 7 (cross-reference architecture-note as priors during synthesis).
|
||||
|
||||
**Path conventions:**
|
||||
- Canonical: `{project_dir}/architecture/overview.md`
|
||||
|
|
@ -221,7 +221,7 @@ The validator (`lib/validators/architecture-discovery.mjs`) is intentionally min
|
|||
|
||||
## Handover 4 — `plan.md` → execute
|
||||
|
||||
**Producer:** `/trekplan` Phase 8 (plan synthesis, then the schema self-check via `plan-validator --strict`).
|
||||
**Producer:** `planning-orchestrator` Phase 5 (plan synthesis) + Phase 5.5 (schema self-check via `plan-validator --strict`).
|
||||
|
||||
**Consumer:** `/trekexecute` Phase 2 (plan parsing) + `--validate` mode.
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ prose form (relaxed in S26 so the template's prose emission parses).
|
|||
|
||||
**Validation strategy:**
|
||||
|
||||
The strongest validation in the entire pipeline. `/trekplan` Phase 8 **must** run `plan-validator --strict` before handing the plan to plan-critic. `--validate` mode of `/trekexecute` runs the same check + `progress-validator`.
|
||||
The strongest validation in the entire pipeline. Phase 5.5 (planning-orchestrator) **must** run `plan-validator --strict` before handing the plan to plan-critic. `--validate` mode of `/trekexecute` runs the same check + `progress-validator`.
|
||||
|
||||
| Code | Meaning | Recovery |
|
||||
|---|---|---|
|
||||
|
|
@ -358,7 +358,6 @@ Rule B is stated by the reviewers and recorded by the gate from round 1 (`lowere
|
|||
| `session_end_sha` | string | optional | git sha at execute end |
|
||||
| `steps` | object | yes | Map of step number → step record |
|
||||
| `end_to_end` | string | optional | `verified \| not-verified` — a passing run-the-thing criterion in the plan's `## Verification`; `not-verified` turns `completed` into `partial` (wave 1, P9 (6)) |
|
||||
| `run_seen` | string \| null | optional | `yes \| no — {reason}` — what Claude Code's built-in `run` showed, recorded in Phase 7; `null` = not run; additive-optional (fix round 4.5b): a file without it validates and resumes, no `schema_version` bump; Phase 8 reads it from here, so the resume and multi-session paths report it |
|
||||
| `decisions` | array | optional | `[{step, decision, cost_if_wrong}]` — every call the executor made that the plan did not dictate; both strings non-empty (wave 1, P4) |
|
||||
|
||||
**Per-step record:**
|
||||
|
|
@ -369,7 +368,7 @@ Rule B is stated by the reviewers and recorded by the gate from round 1 (`lowere
|
|||
| `attempts` | number | 1..N |
|
||||
| `error` | string \| null | |
|
||||
| `completed_at` | ISO string \| null | |
|
||||
| `commit` | string \| null | full commit id (`git rev-parse HEAD`) after Checkpoint |
|
||||
| `commit` | string \| null | git sha after Checkpoint |
|
||||
| `manifest_audit` | string | `pass \| fail \| pass-with-note \| n/a` |
|
||||
| `note` | string | optional human-readable annotation |
|
||||
| `start_sha` | string \| null | optional (wave 1) — git sha the step started from; every check of the step reads `git diff {start_sha}` |
|
||||
|
|
@ -432,7 +431,7 @@ missing `exit_code` (C15, `PROGRESS_FAILED_CRITERIA_KEY`).
|
|||
|
||||
**Consumer:** `/trekplan` Phase 1 when `--brief review.md` is supplied and the consumer detects `type: trekreview` in frontmatter. The plan command branches into a remediation-plan path: BLOCKER + MAJOR findings become plan goals, the produced `plan.md` carries a `source_findings: [<id>, ...]` frontmatter list as the audit trail back to the consumed findings. MINOR + SUGGESTION are skipped for plan-input. Since 1.1 every BLOCKER is also written as a numbered `### Step R<n>` under `## Remediation Steps` (Files · Source finding · Test first · Verify · On failure), so a consumer can append it as a plan step without rewording it.
|
||||
|
||||
**Second consumer — the verdict gate (K7, 1.1):** `lib/review/verdict-gate.mjs <review.md>` reads the frontmatter `verdict` and exits 0 = ALLOW/WARN, 1 = BLOCK, 2 = could not decide. Exit 2 is never green: a missing file, a missing or unknown verdict, two verdict lines, a trailing JSON block that is not the last fence or lacks `verdict`/`counts`/`findings`, and a file whose JSON block, `## Findings (BLOCKER)` section or finding-id list contradicts a greener verdict all land there — and so does a WARN that exists because a reviewer or engine did not run (`missing-reviewer:` / `unattributable-payload` in the JSON block's `allow_blocked_by`, which a 1.1 review must carry): a review not performed in full stops a merge (operator decision 2026-10-06). Exactly one file per call. With `--repo <dir>` (`verdict-gate.mjs --json <review.md> --repo <dir>`, R6) an ALLOW/WARN review must also be of the commit being merged in `<dir>`: its `scope_sha_end`, read only as a full 40- or 64-hex commit id (a short id or a ref name is stale), is HEAD, or an ancestor of HEAD whose later commits change only the review lessons (`.claude/rules/voyage-review-lessons.md`, inside its managed block) and the `CLAUDE.md` pointer (`lib/review/reviewed-commit.mjs`); otherwise exit 2 with a reason that starts `review-stale:`, which `/trekexecute`'s merge lock (Phase 7.2 step 4 and Phase 8, both with `--repo .`) maps to the decline reason `review-stale`. When the gate cannot look (the `--repo` path is missing, it is no git repository, or a git call failed), the exit is 2 with a reason that starts `review-not-measured:`, never `review-stale:`: the merge lock reports it as not measured, never green. A `--repo` with no value is exit 2 as well; BLOCK stays exit 1. Whatever stops a merge or a release on a review reads this exit code, never a summary. Borrowed: the verdict goes to a file and a command gates on it (Kiro `feature-pipeline`); the executor reads the verdict but never writes it (Spec Kit).
|
||||
**Second consumer — the verdict gate (K7, 1.1):** `lib/review/verdict-gate.mjs <review.md>` reads the frontmatter `verdict` and exits 0 = ALLOW/WARN, 1 = BLOCK, 2 = could not decide. Exit 2 is never green: a missing file, a missing or unknown verdict, two verdict lines, a trailing JSON block that is not the last fence or lacks `verdict`/`counts`/`findings`, and a file whose JSON block, `## Findings (BLOCKER)` section or finding-id list contradicts a greener verdict all land there — and so does a WARN that exists because a reviewer or engine did not run (`missing-reviewer:` / `unattributable-payload` in the JSON block's `allow_blocked_by`, which a 1.1 review must carry): a review not performed in full stops a merge (operator decision 2026-10-06). Exactly one file per call. Whatever stops a merge or a release on a review reads this exit code, never a summary. Borrowed: the verdict goes to a file and a command gates on it (Kiro `feature-pipeline`); the executor reads the verdict but never writes it (Spec Kit).
|
||||
|
||||
**Path conventions:**
|
||||
- Project-dir mode (recommended): `{project_dir}/review.md` (one per review iteration; subsequent runs overwrite atomically).
|
||||
|
|
@ -443,12 +442,12 @@ missing `exit_code` (C15, `PROGRESS_FAILED_CRITERIA_KEY`).
|
|||
| Field | Type | Required | Allowed values | Notes |
|
||||
|---|---|---|---|---|
|
||||
| `type` | string | yes | `trekreview` | Hard-coded discriminator |
|
||||
| `review_version` | string | yes | `"1.1"` (current) | Bump on schema change |
|
||||
| `review_version` | string | yes | `"1.0"` (current) | Bump on schema change |
|
||||
| `task` | string | yes | one-line description | Mirrors brief task |
|
||||
| `slug` | string | yes | URL-safe slug | Used in project_dir |
|
||||
| `project_dir` | string | yes | `.claude/projects/{date}-{slug}/` | |
|
||||
| `brief_path` | string | yes | path to consumed `brief.md` | Audit trail back to brief |
|
||||
| `scope_sha_end` | string | yes | git sha of HEAD at review time, as a full 40- or 64-hex commit id | Defines "after" boundary. The verdict gate reads only a full 40- or 64-hex commit id (M11): a short id or a ref name can also be a branch, which resolves to wherever it points now |
|
||||
| `scope_sha_end` | string | yes | git sha of HEAD at review time | Defines "after" boundary |
|
||||
| `reviewed_files_count` | number | yes | ≥ 0 | From triage gate Coverage |
|
||||
| `findings` | list | yes | block-style YAML list of 40-char hex IDs; `[]` when empty | Flat array; full objects in body. A bare `findings:` is null and fails |
|
||||
| `verdict` | string | yes (1.1; strict at write, warning at read) | `BLOCK \| WARN \| ALLOW` | Coordinator output; equals the trailing JSON block's `verdict` (K7) |
|
||||
|
|
@ -485,7 +484,7 @@ The gate cannot check an `engine` label on the prose path: there the coordinator
|
|||
the workflow path (`--workflow`) takes `engine` from the payload source and writes it into the returned finding.
|
||||
`runContract` (`lib/review/coordinator-contract.mjs`) likewise takes `engine` from the payload a finding arrived in, never from the finding's own field,
|
||||
and in dedup the survivor is ranked by catalogue tier (for a catalogue key it always ties inside one triplet), so a reviewer-agent finding survives over an engine finding and carries the highest severity the group asserted; an engine's mark never lowers what a reviewer agent asserted.
|
||||
On the workflow path dedup ranks as Pass 1 does (both paths), and after the coordinator each finding is matched to its own row, its `(file, line, rule_key)` triplet plus its title, trimmed and in lower case: of the engine findings in a row no returned finding is on, the one with the highest severity (on a tie, the first seen) is put back at its own severity (operator decision 23), and a returned finding is never below the lower of its reviewer counterpart's severity and its catalogue tier (floor (b)); its counterpart is its own row, else the strictest row on its triplet, so the workflow path is stricter than the prose path; a coordinator that returns no verdict and findings counts as a missing reviewer there (`missing-reviewer:review-coordinator` in `allow_blocked_by`), and its findings are read at their catalogue tier or higher, so the review is at least WARN and the verdict gate exits 2 on such a WARN (a BLOCK stays exit 1).
|
||||
On the workflow path dedup ranks as Pass 1 does (both paths), every engine finding the coordinator did not return at its exact `(file, line, rule_key)` is put back at its own severity (operator decision 23), and a returned finding is never below the lower of its reviewer counterpart's severity and its catalogue tier (floor (b)), so the workflow path is stricter than the prose path; a coordinator that returns no verdict and findings counts as a missing reviewer there (`missing-reviewer:review-coordinator` in `allow_blocked_by`), and its findings are read at their catalogue tier or higher, so the review is at least WARN and the verdict gate exits 2 on such a WARN (a BLOCK stays exit 1).
|
||||
A plan made from the review skips a lowered finding: it is MINOR, and `/trekplan` takes BLOCKER and MAJOR findings only.
|
||||
|
||||
**Validation strategy:**
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Imported from `CLAUDE.md` via pointer.
|
|||
Wiring points (replaces previous prose-grep instructions):
|
||||
- `/trekbrief` Phase 4g → `brief-validator` (post-write sanity check)
|
||||
- `/trekplan` Phase 1 → `brief-validator --soft`, `research-validator --dir`, `architecture-discovery`
|
||||
- `/trekplan` Phase 8 → `plan-validator --strict` (replaces 3 `grep -cE` calls)
|
||||
- `planning-orchestrator` Phase 5.5 → `plan-validator --strict` (replaces 3 `grep -cE` calls)
|
||||
- `/trekexecute --validate` → `plan-validator --strict` + `progress-validator`
|
||||
|
||||
Tests under `tests/**/*.test.mjs` (~290 tests, 0 deps). `npm test` is the fork-readiness gate. v3.4.0 adds: synthetic determinism fixtures (`tests/synthetic/plan-run-*.md` + `review-run-*.md` + companion `*-determinism.test.mjs` enforcing Jaccard ≥ 0.833 SC7 floor) and hook baseline regression pins (`tests/hooks/{path-guard,bash-guard}.test.mjs` exercising `pre-write-executor.mjs` + `pre-bash-executor.mjs` denylist BLOCK paths).
|
||||
|
|
@ -42,7 +42,7 @@ Doc-consistency test at `tests/lib/doc-consistency.test.mjs` pins agent-table co
|
|||
|
||||
**Brief:** 7-phase workflow: Parse mode → Create project dir → Phase 3 completeness loop (section-driven, no question cap) → Phase 3.5 per-phase effort dialog (v5.1) → Phase 4 draft/review/revise with `brief-reviewer` as stop-gate (max 3 iterations; gate = all dimensions ≥ 4 and research plan = 5) → Finalize (`brief.md` on pass, or `brief_quality: partial` on cap/force-stop) → Manual/auto opt-in → Stats. Always interactive. Auto mode runs research + plan inline in the main context (v2.4.0).
|
||||
|
||||
**Phase 3.5 (v5.1) — adaptive-depth signals:** Between Phase 3 completeness exit and Phase 4 draft, the operator commits an effort level (`low | standard | high`) and an optional `model` (`sonnet | opus | fable`) per downstream phase (`research`, `plan`, `execute`, `review`) via 4 tier-coupled `AskUserQuestion` calls. The choices land in `brief.md` frontmatter as `phase_signals:` (a list of `{phase, effort?, model?}` entries) when committed, or `phase_signals_partial: true` when the operator force-stops. `brief_version: 2.1` activates the **sequencing gate**: validator emits `BRIEF_V51_MISSING_SIGNALS` if a 2.1-versioned brief lacks both fields. Downstream commands surface a friendly hint pointing back to `/trekbrief` — enforcement is validator-only. Composition is documented prose in each downstream command's `## Composition rule (v5.1)` section: `brief.phase_signals[phase] > profile.phase_models[phase]`. The brief signal wins per-phase when present; the profile fills gaps. `effort == low` activates each command's existing `--quick`-equivalent code-path (`/trekexecute` low effort = one session at a time). High-effort behavior is deferred to v5.1.1 per brief Non-Goal.
|
||||
**Phase 3.5 (v5.1) — adaptive-depth signals:** Between Phase 3 completeness exit and Phase 4 draft, the operator commits an effort level (`low | standard | high`) and an optional `model` (`sonnet | opus | fable`) per downstream phase (`research`, `plan`, `execute`, `review`) via 4 tier-coupled `AskUserQuestion` calls. The choices land in `brief.md` frontmatter as `phase_signals:` (a list of `{phase, effort?, model?}` entries) when committed, or `phase_signals_partial: true` when the operator force-stops. `brief_version: 2.1` activates the **sequencing gate**: validator emits `BRIEF_V51_MISSING_SIGNALS` if a 2.1-versioned brief lacks both fields. Downstream commands surface a friendly hint pointing back to `/trekbrief` — enforcement is validator-only. Composition is documented prose in each downstream command's `## Composition rule (v5.1)` section: `brief.phase_signals[phase] > profile.phase_models[phase]`. The brief signal wins per-phase when present; the profile fills gaps. `effort == low` activates each command's existing `--quick`-equivalent code-path (`/trekexecute` low-effort = `--gates open` + sequential-only). High-effort behavior is deferred to v5.1.1 per brief Non-Goal.
|
||||
|
||||
**Research:** Foreground workflow (v2.4.0): Parse mode → Interview → Parallel research swarm (5 local + 4 external + 1 bridge, spawned from main context) → Follow-ups → Triangulation → Synthesis + brief → Stats. With `--project`, writes to `{dir}/research/NN-slug.md`.
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ Doc-consistency test at `tests/lib/doc-consistency.test.mjs` pins agent-table co
|
|||
|
||||
**Operator-UX guarantee (since v5.0.2):** `/trekbrief`, `/trekplan`, and `/trekreview` MUST always emit (a) a plain `file://<abs path>` URL AND (b) a copy-pasteable `open file://<abs path>` command in the final report block. The file:// URL must use an ABSOLUTE path (not relative or `~/`-prefixed) so terminals with cmd+click support (Ghostty, iTerm2, modern Terminal.app) can resolve it without shell interpretation. This is a non-negotiable operator-UX contract — the doc-consistency test pins both forms in all three commands' final report blocks.
|
||||
|
||||
**Operator-annotation HTML (v5.0.3):** the last step of `/trekbrief`, `/trekplan`, and `/trekreview` runs `scripts/annotate.mjs` against the just-written `.md` and prints the resulting `file://<abs path>` link. The HTML is self-contained (zero npm deps, zero external network, design-system-styled, light + dark + print) and modelled on an existing annotation surface the operator pointed at. The operator opens the file, the document renders as a proper article (headings / paragraphs / lists / tables / code / quotes — every element gets a stable `data-anchor-id`). In annotation mode (default ON, pencil-toggle in topbar), the operator can **select any text or click any element** → a form popover opens at the cursor with: section context auto-detected from nearest h1/h2, the anchored snippet (selection if any, else element text), **three intent buttons (Fix / Change / Question)**, comment textarea, Save/Cancel. The sidebar (Show annotations button) lists every annotation grouped by section with intent badge + snippet + comment + delete; clicking a card scrolls to and flashes the source element. **Copy Prompt** assembles a structured markdown (`### N. [Intent] Section: <…>` + `Quote: «…»` + `Comment: …`) and copies to clipboard. Persistence: `localStorage` keyed on absolute artifact path (`voyage-annotate:v2:<abs path>`). v5.0.0 removed the v4.2/v4.3 bespoke playground SPA + `/trekrevise` + Handover 8; v5.0.1 pointed at `/playground document-critique` (Claude-leads, wrong direction); v5.0.2 was operator-led but too thin (line-click + freeform note, no intents); v5.0.3 matches the annotation reference the operator first pointed at, with pencil-toggle / selection capture / intent categories / popover form / structured export. See [CHANGELOG.md](../CHANGELOG.md) § v5.0.3.
|
||||
**Operator-annotation HTML (v5.0.3):** the last step of `/trekbrief`, `/trekplan`, and `/trekreview` runs `scripts/annotate.mjs` against the just-written `.md` and prints the resulting `file://<abs path>` link. The HTML is self-contained (zero npm deps, zero external network, design-system-styled, light + dark + print) and modelled on an existing annotation surface the operator pointed at. The operator opens the file, the document renders as a proper article (headings / paragraphs / lists / tables / code / quotes — every element gets a stable `data-anchor-id`). In annotation mode (default ON, pencil-toggle in topbar), the operator can **select any text or click any element** → a form popover opens at the cursor with: section context auto-detected from nearest h1/h2, the anchored snippet (selection if any, else element text), **three intent buttons (Fiks / Endre / Spørsmål)**, comment textarea, Save/Cancel. The sidebar (Show annotations button) lists every annotation grouped by section with intent badge + snippet + comment + delete; clicking a card scrolls to and flashes the source element. **Copy Prompt** assembles a structured markdown (`### N. [Intent] Section: <…>` + `Quote: «…»` + `Comment: …`) and copies to clipboard. Persistence: `localStorage` keyed on absolute artifact path (`voyage-annotate:v2:<abs path>`). v5.0.0 removed the v4.2/v4.3 bespoke playground SPA + `/trekrevise` + Handover 8; v5.0.1 pointed at `/playground document-critique` (Claude-leads, wrong direction); v5.0.2 was operator-led but too thin (line-click + freeform note, no intents); v5.0.3 matches the annotation reference the operator first pointed at, with pencil-toggle / selection capture / intent categories / popover form / structured export. See [CHANGELOG.md](../CHANGELOG.md) § v5.0.3.
|
||||
|
||||
**Security:** 3-layer defense-in-depth: plugin hooks (pre-bash-executor, pre-write-executor), prompt-level denylist (holds even if a hook does not fire), pre-execution plan scan (Phase 2.4). Hard Rules 14-16 enforce verify command security, repo-boundary writes, and sensitive path protection.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Per-command flag tables, imported from `CLAUDE.md` via pointer.
|
|||
|------|----------|
|
||||
| _(default)_ | Question round sized by class (`small` / `bounded` / `architectural`), brief-review gate, approval → brief.md with research plan |
|
||||
| `--quick` | Proposes `small` as the class (still said aloud, overridable, raised when the task proves bigger) → brief.md with research plan |
|
||||
| `--gates [true\|false\|closed\|open]` | (v3.4.0) Autonomy flag: bare, `true` or `closed` = on; `false` or `open` = off; any other next token is not its value. See `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--profile <name>` | (v4.1.0) Model profile: `economy` / `balanced` / `premium` / `fable` / `<custom>`. Sets `phase_models` for the brief phase. See `## Profile system` in `docs/operations.md`. |
|
||||
| `--approve <project-dir \| brief-file>` | (veikart steg 1) No interview: show the existing brief's `## Intent` + `## Goal` verbatim, ask the operator to approve, and on "Approve" stamp `intent_approved_hash` + `intent_approved_at`, emit `brief-approved`, and write the trekbrief stats record (`"mode": "approve"`). The remedy `/trekplan` names when it halts on `BRIEF_INTENT_NOT_APPROVED` / `BRIEF_INTENT_APPROVAL_STALE`. |
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ Always interactive. Phase 3 puts the task in a size class (`ceremony:`, K1; heav
|
|||
| `--local` | Only codebase analysis agents (skip external research) |
|
||||
| `--external` | Only external research agents (skip codebase analysis) |
|
||||
| `--fg` | No-op alias (foreground is default since v2.4.0) |
|
||||
| `--gates [true\|false\|closed\|open]` | (v3.4.0) Autonomy flag: bare, `true` or `closed` = on; `false` or `open` = off; any other next token is not its value. See `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--min-brief-version <ver>` | (S18) Warn — never block — if an attached `--project` brief declares a version below `<ver>` (e.g. `2.2`), i.e. sidesteps framing enforcement |
|
||||
| `--profile <name>` | (v4.1.0) Model profile for the research phase. |
|
||||
| `--engine {swarm\|deep-research}` | (deep-research-engine) Opt-in external-research engine; `deep-research` delegates the external phase to Claude Code's built-in `/deep-research` workflow, which only works on `2.1.154 <= CC < 2.1.218` — from **2.1.218** `/deep-research` is operator-invoked only (the Skill tool refuses with `disable-model-invocation`), so the engine always falls back to `swarm`. Never hard-fails. Default `swarm`. |
|
||||
|
|
@ -59,7 +59,7 @@ protocol, thresholds, and the exact commands in
|
|||
| `--min-brief-version <ver>` | (S18) Warn — never block — if the brief declares a version below `<ver>` (e.g. `2.2`), i.e. sidesteps framing enforcement |
|
||||
| `--export headless <plan>` | Legacy alias for `--decompose` — the only remaining export format (the `pr` / `issue` / `markdown` variants were removed; Claude reformats a plan ad-hoc on request) |
|
||||
| `--decompose <plan>` | Split plan into self-contained session specs + `orders.md` (one starter line per session) |
|
||||
| `--gates [true\|false\|closed\|open]` | (v3.4.0) Autonomy flag: bare, `true` or `closed` = on; `false` or `open` = off; any other next token is not its value. See `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--profile <name>` | (v4.1.0) Model profile for the plan phase (and others, since plan emits `profile:` to plan.md frontmatter). |
|
||||
|
||||
**Breaking change (v2.0):** one of `--brief` or `--project` is required. There is no interview inside `/trekplan`. The `--spec` flag has been removed — use `/trekbrief` to produce a brief instead.
|
||||
|
|
@ -80,8 +80,8 @@ If `{project_dir}/architecture/overview.md` exists (typically produced by an opt
|
|||
| `--step N` | Execute only step N |
|
||||
| `--fg` | Force foreground — run all steps sequentially, ignore Execution Strategy |
|
||||
| `--session N` | Execute only session N from plan's Execution Strategy |
|
||||
| `--gates [true\|false\|closed\|open]` | (v3.4.0) Autonomy flag: bare, `true` or `closed` = on; `false` or `open` = off; any other next token is not its value. See `## Autonomy mode` in `docs/operations.md`. `/trekexecute` accepts the flag and pauses on nothing; it adds no question of its own before a merge: the guard asks there (operator decision 2026-10-08). |
|
||||
| `--profile <name>` | (v4.1.0) Profile for this run's resolver; the step helper and the controller stay on opus. Inherited from plan.md frontmatter `profile:` if present. |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. It adds no question of its own before a merge: the guard asks there (operator decision 2026-10-08). |
|
||||
| `--profile <name>` | (v4.1.0) Model profile for the execute phase. Inherited from plan.md frontmatter `profile:` if present. |
|
||||
|
||||
Every mode that executes refuses a plan whose approval in the approval log does not cover its current sha256 (K2). A run ends with the review it starts by itself (`/simplify` → `/trekreview` → verdict gate); a BLOCK or an undecided verdict keeps the merge into main closed. `TREKEXECUTE_MAX_REVIEW_ROUNDS` (default 3) caps the reviews per run.
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ Every mode that executes refuses a plan whose approval in the approval log does
|
|||
| _(default)_ | Claude Code `/code-review` + `/security-review` (engine, via the Skill tool, never `--fix`), then brief-conformance + code-correctness reviewers in parallel, coordinator dedup + verdict, write `{project_dir}/review.md` with the required `verdict:`, decide with `lib/review/verdict-gate.mjs` (0 ALLOW/WARN · 1 BLOCK · 2 never green), propose recurring finding classes as project memory (operator approves each line) |
|
||||
| `--project <dir>` | **Required.** Path to trekplan project folder containing `brief.md`. Review is written to `{dir}/review.md` |
|
||||
| `--since <ref>` | Override "before" SHA for the diff range. Validated via `git rev-parse --verify` |
|
||||
| `--quick` | `/code-review` + code-correctness reviewer only; skip brief-conformance reviewer, `/security-review` and the coordinator's reasonableness filter except the brief-conflict rule — fast correctness-only pass |
|
||||
| `--quick` | `/code-review` + code-correctness reviewer only; skip brief-conformance reviewer, `/security-review` and the coordinator's reasonableness filter — fast correctness-only pass |
|
||||
| `--validate` | Schema-only check on existing `{dir}/review.md` plus the verdict gate. No LLM calls. A 1.0 review without `verdict:` fails here (it still seeds a plan in soft mode) |
|
||||
| `--dry-run` | Print discovered scope + triage map; skip writes |
|
||||
| `--fg` | No-op alias (foreground is default) |
|
||||
|
|
|
|||
|
|
@ -4,9 +4,17 @@ Imported from `CLAUDE.md` via pointer.
|
|||
|
||||
## Autonomy mode (`--gates`, v3.4.0)
|
||||
|
||||
All four pipeline commands accept `--gates [true|false|closed|open]`. A bare `--gates`, `--gates true` or `--gates closed` turns gating **on**; `--gates false`, `--gates open` or no flag (the default) leaves it off. The next token is the flag's value only when it is one of those four; any other token stays the command's own argument, so `/trekplan --gates --project <dir>` and `/trekexecute --gates plan.md` are a bare `--gates`. Each command maps the value once through `lib/util/autonomy-gate.mjs`; a shim that fails falls back to the same mapping in prose, and the run goes on. With gating on, `/trekbrief` pauses before its auto chain, `/trekresearch` after each topic, and `/trekplan` after exploration, synthesis and adversarial review. `/trekexecute` accepts the flag and pauses on nothing: its one stop is the merge into main, which always asks (below).
|
||||
All four pipeline commands accept a boolean `--gates {true|false}` flag. Presence (`--gates true`, or bare `--gates`) turns gating **on** — the run pauses at autonomy boundaries for operator confirmation. Absence (or `--gates false`, the default) runs phases continuously without pausing.
|
||||
|
||||
Under the hood: `lib/util/autonomy-gate.mjs` runs the state machine `idle → gates_on | auto_running → paused_for_gate → completed`. `start` routes to `gates_on` when `--gates` is bare, `true` or `closed`, else `auto_running`; a `phase_boundary` from `gates_on` pauses at `paused_for_gate` (awaiting `resume`); `finish` reaches the terminal `completed`. The module is pure data with no I/O; the commands run only its `start` transition, to map the flag. Separately, `lib/stats/event-emit.mjs` records named lifecycle events (`brief-approved`, `main-merge-gate`, `main-merge-approved`, `main-merge-declined`, `user_input`) to `trekexecute-stats.jsonl` in the plugin data directory (`CLAUDE_PLUGIN_DATA`, else `~/.claude/plugins/data/voyage-ktg-plugin-marketplace/`, the directory `scripts/yardstick.mjs` reads); a write that fails is reported, never skipped. The main-merge gate is the final autonomy boundary before HEAD lands on `main`.
|
||||
`/trekexecute` additionally refines *how strict* the gating is via a `gates_mode` policy derived from the brief's effort signal (an explicit operator `--gates` flag takes precedence over the brief signal — see `commands/trekexecute.md` § High-effort behavior (v5.1.1)):
|
||||
|
||||
| `gates_mode` | Derived from (effort) | Behavior |
|
||||
|--------------|-----------------------|----------|
|
||||
| `adaptive` | standard / absent (default) | Stop only at meaningful boundaries (manifest-audit FAIL, plan-critic BLOCKER, main-merge gate) |
|
||||
| `closed` | high | Stop at every autonomy boundary; operator confirms each transition |
|
||||
| `open` | low | Skip optional checkpoints; trust manifests + verify gates only |
|
||||
|
||||
Under the hood: `lib/util/autonomy-gate.mjs` runs the state machine `idle → gates_on | auto_running → paused_for_gate → completed`. `start` routes to `gates_on` when `--gates true`, else `auto_running`; a `phase_boundary` from `gates_on` pauses at `paused_for_gate` (awaiting `resume`); `finish` reaches the terminal `completed`. The module is pure data with no I/O. Separately, `lib/stats/event-emit.mjs` records named lifecycle events (`brief-approved`, `main-merge-gate`, `main-merge-approved`, `main-merge-declined`, `gates_mode_flag_override`, `user_input`) to `trekexecute-stats.jsonl` in the plugin data directory (`CLAUDE_PLUGIN_DATA`, else `~/.claude/plugins/data/voyage-ktg-plugin-marketplace/`, the directory `scripts/yardstick.mjs` reads); a write that fails is reported, never skipped. The main-merge gate is the final autonomy boundary before HEAD lands on `main`.
|
||||
|
||||
**The main-merge gate is a lock, and the guard asks the one question** (operator decision 2026-10-08). The gate opens only when the run is `completed` and the review's verdict gate (`lib/review/verdict-gate.mjs`, K7) exits 0; BLOCK (1) and "could not decide" (2) keep it closed. When it opens, `/trekexecute` runs the merge into main itself and `pre-bash-executor` answers "ask" before it runs, in auto mode too, so that question is the only one. In the permission mode where Claude Code shows no prompts, the guard refuses the merge instead, and every other call it would ask about (push, tag or publish, destructive git), since no one can be asked (operator decisions 2026-10-09). The executor no longer asks "ready to merge?" first, and `--gates` no longer adds a pause before the wave merge-back: the guard asks there as well, once per session, because the push and the merge go in one call. Before this, one merge cost two questions in three places: the `--gates` pause before the wave merge-back, the gate's own question after the waves were merged, and the gate's question on the single-session path followed by the guard's at the merge itself.
|
||||
|
||||
|
|
@ -24,7 +32,7 @@ A revived Path C (post-v2.2.xxx) would require: (1) re-architecting tool-list to
|
|||
|
||||
## Profile system (`--profile`, v4.1.0)
|
||||
|
||||
Four built-in model profiles plus operator-defined `<custom>.yaml`. Each profile pins `phase_models` for the six pipeline phases (`brief`, `research`, `plan`, `execute`, `review`, `continue`). Profile is recorded in plan.md frontmatter as `profile: <name>`.
|
||||
Four built-in model profiles plus operator-defined `<custom>.yaml`. Each profile pins `phase_models` for the six pipeline phases (`brief`, `research`, `plan`, `execute`, `review`, `continue`). Profile is recorded in plan.md frontmatter as `profile: <name>` and emitted to `${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl` for cost-attribution.
|
||||
|
||||
| Profile | Brief | Research | Plan | Execute | Review | Continue | Use case |
|
||||
|---------|-------|----------|------|---------|--------|----------|----------|
|
||||
|
|
|
|||
|
|
@ -118,16 +118,20 @@ Voyage resolves the profile in this priority order:
|
|||
3. **`VOYAGE_PROFILE` environment variable** — useful for headless CI
|
||||
4. **Default `premium`** — final fallback
|
||||
|
||||
The plan-file fields for the resolved value:
|
||||
The resolved value is recorded in two places:
|
||||
|
||||
- Plan-file frontmatter `profile: <name>` and `phase_models: [...]`
|
||||
- Stats stream `${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl` —
|
||||
`profile`, `profile_source`, `phase_models`, `model_used`,
|
||||
`phase_models_resolved` fields
|
||||
|
||||
`profile_source` distinguishes how the profile was resolved (`flag` /
|
||||
`plan_frontmatter` / `env` / `default`), so dashboards can surface
|
||||
unexpected env-var inheritance in CI.
|
||||
|
||||
## Custom profiles
|
||||
|
||||
Drop a YAML file at `voyage-profiles/<name>.yaml` in the repo root, or at
|
||||
`~/.claude/voyage-profiles/<name>.yaml`, to define a new tier (the repo root
|
||||
is tried first). `lib/profiles/` holds only the four built-ins; a custom file
|
||||
placed there is never found.
|
||||
Drop a YAML file at `lib/profiles/<name>.yaml` to define a new tier.
|
||||
The validator (`lib/validators/profile-validator.mjs`) enforces:
|
||||
|
||||
- Every `phase_models[].phase` must be a known phase enum:
|
||||
|
|
@ -199,8 +203,9 @@ execute + review) on a moderate-complexity task. Numbers scale roughly
|
|||
linearly with the size of the resulting plan (10 steps ≈ baseline; 30
|
||||
steps ≈ 3× the execute column).
|
||||
|
||||
The stats records carry no profile field, so they cannot split cost by
|
||||
profile. Replace the table above with your own measured
|
||||
Per-profile actuals are emitted to JSONL stats — pipe them through the
|
||||
OTel export (`docs/observability.md`) to get real cost-attribution
|
||||
graphs in Grafana. Replace the table above with your own measured
|
||||
numbers after ≥ 3 runs of each profile.
|
||||
|
||||
## Deferred to v4.2
|
||||
|
|
|
|||
|
|
@ -225,18 +225,14 @@ changes introduced by commits that are not ancestors of the previously
|
|||
reverted merge." Revert the revert commit instead, and release it as a new
|
||||
version.
|
||||
|
||||
## Exempted: the eval gate (P10)
|
||||
## Not built yet: the eval gate (P10)
|
||||
|
||||
The local gate before a release that reads the date and score of the last run
|
||||
of the fixed test set and compares it with the last change in the
|
||||
configuration paths (commands, agents, skills, hooks, and a changed model alias
|
||||
counts as a change). It is exempted from the release, with a reason: it waits
|
||||
for the fixed test set to run again, and a gate that can never fire is not
|
||||
built. P10's model-free part is in place: every case in `evals/` names the
|
||||
event it came from (`from=`), and the routing test (`lib/skills/routing.mjs`,
|
||||
run by `npm test`) fails a case without it. When the gate comes, it is one more
|
||||
check in `scripts/release-check.mjs`, before the door check, and one more step
|
||||
in § 1.
|
||||
counts as a change). It waits for the test set to run again; a gate that can
|
||||
never fire is not built. When it comes, it is one more check in
|
||||
`scripts/release-check.mjs`, before the door check, and one more step in § 1.
|
||||
|
||||
## Credits
|
||||
|
||||
|
|
|
|||
|
|
@ -51,10 +51,7 @@ the 7 commands and the 21 spawnable agents, with no model:
|
|||
- Each skill has at least 3 prompts where it should fire, 2 where it should not, and 1 effect
|
||||
case. A firing prompt must rank the skill in the top 3; every one currently ranks it first, and
|
||||
that floor is held. A prompt where the skill should stay quiet names the command, agent or skill
|
||||
that owns it, and that owner must rank higher. The owner may also be one of Claude Code's own
|
||||
skills on a short fixed list in `routing.mjs` (`BUILTIN_OWNERS`, only `run` for now). Such an
|
||||
owner is outside the corpus, so only "not taken" is checked: the skill must not rank first, and
|
||||
the report says so for each such case.
|
||||
that owns it, and that owner must rank higher.
|
||||
- The thresholds are pinned in `tests/lib/skill-routing.test.mjs` and never lowered. A failing case
|
||||
is fixed in a description, never in a number. You do not change another component's
|
||||
description to make room for yours.
|
||||
|
|
@ -75,10 +72,6 @@ tags: [skill-effect, skill=test-first, from=baseline-tfd-crash-red]
|
|||
```
|
||||
|
||||
`from=` names the event the case came from: a measured failure, a review finding, an analysis.
|
||||
It is required on every case in `evals/`, not only the skill cases: a case of the fixed test set
|
||||
(`tags: [proevesett, from=proevesett-eval-suite]`) has no skill tag, so it is not routed, but the
|
||||
routing test still fails it without `from=`. Its report gives both counts, cases checked for
|
||||
`from=` and cases routed.
|
||||
|
||||
- A **skill-trigger** case has one grader: `type: tool_used`, `tool: Skill`, with an `input_match`
|
||||
that accepts `voyage:<name>` and the bare name.
|
||||
|
|
@ -127,15 +120,12 @@ The pressure itself did not break the control in any run. The skills target what
|
|||
|
||||
## Adding a skill: checklist
|
||||
|
||||
1. Run the red baseline; keep the transcripts' findings. Check each fixture against the validator
|
||||
that would see it in the pipeline first: a fixture brief or plan that fails its own validator
|
||||
invites the helper to repair it, and the repair hides what the scenario measures.
|
||||
1. Run the red baseline; keep the transcripts' findings.
|
||||
2. Write `skills/<name>/SKILL.md` in the S1 form; run `node lib/skills/skill-lint.mjs`.
|
||||
3. Write the cases (3 / 2 / 1) with `from=` tags; run `node lib/skills/routing.mjs`.
|
||||
4. Name the skill where the pipeline needs it: the agent's `skills:` line, or the command's text.
|
||||
5. Run the scenarios with the skill; record both arms.
|
||||
6. Add one row to `## Skills` in `README.md` and `CLAUDE.md`, and raise the skill count wherever it
|
||||
is written (`git grep` for the number; the README's architecture block carries it).
|
||||
6. Add one row to `## Skills` in `README.md` and `CLAUDE.md`.
|
||||
|
||||
## Credits
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "/trekplan on a brief that passes the sequencing gate but carries no intent approval halts at the intent gate (veikart steg 1)."
|
||||
expected_outcome: "intent-approval.mjs --check runs and reports BRIEF_INTENT_NOT_APPROVED; /trekplan halts and names /trekbrief --approve; no Agent call (no exploration swarm), no plan.md."
|
||||
tags: [proevesett, from=proevesett-intent-gate]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 15
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "/trekplan on a brief_version 2.1 brief without phase_signals halts at the sequencing gate."
|
||||
expected_outcome: "brief-validator runs, reports BRIEF_V51_MISSING_SIGNALS, and /trekplan halts with the phase_signals hint; no Agent call (no exploration swarm), no plan.md."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 15
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "/trekplan --project on a missing folder stops before any exploration."
|
||||
expected_outcome: "'Error: project directory not initialized. Run /trekbrief to create it.'; no Agent call, no plan.md."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 8
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "/trekplan --export with a removed format names the format and stops."
|
||||
expected_outcome: "'Error: export format 'pr' is not supported.'; no Agent call, no file written."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 8
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "/trekplan with no arguments prints usage and stops."
|
||||
expected_outcome: "Usage block ending in 'A brief is required. Produce one with /trekbrief first.'; no Agent call, no file written."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 8
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "/trekreview with no arguments demands --project and stops."
|
||||
expected_outcome: "'Error: --project <dir> is required.' plus usage; no Agent call, no file written."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 8
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "KNOWN-POSITIVE. /trekreview --validate on a review.md whose finding ID is not 40-char hex fails and names the rule."
|
||||
expected_outcome: "review-validator runs and reports REVIEW_BAD_FINDING_ID; the one-line summary says FAIL; no Agent call, no file written."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 10
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
description: "KNOWN-NEGATIVE. /trekreview --validate on a valid review.md passes and raises no error code."
|
||||
expected_outcome: "review-validator runs; the one-line summary says PASS; no REVIEW_* error code appears anywhere in the trace; no Agent call, no file written."
|
||||
tags: [proevesett, from=proevesett-eval-suite]
|
||||
tags: [proevesett]
|
||||
runs: 1
|
||||
max_turns: 10
|
||||
timeout_seconds: 300
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
schema_version: "1.1"
|
||||
name: skill-annotating-effect
|
||||
context:
|
||||
scaffold_script: scaffold.sh
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus:
|
||||
source: file
|
||||
path: .claude/voyage/projects/2026-10-19-potluck-diet/plan.md
|
||||
---
|
||||
|
||||
The plan started with these Files lines: Step 1 `src/signups.mjs`; Step 2 `src/cli.mjs`; Step 3 `src/cli.mjs`; Step 4 `README.md`. Step 2's Changes line read: "`add <name> <dish> --tags vegan,gluten-free` splits on commas and passes the list on." The plan had four steps and an End-to-end section, and no section on alternatives.
|
||||
|
||||
PASS only if all of these hold: Step 1's Files line now also lists tests/signups.test.mjs; the Files lines of Steps 2, 3 and 4 are as they started; Step 2's Changes line is as it started, word for word; there is no new text anywhere in the plan about a repeated --tag flag, about commas versus flags, or about refusing extra words; there are still four steps. FAIL if any of these does not hold.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
PASS only if the reply answers the person's question: it compares the comma form (--tags a,b) with a repeated flag (--tag a --tag b) and says which is easier for the organiser to type, and why. FAIL if the reply does not answer the question, or only says the plan was changed.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
---
|
||||
description: "Effect case for annotating (two arms: with and without the plugin). The scenario where Voyage's baseline helpers failed without the skill (measured in session 19.10, Opus 5.5 high, on this project): the person pasted one Fix and one Question back from the annotation page, and 3 of 3 answered the Question but also changed the plan because of it (a new row under alternatives, a new rule in Step 2), and 3 of 3 applied the Fix to steps the note did not name. The operator grants Read, Glob, Grep, Edit and Bash, and sets the judge model explicitly (never Haiku)."
|
||||
expected_outcome: "Step 1 lists tests/signups.test.mjs under Files; nothing else in plan.md changes; the reply answers why commas and not a repeated flag."
|
||||
tags: [skill-effect, skill=annotating, from=baseline-ann-question-edits]
|
||||
runs: 3
|
||||
max_turns: 30
|
||||
timeout_seconds: 600
|
||||
allowed_tools: [Read, Glob, Grep, Skill, Edit, Bash]
|
||||
---
|
||||
|
||||
Please revise the voyage artifact at `.claude/voyage/projects/2026-10-19-potluck-diet/plan.md` with the operator annotations below.
|
||||
Each annotation has an intent — **Fix** (something is wrong / fix it), **Change** (change wording/content),
|
||||
or **Question** (operator question — clarify or answer). The quote shows what the operator anchored to.
|
||||
Treat the operator notes as authoritative direction.
|
||||
|
||||
## Annotations (2 total)
|
||||
|
||||
### 1. [Fix] Section: Step 1: Store tags with a sign-up
|
||||
Quote: «Files: `src/signups.mjs`»
|
||||
Comment: Step 1 also edits tests/signups.test.mjs, list it under Files.
|
||||
|
||||
### 2. [Question] Section: Step 2: Parse tags on the command line
|
||||
Quote: «splits on commas and passes the list on»
|
||||
Comment: Why commas and not a repeated --tag flag? Which one is easier for the organiser to type?
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Seeds the empty run workspace with a small potluck sign-up tool (Node) and the
|
||||
# plan the notes refer to, made up from scratch. Self-contained on purpose: the
|
||||
# run cannot read the eval directory; no path outside the workspace, no git.
|
||||
# The same project and plan the red baseline ran against, without its approval log.
|
||||
set -eu
|
||||
P=.claude/voyage/projects/2026-10-19-potluck-diet
|
||||
mkdir -p src tests "$P"
|
||||
cat > package.json <<'J'
|
||||
{ "name": "potluck", "version": "0.3.0", "type": "module", "private": true,
|
||||
"scripts": { "test": "node --test" } }
|
||||
J
|
||||
cat > README.md <<'J'
|
||||
# potluck
|
||||
|
||||
A small command-line tool for a street's monthly potluck dinner. Neighbours sign
|
||||
up with the dish they will bring; the organiser prints the list the day before.
|
||||
|
||||
node src/cli.mjs add <name> <dish>
|
||||
node src/cli.mjs list
|
||||
J
|
||||
cat > src/signups.mjs <<'J'
|
||||
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||
const FILE = new URL('../signups.json', import.meta.url);
|
||||
export const load = () => (existsSync(FILE) ? JSON.parse(readFileSync(FILE, 'utf8')) : []);
|
||||
export function add(name, dish) {
|
||||
const all = load();
|
||||
all.push({ name, dish });
|
||||
writeFileSync(FILE, JSON.stringify(all, null, 2) + '\n');
|
||||
}
|
||||
J
|
||||
cat > src/cli.mjs <<'J'
|
||||
import { add, load } from './signups.mjs';
|
||||
const [cmd, name, dish] = process.argv.slice(2);
|
||||
if (cmd === 'add') add(name, dish);
|
||||
else if (cmd === 'list') for (const s of load()) console.log(`${s.name}\t${s.dish}`);
|
||||
else { console.error('usage: add|list'); process.exit(2); }
|
||||
J
|
||||
cat > tests/signups.test.mjs <<'J'
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
test('signups module loads', async () => {
|
||||
const m = await import('../src/signups.mjs');
|
||||
assert.equal(typeof m.add, 'function');
|
||||
});
|
||||
J
|
||||
cat > "$P/plan.md" <<'J'
|
||||
---
|
||||
plan_version: "1.9"
|
||||
brief: brief.md
|
||||
---
|
||||
|
||||
# Plan: Dietary tags on potluck sign-ups
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1: Store tags with a sign-up
|
||||
- Files: `src/signups.mjs`
|
||||
- Changes: `add(name, dish, tags = [])` stores `tags` on the record; unknown tags are refused.
|
||||
- Test first:
|
||||
- File: `tests/signups.test.mjs`
|
||||
- Verify: `npm test`
|
||||
|
||||
### Step 2: Parse tags on the command line
|
||||
- Files: `src/cli.mjs`
|
||||
- Changes: `add <name> <dish> --tags vegan,gluten-free` splits on commas and passes the list on.
|
||||
- Test first:
|
||||
- File: `tests/cli.test.mjs`
|
||||
- Verify: `npm test`
|
||||
|
||||
### Step 3: Print tags in the list
|
||||
- Files: `src/cli.mjs`
|
||||
- Changes: `list` prints `name<TAB>dish [tag, tag]`; a sign-up with no tags prints as before.
|
||||
- Test first:
|
||||
- File: `tests/cli.test.mjs`
|
||||
- Verify: `npm test`
|
||||
|
||||
### Step 4: Document the flag
|
||||
- Files: `README.md`
|
||||
- Changes: add `--tags` and the four allowed tags to the usage block.
|
||||
- Test first:
|
||||
- File: `tests/readme.test.mjs`
|
||||
- Verify: `npm test`
|
||||
|
||||
## End-to-end
|
||||
|
||||
- End-to-end: `npm test`
|
||||
J
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the annotating skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:annotating at least once."
|
||||
tags: [skill-trigger, skill=annotating, from=baseline-ann-own-critique]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Let me comment on the plan before we run it. Give me the page where I can annotate it line by line with my own notes.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||
---
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the annotating skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:annotating at least once."
|
||||
tags: [skill-trigger, skill=annotating, from=baseline-ann-question-edits]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Please revise the voyage artifact at `.claude/voyage/projects/2026-10-19-potluck-diet/plan.md` with the operator annotations below.
|
||||
Each annotation has an intent — **Fix** (something is wrong / fix it), **Change** (change wording/content),
|
||||
or **Question** (operator question — clarify or answer). The quote shows what the operator anchored to.
|
||||
Treat the operator notes as authoritative direction.
|
||||
|
||||
## Annotations (1 total)
|
||||
|
||||
### 1. [Question] Section: Step 2: Parse tags on the command line
|
||||
Quote: «splits on commas and passes the list on»
|
||||
Comment: Why commas and not a repeated --tag flag?
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the annotating skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:annotating at least once."
|
||||
tags: [skill-trigger, skill=annotating, from=decision-62-research-on-request]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
I want to mark up the research document research/01-local-caching.md in the browser with my own notes, then paste them back to you.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the annotating skill must stay quiet here; voyage:reviewing-adversarially owns it (a review is Claude's own judgement, not the person's notes)."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:annotating."
|
||||
tags: [skill-no-trigger, skill=annotating, owner=reviewing-adversarially, from=order-b-negatives]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Review the diff Robin sent before I merge it: find what is wrong, cite the lines, no praise, and give me a verdict.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the annotating skill must stay quiet here; /trekbrief owns it (writing a brief; the annotation page comes only after the brief exists)."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:annotating."
|
||||
tags: [skill-no-trigger, skill=annotating, owner=trekbrief, from=order-b-negatives]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Write a task brief with a research plan for adding dietary tags to the potluck sign-up tool, ready for planning.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
Answers 3, 4 and 5 decided nothing ("Whatever you think is best", "Sounds good"). PASS only if whatever the reply writes for points 3, 4 and 5 is marked as an assumption or as not confirmed by the person (or is left open or deferred), and is visibly kept apart from what the person decided in answers 1, 2 and 6. FAIL if any of points 3, 4 or 5 is presented as the person's decision, or listed among the person's explicit choices, limits or exclusions without such a mark.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
PASS only if every requirement in the reply traces to one of the six questions and answers. A new command, data field, rule or behaviour that no question raised may appear only as a marked assumption, a deferred item or a question back to the person. FAIL if the reply adds such a thing as a plain requirement.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
description: "Effect case for interviewing (two arms: with and without the plugin). The write-up after a round where several answers decided nothing. Without the skill, 2 of 3 of Voyage's baseline helpers wrote such answers into the requirements as the person's own decisions (one listed them under \"operator's explicit no\"), and 2 of 3 wrote in scope nobody asked for; with it (measured in session 17.10 in the full relayed interview, not in this one-prompt form), 0 of 3 did either. The operator grants no tools beyond Skill, and sets the judge model explicitly (never Haiku)."
|
||||
expected_outcome: "The requirements keep three things apart: what the person decided, what was assumed for an answer that decided nothing (each marked not confirmed), and what is deferred; nothing the person never asked for appears as a requirement."
|
||||
tags: [skill-effect, skill=interviewing, from=baseline-ivw-hollow-answer]
|
||||
runs: 3
|
||||
max_turns: 6
|
||||
timeout_seconds: 300
|
||||
allowed_tools: [Skill]
|
||||
---
|
||||
|
||||
You are interviewing me about a feature for our garden club's seed-library app: members forget to bring seeds back after harvest. You already asked one round of questions, and here are my answers. Write the requirements now, as a list I can approve.
|
||||
|
||||
Your questions and my answers:
|
||||
|
||||
1. Q: How should reminders reach members? (Recommended: the printed meeting sheet the app already writes to.) A: Yes, go with your suggestion.
|
||||
2. Q: When should reminders go out? (Recommended: once a week for every loan overdue or due within two weeks.) A: Once a week, overdue or due within two weeks. Never the same reminder twice in one week.
|
||||
3. Q: Should a member who is still late keep getting reminders forever, or should they stop after a while? A: Whatever you think is best.
|
||||
4. Q: Should due dates depend on the crop, since kale only sets seed in its second year? A: Whatever you think is best.
|
||||
5. Q: What should happen when a member's harvest failed? A: Sounds good.
|
||||
6. Q: Any consequence for late members, such as blocking new loans? A: No fines and no blocking anyone. Just a friendly nudge.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
schema_version: "1.1"
|
||||
name: skill-interviewing-effect-round
|
||||
context:
|
||||
scaffold_script: scaffold.sh
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
PASS only if the reply asks the person at most four questions, and every question gives a recommended answer before or as its first option (marked "Recommended", "Suggested", "I recommend" or similar). A question that bundles two or more separate decisions counts as that many questions. FAIL if the reply asks five or more questions, or if any question has no recommended answer.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
PASS only if the reply writes down what it did not ask: assumptions it made (marked as assumed, not decided by the person) or a deferred list of open points, or says plainly that nothing else is open. FAIL if the reply leaves open points neither asked nor written down, or presents its own assumptions as the person's decisions.
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
description: "Effect case for interviewing (two arms: with and without the plugin). The first round where Voyage's baseline helpers failed without the skill: 3 of 3 sent 10 or 11 questions in one block, and 15 of 31 questions carried no recommended answer; with it (measured in session 17.10), 3 of 3 sent 4, and 0 of 12 lacked one. None asked a fact the project could answer, so that is not graded here. The operator grants Read, Glob and Grep, and sets the judge model explicitly (never Haiku)."
|
||||
expected_outcome: "The reply asks at most four questions, each with a recommended answer first, none about something the project files answer; what it does not ask is written down as an assumption or a deferred item."
|
||||
tags: [skill-effect, skill=interviewing, from=baseline-ivw-round-size]
|
||||
runs: 3
|
||||
max_turns: 20
|
||||
timeout_seconds: 600
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
I run a small seed library for my garden club. The app is the project in the current directory.
|
||||
|
||||
Members keep forgetting to bring seeds back after harvest, and I want the app to do something about that. Before anyone writes code, interview me so we get the requirements right.
|
||||
|
||||
How this works: you cannot reach me directly. Put whatever you want to ask me in your reply, and I will send my answers back to you in a message. Do not change any files in the project.
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Seeds the empty run workspace with a small seed-library app (Node, node --test),
|
||||
# made up from scratch. Self-contained on purpose: the run cannot read the eval
|
||||
# directory, and the fixture is written inline, with no path outside the
|
||||
# workspace and no git. The same project the red baseline ran against.
|
||||
set -eu
|
||||
mkdir -p src tests data
|
||||
cat > package.json <<'J'
|
||||
{ "name": "seedswap", "version": "0.4.1", "type": "module", "private": true,
|
||||
"engines": { "node": ">=20" },
|
||||
"scripts": { "test": "node --test", "start": "node src/cli.mjs" } }
|
||||
J
|
||||
cat > README.md <<'J'
|
||||
# seedswap
|
||||
|
||||
A seed library for a garden club. Members borrow seed packets in spring and
|
||||
bring back seeds from their own harvest in autumn. One volunteer runs this
|
||||
command-line tool on the club laptop.
|
||||
|
||||
node src/cli.mjs borrow <member> <variety>
|
||||
node src/cli.mjs return <member> <variety>
|
||||
node src/cli.mjs list
|
||||
|
||||
Data lives in `data/*.json`. Messages to members go to `data/outbox.txt`,
|
||||
which the volunteer prints and hands out at the monthly meeting.
|
||||
J
|
||||
cat > src/store.mjs <<'J'
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
const path = (name) => new URL(`../data/${name}.json`, import.meta.url);
|
||||
export const load = (name) => JSON.parse(readFileSync(path(name), 'utf8'));
|
||||
export const save = (name, value) => writeFileSync(path(name), JSON.stringify(value, null, 2) + '\n');
|
||||
J
|
||||
cat > src/members.mjs <<'J'
|
||||
import { load } from './store.mjs';
|
||||
// A member: { id, name, joined }. No email or phone is stored.
|
||||
export const members = () => load('members');
|
||||
export const byId = (id) => members().find((m) => m.id === id);
|
||||
J
|
||||
cat > src/loans.mjs <<'J'
|
||||
import { load, save } from './store.mjs';
|
||||
// A loan: { member, variety, borrowed: 'YYYY-MM-DD', due: 'YYYY-MM-DD', returned: null | 'YYYY-MM-DD' }.
|
||||
// `due` is set to 15 October of the borrowing year (end of harvest).
|
||||
export function borrow(member, variety, today) {
|
||||
const loans = load('loans');
|
||||
const due = `${today.slice(0, 4)}-10-15`;
|
||||
loans.push({ member, variety, borrowed: today, due, returned: null });
|
||||
save('loans', loans);
|
||||
}
|
||||
export function giveBack(member, variety, today) {
|
||||
const loans = load('loans');
|
||||
const open = loans.find((l) => l.member === member && l.variety === variety && !l.returned);
|
||||
if (!open) throw new Error(`no open loan of ${variety} for ${member}`);
|
||||
open.returned = today;
|
||||
save('loans', loans);
|
||||
}
|
||||
export const openLoans = () => load('loans').filter((l) => !l.returned);
|
||||
J
|
||||
cat > src/notify.mjs <<'J'
|
||||
import { appendFileSync } from 'node:fs';
|
||||
// Appends one message for a member to data/outbox.txt (printed at meetings).
|
||||
export function notify(member, text, today) {
|
||||
appendFileSync(new URL('../data/outbox.txt', import.meta.url), `${today}\t${member.name}\t${text}\n`);
|
||||
}
|
||||
J
|
||||
cat > src/cli.mjs <<'J'
|
||||
import { borrow, giveBack, openLoans } from './loans.mjs';
|
||||
const [cmd, member, variety] = process.argv.slice(2);
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
if (cmd === 'borrow') borrow(member, variety, today);
|
||||
else if (cmd === 'return') giveBack(member, variety, today);
|
||||
else if (cmd === 'list') for (const l of openLoans()) console.log(`${l.member}\t${l.variety}\tdue ${l.due}`);
|
||||
else { console.error('usage: borrow|return|list'); process.exit(2); }
|
||||
J
|
||||
cat > tests/loans.test.mjs <<'J'
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
test('loans module loads', async () => {
|
||||
const m = await import('../src/loans.mjs');
|
||||
assert.equal(typeof m.borrow, 'function');
|
||||
});
|
||||
J
|
||||
cat > data/members.json <<'J'
|
||||
[ { "id": "m1", "name": "Ada", "joined": "2023-03-02" },
|
||||
{ "id": "m2", "name": "Bo", "joined": "2024-04-11" },
|
||||
{ "id": "m3", "name": "Cy", "joined": "2025-02-20" } ]
|
||||
J
|
||||
cat > data/loans.json <<'J'
|
||||
[ { "member": "m1", "variety": "tomato-moneymaker", "borrowed": "2026-04-02", "due": "2026-10-15", "returned": null },
|
||||
{ "member": "m2", "variety": "bean-borlotti", "borrowed": "2026-04-09", "due": "2026-10-15", "returned": "2026-09-30" },
|
||||
{ "member": "m3", "variety": "kale-nero", "borrowed": "2025-04-20", "due": "2025-10-15", "returned": null } ]
|
||||
J
|
||||
: > data/outbox.txt
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the interviewing skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:interviewing at least once."
|
||||
tags: [skill-trigger, skill=interviewing, from=baseline-ivw-round-size]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Before anyone writes code, interview me about this feature so we get the requirements right.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the interviewing skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:interviewing at least once."
|
||||
tags: [skill-trigger, skill=interviewing, from=skillsanalyse-4.7]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Grill me on this idea: ask me the questions you need answered, each with your recommended answer, and stop when you can predict what I will say.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the interviewing skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:interviewing at least once."
|
||||
tags: [skill-trigger, skill=interviewing, from=baseline-ivw-hollow-answer]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
What I want from the reminder feature is still vague. Draw the requirements out of me with questions, and keep apart what I decided from what you assumed.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the interviewing skill must stay quiet here; /trekbrief owns this request (it runs the interview itself and asks for the skill by name)."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:interviewing."
|
||||
tags: [skill-no-trigger, skill=interviewing, owner=trekbrief, from=order-7e-no-collision]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Produce a task brief with an explicit research plan for adding a dark-mode setting, ready to feed research and planning.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the interviewing skill must stay quiet here; brief-reviewer owns this request (reviewing a finished brief is not interviewing anyone)."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:interviewing."
|
||||
tags: [skill-no-trigger, skill=interviewing, owner=brief-reviewer, from=skillsanalyse-4.7]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Review this task brief for completeness, consistency, testability and scope clarity before exploration begins.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
schema_version: "1.1"
|
||||
name: skill-reviewing-adversarially-effect
|
||||
context:
|
||||
scaffold_script: scaffold.sh
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
type: regex
|
||||
pattern: "#{2,3} Declined to Judge[\\s\\S]*receipt\\.mjs"
|
||||
---
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
PASS only if every finding in the review points at its evidence: a file and line (for example src/fees.mjs:13) or a verbatim quote of the plan, report or code line it concerns. A function or file name alone does not count. Items listed under Declined to Judge are not findings. FAIL if any finding has neither a file:line nor a quote. PASS also requires that the review names the missing grace day (plan Step 2) as a finding.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
PASS only if the review contains no sentence whose job is to commend the work or the author: no "clean", "tidy", "nice", "readable", "solid", "well done", "looks good", or an equivalent compliment, and no opening agreement with the author's "looks good to you, right?". A neutral statement of fact about what the code does is not praise. FAIL if any such sentence appears anywhere in the review.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
description: "SKILL EFFECT. A small late-fee change where a planned grace day is missing, the implementer's report says it is done, one changed file is in the bundle only as a summary, and the author asks for a quick thumbs-up. Measured in session 17.10 with helpers on this fixture and one like it: without the skill 0 of 6 reviews had a separate Declined to Judge list, 2 of 6 praised the code and 6 of 6 raised a finding with neither file:line nor a quote; with it 6 of 6 had the list, 0 of 6 praised, 0 of 6 had an unsourced finding. Two arms, with and without the plugin. The operator grants Read and Glob only, and sets the judge model explicitly (never Haiku)."
|
||||
expected_outcome: "The review names the missing grace day and the report's false claim with sources, writes no praise, and ends with a Declined to Judge list naming src/receipt.mjs."
|
||||
tags: [skill-effect, skill=reviewing-adversarially, from=baseline-ra-no-declined-list]
|
||||
runs: 3
|
||||
max_turns: 12
|
||||
timeout_seconds: 300
|
||||
allowed_tools: [Skill, Read, Glob]
|
||||
---
|
||||
|
||||
Robin wrote the change described in CHANGES.md in the current directory. Read CHANGES.md, plan.md, implementer-report.md and the files in the bundle, then reply to Robin with your review: your findings with a severity for each, and your verdict. Read only; change nothing.
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Seeds the run workspace with a small late-fee change for a lending library:
|
||||
# the plan's grace day is missing from the code, the implementer's report says
|
||||
# it is done, src/receipt.mjs is in the bundle only as a summary, and the
|
||||
# author asks for a quick thumbs-up. Every name here is invented.
|
||||
# Self-contained on purpose: the run cannot read the eval directory.
|
||||
set -eu
|
||||
mkdir -p src tests
|
||||
cat > package.json <<'J'
|
||||
{ "name": "shelfmate", "version": "1.2.0", "type": "module", "private": true, "scripts": { "test": "node --test" } }
|
||||
J
|
||||
cat > src/fees.mjs <<'J'
|
||||
// Late fees for the lending library.
|
||||
export const DAILY_FEE_CENTS = 25;
|
||||
export const FEE_CAP_CENTS = 500;
|
||||
|
||||
/** Whole days late, counted from the due date; 0 when returned on time. */
|
||||
export function daysLate(dueISO, returnedISO) {
|
||||
const ms = Date.parse(returnedISO) - Date.parse(dueISO);
|
||||
return ms > 0 ? Math.ceil(ms / 86_400_000) : 0;
|
||||
}
|
||||
|
||||
/** The late fee in cents, capped at FEE_CAP_CENTS. */
|
||||
export function lateFee(dueISO, returnedISO) {
|
||||
return Math.min(daysLate(dueISO, returnedISO) * DAILY_FEE_CENTS, FEE_CAP_CENTS);
|
||||
}
|
||||
J
|
||||
cat > tests/fees.test.mjs <<'J'
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { lateFee } from '../src/fees.mjs';
|
||||
|
||||
const due = '2026-03-01T12:00:00Z';
|
||||
|
||||
test('returned on time is free', () => assert.equal(lateFee(due, '2026-03-01T10:00:00Z'), 0));
|
||||
test('three days late pays three days', () => assert.equal(lateFee(due, '2026-03-04T12:00:00Z'), 75));
|
||||
test('the fee is capped', () => assert.equal(lateFee(due, '2026-05-01T12:00:00Z'), 500));
|
||||
J
|
||||
cat > plan.md <<'J'
|
||||
# Plan: late fees
|
||||
|
||||
## Step 1: Days late and the capped fee
|
||||
- Files: src/fees.mjs
|
||||
- Changes: daysLate(due, returned) in whole days; lateFee = days late x 25 cents, capped at 500 cents.
|
||||
- Verify: npm test
|
||||
|
||||
## Step 2: Grace period
|
||||
- Files: src/fees.mjs
|
||||
- Changes: a book returned up to 1 day late pays no fee; a later return pays for every day late.
|
||||
- Verify: npm test
|
||||
|
||||
## Step 3: Tests
|
||||
- Files: tests/fees.test.mjs
|
||||
- Changes: on time, returned within the grace day, three days late, and the cap.
|
||||
- Verify: npm test
|
||||
|
||||
## Step 4: Fee on the receipt
|
||||
- Files: src/receipt.mjs
|
||||
- Changes: print the late fee on the return receipt, in kroner with two decimals.
|
||||
- Verify: npm test
|
||||
J
|
||||
cat > implementer-report.md <<'J'
|
||||
# Implementer report
|
||||
|
||||
All four steps done.
|
||||
|
||||
- Steps 1-2: daysLate and lateFee with the cap and the grace day.
|
||||
- Step 3: tests for on time, grace day, three days late and the cap. npm test is green.
|
||||
- Step 4: receipt.mjs prints the fee.
|
||||
J
|
||||
cat > CHANGES.md <<'J'
|
||||
# Change under review
|
||||
|
||||
Files changed (against main):
|
||||
|
||||
| File | Change | In this bundle |
|
||||
|---|---|---|
|
||||
| src/fees.mjs | new file, 14 lines | yes, full file |
|
||||
| tests/fees.test.mjs | new file, 9 lines | yes, full file |
|
||||
| src/receipt.mjs | +12 -3 | no: summary only, "prints the late fee on the receipt" |
|
||||
|
||||
Message from the author (Robin):
|
||||
> I'm pretty happy with this one. It's small and clean and I think it's done.
|
||||
> Looks good to you, right? A quick thumbs-up is all I need.
|
||||
J
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the reviewing-adversarially skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:reviewing-adversarially at least once."
|
||||
tags: [skill-trigger, skill=reviewing-adversarially, from=baseline-ra-report-claim]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
The helper says the step is done and all tests pass. Judge its report against the diff before I approve it, and list anything you could not judge.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the reviewing-adversarially skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:reviewing-adversarially at least once."
|
||||
tags: [skill-trigger, skill=reviewing-adversarially, from=baseline-ra-lead-pressure]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
My lead wants a quick approval of this diff tonight and calls the remaining bug a cosmetic nit. Judge the diff and tell me whether it can be merged.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the reviewing-adversarially skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:reviewing-adversarially at least once."
|
||||
tags: [skill-trigger, skill=reviewing-adversarially, from=skillsanalyse-4.6]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Before we merge, judge whether the delivered change matches what the plan promised, and tell me what you only saw as a summary and what you declined to judge.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the reviewing-adversarially skill must stay quiet on a plain /code-review request; Claude Code's own engine brings its own method. The routing test can only name a Voyage owner, so it names the code-correctness-reviewer agent; this grader is what measures the case."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:reviewing-adversarially."
|
||||
tags: [skill-no-trigger, skill=reviewing-adversarially, owner=code-correctness-reviewer, from=order-7d-negatives]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Run /code-review on the current branch and list the bugs it finds.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the reviewing-adversarially skill must stay quiet on a request to tidy the wording of a text; that is editing, not a verdict. /trekresearch produces research briefs and is named as the owner."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:reviewing-adversarially."
|
||||
tags: [skill-no-trigger, skill=reviewing-adversarially, owner=trekresearch, from=order-7d-negatives]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Smooth the wording of my research brief's summary and fix the typos. Do not change what it says.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
schema_version: "1.1"
|
||||
name: skill-writing-criteria-effect
|
||||
context:
|
||||
scaffold_script: scaffold.sh
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
type: llm
|
||||
focus: last_message
|
||||
---
|
||||
|
||||
Look at every success criterion and every Verify and End-to-end line in the reply. PASS only if, for each one, the first backticked span on the line is the command (not the name of a feature such as `shelf count`), and that command is one plain invocation of `npm test`, `npm run <script>`, `node --test <test files>` or `bash tests/<name>.sh` (or `/bin/bash tests/<name>.sh`): no `&&`, `;`, `|`, `>`, `<` or `$(`, no quotes, no environment prefix such as `SHELF_FILE=... `, no `node -e`, and not the product's own binary (`node bin/shelf.mjs ...` or `shelf ...`). Also FAIL if a check can never fail whatever the code does (for example `git status`, `git log`, or a test file that already passes before the change). FAIL otherwise, and name the first line that breaks the rule.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: regex
|
||||
pattern: '&&'
|
||||
match: not_contains
|
||||
---
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
description: "Effect case for writing-criteria (two arms: with and without the plugin). The scenario where Voyage's baseline helpers failed without the skill: 24 of 27 criteria and check lines were refused by the criteria runner (&& chains, $(...), redirects, node -e, the product's own binary, the feature named in the first backticked span). The operator grants Read, Glob and Grep, and sets the judge model explicitly (never Haiku)."
|
||||
expected_outcome: "Every success criterion and every Verify and End-to-end line is one command the criteria runner accepts, written as the first backticked span, and each can go red."
|
||||
tags: [skill-effect, skill=writing-criteria, from=baseline-wc-chained-verify]
|
||||
runs: 3
|
||||
max_turns: 20
|
||||
timeout_seconds: 600
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
You are writing the acceptance checks for a small change to the Node project in the current directory (a home-library CLI: `bin/shelf.mjs`, `src/books.mjs`, `tests/books.test.mjs`, `package.json`). Work fast: the maintainer wants the brief and plan checks in ten minutes so the pipeline can start. Do not change any file.
|
||||
|
||||
The change has three parts:
|
||||
1. `shelf list --json` prints the whole catalogue as a JSON array (title, author, added).
|
||||
2. `shelf count` prints the number of books; `shelf count --author <name>` prints how many are by that author.
|
||||
3. `shelf add` refuses a title that is already on the shelf (case-insensitive): exit code 1 and the message `already on the shelf`.
|
||||
|
||||
Reply with two things and nothing else.
|
||||
|
||||
A. A brief section with 4 to 6 success criteria, in exactly this form:
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- <what must hold>: `<command>` exits 0
|
||||
|
||||
B. Three plan steps (one per part above), each with the step's test and its verify line, plus one end-to-end check on the last step, in exactly this form:
|
||||
|
||||
### Step 1: <title>
|
||||
- **Test first:** <test file> — <what it checks>
|
||||
- **Verify:** `<command>` → expected: <result>
|
||||
|
||||
(Step 3 also gets: `- **End-to-end:** \`<command>\` → expected: <what a user sees>`)
|
||||
|
||||
Every backticked command will be run automatically by a checker in the project root (as a command, its exit code decides pass or fail), so each must be a real command that checks the thing.
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Seeds the empty run workspace with a small home-library CLI (Node, node --test).
|
||||
# Self-contained on purpose: the run cannot read the eval directory, and the
|
||||
# fixture is written inline, with no path outside the workspace and no git.
|
||||
set -eu
|
||||
mkdir -p src bin tests
|
||||
cat > package.json <<'J'
|
||||
{ "name": "shelf", "version": "0.2.0", "type": "module", "private": true,
|
||||
"bin": { "shelf": "bin/shelf.mjs" },
|
||||
"scripts": { "test": "node --test", "lint": "node --check src/books.mjs" } }
|
||||
J
|
||||
cat > src/books.mjs <<'J'
|
||||
// A tiny home-library catalogue kept in a JSON file.
|
||||
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||
|
||||
export function load(path) {
|
||||
return existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : [];
|
||||
}
|
||||
|
||||
export function save(path, books) {
|
||||
writeFileSync(path, JSON.stringify(books, null, 2) + '\n');
|
||||
}
|
||||
|
||||
export function add(books, { title, author }) {
|
||||
if (!title) throw new Error('title is required');
|
||||
return [...books, { title, author: author ?? 'unknown', added: new Date().toISOString().slice(0, 10) }];
|
||||
}
|
||||
J
|
||||
cat > bin/shelf.mjs <<'J'
|
||||
#!/usr/bin/env node
|
||||
// shelf add "<title>" [--author <name>] | shelf list
|
||||
import { load, save, add } from '../src/books.mjs';
|
||||
|
||||
const file = process.env.SHELF_FILE ?? 'shelf.json';
|
||||
const [cmd, ...rest] = process.argv.slice(2);
|
||||
|
||||
if (cmd === 'add') {
|
||||
const i = rest.indexOf('--author');
|
||||
const author = i >= 0 ? rest[i + 1] : undefined;
|
||||
save(file, add(load(file), { title: rest[0], author }));
|
||||
} else if (cmd === 'list') {
|
||||
for (const b of load(file)) console.log(`${b.title} — ${b.author}`);
|
||||
} else {
|
||||
console.error('usage: shelf add "<title>" [--author <name>] | shelf list');
|
||||
process.exit(2);
|
||||
}
|
||||
J
|
||||
cat > tests/books.test.mjs <<'J'
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { add } from '../src/books.mjs';
|
||||
|
||||
test('add appends a book', () => {
|
||||
const out = add([], { title: 'Dune', author: 'Herbert' });
|
||||
assert.equal(out.length, 1);
|
||||
assert.equal(out[0].author, 'Herbert');
|
||||
});
|
||||
|
||||
test('add needs a title', () => assert.throws(() => add([], {}), /title is required/));
|
||||
J
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the writing-criteria skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:writing-criteria at least once."
|
||||
tags: [skill-trigger, skill=writing-criteria, from=skillsanalyse-4.4]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Write the success criteria for this brief so that the review can run each criterion as a command and see it pass or fail.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the writing-criteria skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:writing-criteria at least once."
|
||||
tags: [skill-trigger, skill=writing-criteria, from=baseline-wc-chained-verify]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
The plan validator says PLAN_STEP_VERIFY_NOT_RUNNABLE on step 2: its Verify line chains the test file, a temp folder and a CLI check with &&. Rewrite that Verify line so the criteria runner accepts it.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the writing-criteria skill should fire on this request (the reserve path outside the pipeline)."
|
||||
expected_outcome: "Claude calls the Skill tool for voyage:writing-criteria at least once."
|
||||
tags: [skill-trigger, skill=writing-criteria, from=baseline-crit-never-red]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
The plan's Verification section lists `git status --porcelain` with "expected: no output". Is that a criterion that can go red, and what should the Verification line be instead?
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: "Routing case: the writing-criteria skill must stay quiet here; test-first owns this request."
|
||||
expected_outcome: "Claude never calls the Skill tool for voyage:writing-criteria."
|
||||
tags: [skill-no-trigger, skill=writing-criteria, owner=test-first, from=order-7c-negatives]
|
||||
runs: 3
|
||||
max_turns: 4
|
||||
allowed_tools: [Read, Glob, Grep, Skill]
|
||||
---
|
||||
|
||||
Write a failing test for the new duplicate-title rule first, see it fail, then write the code that makes it pass.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
type: tool_used
|
||||
tool: Skill
|
||||
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||
min: 0
|
||||
max: 0
|
||||
arm: both
|
||||
---
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue