Compare commits
91 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
591f3c4793 |
|||
|
7cb038cce3 |
|||
|
051331a5ef |
|||
|
31af4fa774 |
|||
|
bba5cb89b3 |
|||
|
8c52c3c32e |
|||
|
ce98f62e82 |
|||
|
c75ae2d3f5 |
|||
|
712a51591d |
|||
|
f9cd08076e |
|||
|
1b9d5fd459 |
|||
|
eca974aaa6 |
|||
|
8be0c05221 |
|||
|
52c382c198 |
|||
|
76f74793e9 |
|||
|
ad053e0e0e |
|||
|
b9d173a7fd |
|||
|
c7fdbf0d8b |
|||
|
33ef2c1b3a |
|||
|
27280ca8cb |
|||
|
4b59ec7f16 |
|||
|
b99081f215 |
|||
|
89975a1fd6 |
|||
|
2c0a98c1ba |
|||
|
f1704f0800 |
|||
|
738efa3e24 |
|||
|
878871a6ad |
|||
|
9145d2bbf5 |
|||
|
afe56899a9 |
|||
|
bf4736a254 |
|||
|
5ddbcd3de6 |
|||
|
77544841d7 |
|||
|
703c508433 |
|||
|
e279f12131 |
|||
|
cf7af30b46 |
|||
|
7566b71674 |
|||
|
2dbfbaf8ca |
|||
|
cde4c1d3ed |
|||
|
be0b631fed |
|||
|
af90e82794 |
|||
|
f6bdc2de59 |
|||
|
8a2a989f79 |
|||
|
e351e7c29d |
|||
|
5476a36782 |
|||
|
7869c4cbae |
|||
|
773aa44dc9 |
|||
|
a5fcb5e8b4 |
|||
|
7175783ce5 |
|||
|
761f406faa |
|||
|
b16e39ccd9 |
|||
|
f32baf50ad |
|||
|
403afe606f |
|||
|
6226372eaa |
|||
|
050a77f513 |
|||
|
6c0718c8d8 |
|||
|
a9f5f6251a |
|||
|
2fe6feb74d |
|||
|
2b5d5f72bc |
|||
|
af36578f12 |
|||
|
e2fcf4060c |
|||
|
8f9b0abfad |
|||
|
95eaa8dc57 |
|||
|
074feef475 |
|||
|
eafe023c74 |
|||
|
be83e6e066 |
|||
|
4312882451 |
|||
|
ab6b32c930 |
|||
|
45eaedc6b4 |
|||
|
074b44a7e0 |
|||
|
843897ae33 |
|||
|
1989656a9c |
|||
|
cf08df9d55 |
|||
|
1b613421eb |
|||
|
849b2427c3 |
|||
|
8677836060 |
|||
|
3238327483 |
|||
|
b47cabdf30 |
|||
|
16d1bb7dd5 |
|||
|
c88c66fea1 |
|||
|
7774bb5043 |
|||
|
0db3fe4be3 |
|||
|
01ab61e451 |
|||
|
692f528a5c |
|||
|
7b092b8af1 |
|||
|
f6e18a1d09 |
|||
|
837e92545d |
|||
|
f906ec9252 |
|||
|
31c77fd8d6 |
|||
|
af5de3fcb8 |
|||
|
f4bf9a85c6 |
|||
|
4d9b44096a |
196 changed files with 14398 additions and 859 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "voyage",
|
"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 (Fiks/Endre/Spørsmål), write comment, copy structured prompt, paste back, Claude revises the .md.",
|
"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.4.0",
|
"version": "6.5.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Kjell Tore Guttormsen"
|
"name": "Kjell Tore Guttormsen"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
380
CHANGELOG.md
380
CHANGELOG.md
|
|
@ -4,6 +4,386 @@ 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/).
|
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
|
## 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
|
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 |
|
| Command | Description | Orchestrator model |
|
||||||
|---------|-------------|--------------------|
|
|---------|-------------|--------------------|
|
||||||
| `/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 |
|
| `/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 |
|
||||||
| `/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 |
|
| `/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; 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 |
|
| `/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, 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 |
|
| `/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) | 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 |
|
||||||
| `/trekcontinue` | Continue — resumes the next session of a multi-session voyage project. Reads `.session-state.local.json` (Handover 7) and immediately begins executing | 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 |
|
| `/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,9 +134,15 @@ 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: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: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: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>`); 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`.
|
> **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`.
|
||||||
|
|
||||||
## Reference docs (read on demand)
|
## 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.
|
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 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).
|
`/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).
|
||||||
|
|
||||||
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`.
|
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) |
|
| `/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` |
|
| `/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 |
|
| `/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 (Critical/High/Medium/Low/Info) 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 (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 |
|
||||||
|
|
||||||
**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.
|
**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,13 +72,7 @@ No cloud dependency. No GitHub requirement. Works on **Mac, Linux, and Windows**
|
||||||
|
|
||||||
### Autonomy mode (`--gates`, v3.4.0)
|
### Autonomy mode (`--gates`, v3.4.0)
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
| 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.
|
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.
|
||||||
|
|
||||||
|
|
@ -130,7 +124,7 @@ An optional architect step can sit between research and plan — `/trekplan` aut
|
||||||
Concrete capabilities, observable in the code — not aspirations.
|
Concrete capabilities, observable in the code — not aspirations.
|
||||||
|
|
||||||
**Across all profiles:**
|
**Across all profiles:**
|
||||||
- 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.
|
- 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.
|
||||||
- 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.
|
- 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.
|
- 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`.
|
- Audit trail by construction. Every executed step records `commit_sha`, `verify_passed`, `files_changed` in `progress.json`.
|
||||||
|
|
@ -139,7 +133,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".
|
**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".
|
||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
## Non-goals
|
## Non-goals
|
||||||
|
|
||||||
|
|
@ -160,7 +154,9 @@ 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:`.
|
**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.** 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.
|
**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`.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|
@ -168,7 +164,7 @@ Then `brief-reviewer` scores the draft on six dimensions (completeness, consiste
|
||||||
|
|
||||||
Output: `.claude/projects/{YYYY-MM-DD}-{slug}/brief.md`
|
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 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 (the classes), `skills/interviewing/SKILL.md` (the round) and `lib/util/approval-log.mjs`.
|
||||||
|
|
||||||
### Modes
|
### Modes
|
||||||
|
|
||||||
|
|
@ -189,6 +185,7 @@ If you say "stop" or "enough" during Phase 4, the current review findings are su
|
||||||
|
|
||||||
### What the brief contains
|
### 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)
|
- **Intent** — why this matters, motivation, user need (load-bearing)
|
||||||
- **Goal** — concrete end state in 1-3 sentences
|
- **Goal** — concrete end state in 1-3 sentences
|
||||||
- **Non-Goals** — explicitly out of scope
|
- **Non-Goals** — explicitly out of scope
|
||||||
|
|
@ -325,7 +322,9 @@ Every implementation step includes:
|
||||||
- **Checkpoint:** — git commit after success
|
- **Checkpoint:** — git commit after success
|
||||||
- **Manifest:** — the objective completion predicate (Hard Rule 17)
|
- **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.
|
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).
|
||||||
|
|
||||||
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/).
|
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/).
|
||||||
|
|
||||||
|
|
@ -341,7 +340,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.
|
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.
|
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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|
@ -391,7 +390,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 |
|
| **Single step** | `/trekexecute --project <dir> --step 3` | Execute only step 3 |
|
||||||
| **Foreground** | `/trekexecute --project <dir> --fg` | Force sequential, ignore Execution Strategy |
|
| **Foreground** | `/trekexecute --project <dir> --fg` | Force sequential, ignore Execution Strategy |
|
||||||
| **Single session** | `/trekexecute --project <dir> --session 2` | Execute only session 2 from 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) Pin model profile for execution. 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) 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). |
|
||||||
|
|
||||||
### Multi-session execution through session orders (worktree-isolated)
|
### Multi-session execution through session orders (worktree-isolated)
|
||||||
|
|
||||||
|
|
@ -472,7 +471,7 @@ prompt-injection vector that the plugin's own hooks cannot fully mitigate
|
||||||
|
|
||||||
A `UserPromptSubmit` hook (`hooks/scripts/session-title.mjs`) sets the
|
A `UserPromptSubmit` hook (`hooks/scripts/session-title.mjs`) sets the
|
||||||
session title to `voyage:<command>:<slug>` whenever you invoke one of
|
session title to `voyage:<command>:<slug>` whenever you invoke one of
|
||||||
the four voyage commands. This makes the sessions of a multi-session run and
|
the six pipeline commands. This makes the sessions of a multi-session run and
|
||||||
session-picker output trivially identifiable. Slug derivation:
|
session-picker output trivially identifiable. Slug derivation:
|
||||||
|
|
||||||
| Invocation | Session title |
|
| Invocation | Session title |
|
||||||
|
|
@ -522,13 +521,22 @@ 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
|
keeps the review from coming back `ALLOW` — and from passing the gate — and
|
||||||
the summary says why.
|
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
|
### Modes
|
||||||
|
|
||||||
| Mode | Command | Description |
|
| 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 |
|
| **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` |
|
| **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 — 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 except the brief-conflict rule — fast correctness-only pass |
|
||||||
| **Validate** | `/trekreview --project <dir> --validate` | Schema-only check on existing `review.md`. No LLM calls |
|
| **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 |
|
| **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). |
|
| **Profile** | `/trekreview --profile <name> --project <dir>` | (v4.1.0) Pin model profile for the review phase. See [Profile system](#profile-system-v410). |
|
||||||
|
|
@ -557,7 +565,7 @@ The history is the `review.md` files your repo already has; no new store.
|
||||||
|
|
||||||
### Triage gate (deterministic)
|
### 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 patterns: `auth/**`, `crypto/**`, `**/security/**`. 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`: 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.
|
||||||
|
|
||||||
### Feedback loop (Handover 6)
|
### Feedback loop (Handover 6)
|
||||||
|
|
||||||
|
|
@ -650,13 +658,19 @@ 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: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: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: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,
|
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)
|
"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,
|
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
|
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. How to write one, starting with a baseline the
|
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
|
||||||
helper fails without the skill: [docs/skills-authoring.md](docs/skills-authoring.md).
|
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
|
Borrowed, with credit: the form check and routing test from addyosmani/agent-skills (MIT); the red
|
||||||
|
|
@ -664,7 +678,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
|
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`.
|
(Apache-2.0). Only ideas are borrowed, no code; pinned commits in each `SKILL.md`.
|
||||||
|
|
||||||
## Reviewing and annotating artifacts (v5.0.3)
|
## Reviewing and annotating artifacts
|
||||||
|
|
||||||
`/trekbrief`, `/trekplan`, and `/trekreview` each end by running
|
`/trekbrief`, `/trekplan`, and `/trekreview` each end by running
|
||||||
`scripts/annotate.mjs` against the just-written `.md` and printing the
|
`scripts/annotate.mjs` against the just-written `.md` and printing the
|
||||||
|
|
@ -704,8 +718,8 @@ annotation surface the operator pointed at:
|
||||||
- **Section** (auto-detected from the nearest h1/h2 above).
|
- **Section** (auto-detected from the nearest h1/h2 above).
|
||||||
- **Anchored to** — the exact text you selected, or the element's
|
- **Anchored to** — the exact text you selected, or the element's
|
||||||
first ~200 chars if you didn't select.
|
first ~200 chars if you didn't select.
|
||||||
- **Three intent buttons:** **Fiks** (something is wrong — fix it),
|
- **Three intent buttons:** **Fix** (something is wrong — fix it),
|
||||||
**Endre** (change the wording / content), **Spørsmål** (an open
|
**Change** (the wording / content), **Question** (an open
|
||||||
question — clarify or answer). Colored: red / orange / blue.
|
question — clarify or answer). Colored: red / orange / blue.
|
||||||
- **Comment** textarea (optional but helpful).
|
- **Comment** textarea (optional but helpful).
|
||||||
- **Cancel** / **Save**. Save stays disabled until you pick an intent.
|
- **Cancel** / **Save**. Save stays disabled until you pick an intent.
|
||||||
|
|
@ -725,20 +739,30 @@ annotation surface the operator pointed at:
|
||||||
Refresh the tab or close the browser and re-open — your work is there.
|
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
|
You select / click, pick intent, write comment, repeat. When you're
|
||||||
done, Copy Prompt, paste back into this chat. Claude revises the `.md`
|
done, Copy Prompt, paste back into this chat. **The operator drives every
|
||||||
freehand from your notes. **The operator drives every annotation.**
|
annotation.** Claude never pre-generates suggestions in this flow. The surface
|
||||||
Claude never pre-generates suggestions in this flow.
|
has worked this way since v5.0.3; how it got here is in
|
||||||
|
[CHANGELOG.md](CHANGELOG.md) § v5.0.0 → § v5.0.3.
|
||||||
|
|
||||||
> **What v5.0.3 changed from v5.0.2.** v5.0.2 was operator-led but the UX
|
What Claude does with the pasted notes is the skill `voyage:annotating`
|
||||||
> was too thin — click a line, type a freeform note, save. The reference
|
([skills/annotating/](skills/annotating/SKILL.md)), which the three commands
|
||||||
> the operator pointed at (an existing annotation surface in another project)
|
ask for by name:
|
||||||
> already had the right pattern: pencil-toggle, selection capture, three
|
|
||||||
> intent categories, popover form, structured markdown export. v5.0.3
|
- **Fix** and **Change** edit the text the note points at, and nothing else.
|
||||||
> rebuilds `scripts/annotate.mjs` against that reference. v5.0.0 / v5.0.1
|
Anything the notes did not ask for (a summary that now disagrees, the same gap
|
||||||
> / v5.0.2 are all superseded; only the v5.0.0 removals (bespoke
|
in another step) comes back as a question, not as an edit.
|
||||||
> playground SPA, `/trekrevise`, Handover 8, supporting `lib/` modules,
|
- A **Question** is answered in the chat; the text stays as it was unless you
|
||||||
> Playwright e2e + devDeps) stay. See [CHANGELOG.md](CHANGELOG.md)
|
say to write the answer in.
|
||||||
> § v5.0.0 → § v5.0.3.
|
- **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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -780,7 +804,7 @@ flowchart TB
|
||||||
end
|
end
|
||||||
subgraph RES["/trekresearch · Phase 4 — parallel"]
|
subgraph RES["/trekresearch · Phase 4 — parallel"]
|
||||||
RL["LOCAL: architecture-mapper · dependency-tracer<br/>task-finder · git-historian · convention-scanner*"]
|
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
|
end
|
||||||
subgraph PL["/trekplan"]
|
subgraph PL["/trekplan"]
|
||||||
PLG["Phase 4b · brief-reviewer (gate)"]
|
PLG["Phase 4b · brief-reviewer (gate)"]
|
||||||
|
|
@ -799,7 +823,7 @@ flowchart TB
|
||||||
BR --> RES --> PL --> EX --> RV
|
BR --> RES --> PL --> EX --> RV
|
||||||
```
|
```
|
||||||
|
|
||||||
`* = 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`.
|
`* = 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`.
|
||||||
|
|
||||||
> **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).
|
> **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).
|
||||||
|
|
||||||
|
|
@ -874,7 +898,7 @@ An opt-in upstream architect plugin (not bundled) can insert a Claude-Code-speci
|
||||||
|
|
||||||
## Upgrading
|
## Upgrading
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## Releasing and rolling back
|
## Releasing and rolling back
|
||||||
|
|
||||||
|
|
@ -885,8 +909,7 @@ 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:
|
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
|
```bash
|
||||||
cd plugins/trekplan
|
npm test # from the repo root; runs all tests under tests/**/*.test.mjs
|
||||||
npm test # runs all tests under tests/**/*.test.mjs
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Validators (zero npm deps, hand-rolled YAML subset):
|
Validators (zero npm deps, hand-rolled YAML subset):
|
||||||
|
|
@ -921,7 +944,7 @@ The `pre-compact-flush.mjs` hook directly fixes the documented P0 in `docs/treke
|
||||||
|
|
||||||
## Profile system (v4.1.0)
|
## Profile system (v4.1.0)
|
||||||
|
|
||||||
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.
|
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>`.
|
||||||
|
|
||||||
| Profile | Brief | Research | Plan | Execute | Review | Continue | Use case |
|
| Profile | Brief | Research | Plan | Execute | Review | Continue | Use case |
|
||||||
|---------|-------|----------|------|---------|--------|----------|----------|
|
|---------|-------|----------|------|---------|--------|----------|----------|
|
||||||
|
|
@ -934,10 +957,12 @@ Lookup order:
|
||||||
|
|
||||||
1. Explicit `--profile <name>` flag passed to the command
|
1. Explicit `--profile <name>` flag passed to the command
|
||||||
2. Plan-file frontmatter `profile:` (when resuming via `/trekexecute --resume` or `/trekcontinue`)
|
2. Plan-file frontmatter `profile:` (when resuming via `/trekexecute --resume` or `/trekcontinue`)
|
||||||
3. `VOYAGE_PROFILE` environment variable
|
3. `VOYAGE_PROFILE` environment variable (not read on a resume)
|
||||||
4. Default `premium`
|
4. Default `premium`
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
## Observability (v4.1.0)
|
## Observability (v4.1.0)
|
||||||
|
|
||||||
|
|
@ -970,16 +995,18 @@ For per-profile cost estimates, see [`docs/profiles.md`](docs/profiles.md).
|
||||||
Top-level layout:
|
Top-level layout:
|
||||||
|
|
||||||
```
|
```
|
||||||
trekplan/
|
voyage/
|
||||||
├── agents/ 24 specialized agents (all `model: opus`-pinned; per-phase model set by `--profile`)
|
├── 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)
|
│ └ 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
|
├── commands/ 6 slash commands (trekbrief, trekresearch, trekplan, trekexecute, trekreview, trekcontinue) + trekendsession helper
|
||||||
├── skills/ 3 skills (test-first, debugging: preloaded into the step helper; researching-sources: preloaded into the five web-search agents)
|
├── 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)
|
||||||
├── templates/ Frontmatter templates for brief, research, plan, session
|
├── 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)
|
├── 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/)
|
├── lib/ Zero-dep parsers and validators (CLI shims under lib/validators/)
|
||||||
├── tests/ comprehensive node:test suite — `npm test` is the fork-readiness gate
|
├── tests/ comprehensive node:test suite — `npm test` is the fork-readiness gate
|
||||||
├── docs/ HANDOVER-CONTRACTS.md + architect-bridge-test.md
|
├── docs/ HANDOVER-CONTRACTS.md, architecture.md, operations.md, profiles.md, command-modes.md, release-runbook.md
|
||||||
└── examples/ 01-add-verbose-flag/ — calibrated end-to-end pipeline demo
|
└── examples/ 01-add-verbose-flag/ — calibrated end-to-end pipeline demo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -1001,12 +1028,14 @@ synthesis.
|
||||||
cp agents/architecture-mapper.md agents/my-new-agent.md
|
cp agents/architecture-mapper.md agents/my-new-agent.md
|
||||||
```
|
```
|
||||||
2. Update the frontmatter `name`, `description`, `tools`, and `model`.
|
2. Update the frontmatter `name`, `description`, `tools`, and `model`.
|
||||||
Use `sonnet` unless the agent needs deep reasoning (most don't).
|
Every shipped agent is `model: opus`; the profile picks the model at
|
||||||
3. Add the agent to the swarm in `agents/planning-orchestrator.md`
|
the spawn site, so the pin is only the fallback.
|
||||||
Phase 5 — register it under the codebase-size bucket where it
|
3. Add the agent to the swarm in `commands/trekplan.md` Phase 5
|
||||||
should fire (always / medium+ / large only).
|
(the command runs the swarm inline; `agents/planning-orchestrator.md`
|
||||||
4. Update the agent table in `CLAUDE.md` and `README.md` to keep the
|
is a reference copy of that workflow) — register it under the
|
||||||
doc-consistency test green:
|
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:
|
||||||
```bash
|
```bash
|
||||||
npm test -- tests/lib/doc-consistency.test.mjs
|
npm test -- tests/lib/doc-consistency.test.mjs
|
||||||
```
|
```
|
||||||
|
|
@ -1033,7 +1062,7 @@ document it in your team's CLAUDE.md.
|
||||||
|
|
||||||
### Plugin data contract
|
### Plugin data contract
|
||||||
|
|
||||||
The four commands write to a single project directory (`.claude/projects/{date}-{slug}/`).
|
The pipeline 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).
|
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:
|
That document is the single source of truth for:
|
||||||
|
|
||||||
|
|
@ -1048,13 +1077,16 @@ that doc *and* the corresponding `lib/validators/*.mjs` *and* run
|
||||||
`npm test` — the validators and doc-consistency tests will catch
|
`npm test` — the validators and doc-consistency tests will catch
|
||||||
schema drift.
|
schema drift.
|
||||||
|
|
||||||
### Disable the architect bridge
|
### Use or skip the architecture slot
|
||||||
|
|
||||||
`/trekplan` auto-discovers `architecture/overview.md` if an
|
`/trekplan` reads `architecture/overview.md` in the project directory
|
||||||
opt-in upstream architect plugin (not bundled) produced one. To
|
as priors when the file is there. The architect plugin that once wrote
|
||||||
suppress this, leave the `architecture/` directory absent from your
|
it is no longer publicly distributed; any producer that writes the
|
||||||
project directory. Discovery is additive — missing file is fine, no
|
format in [docs/HANDOVER-CONTRACTS.md](docs/HANDOVER-CONTRACTS.md)
|
||||||
error.
|
§ 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.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
|
@ -1062,11 +1094,11 @@ Full version history → [CHANGELOG.md](CHANGELOG.md).
|
||||||
|
|
||||||
Recent, in one line each:
|
Recent, in one line each:
|
||||||
|
|
||||||
- **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.
|
- **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.
|
||||||
- **v5.7.1** — leaner always-loaded agent listing (`<example>` blocks moved into agent bodies, ~3,180 tok/turn, no behavior change).
|
- **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.
|
||||||
- **v5.7.0** — opt-in per-session token/cost metering (SKAL-2) + eval foundation (SKAL-1·4a).
|
- **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.
|
||||||
- **v5.6.1** — one-line `description:` for the four reference/dormant agents (~700 tok).
|
- **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).
|
||||||
- **v5.5.0** — brief **framing** enforcement (`brief_version 2.2`) + a `/trekreview` reviewer-schema contract. Additive, no breaking changes.
|
- **v6.0.0** — breaking: Voyage never starts Claude Code; multi-session work becomes session orders you start yourself.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,27 +8,7 @@ description: |
|
||||||
model: opus
|
model: opus
|
||||||
color: magenta
|
color: magenta
|
||||||
tools: ["Read", "Glob", "Grep"]
|
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
|
You are a brief conformance reviewer. You find what was promised in the
|
||||||
|
|
@ -36,6 +16,12 @@ 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
|
trace every Success Criterion and every Non-Goal to delivered code and
|
||||||
report mismatches.
|
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
|
## Input
|
||||||
|
|
||||||
You will receive a prompt containing:
|
You will receive a prompt containing:
|
||||||
|
|
@ -185,8 +171,9 @@ Severity is fixed by `rule_key`. Do NOT override the catalogue:
|
||||||
| `COVERAGE_SILENT_SKIP` | MAJOR |
|
| `COVERAGE_SILENT_SKIP` | MAJOR |
|
||||||
|
|
||||||
If a finding feels less severe than its catalogue tier, do NOT downgrade
|
If a finding feels less severe than its catalogue tier, do NOT downgrade
|
||||||
it. Either drop the finding (it was wrong) or emit it at the
|
it. Emit it at the catalogue's severity. Drop the finding only when you
|
||||||
catalogue's severity.
|
can say why it is wrong, and then write it as one line under
|
||||||
|
`### Declined to Judge` with that reason.
|
||||||
|
|
||||||
## Output format
|
## Output format
|
||||||
|
|
||||||
|
|
@ -221,6 +208,12 @@ parsers find it by reading the last `json` code fence.
|
||||||
|
|
||||||
(repeat per finding)
|
(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
|
### Verdict
|
||||||
|
|
||||||
- BLOCKER count: {N}
|
- BLOCKER count: {N}
|
||||||
|
|
@ -262,8 +255,9 @@ parsers find it by reading the last `json` code fence.
|
||||||
`(file, line, rule_key)` with `lib/review/fill-finding-ids.mjs`).
|
`(file, line, rule_key)` with `lib/review/fill-finding-ids.mjs`).
|
||||||
- `line` is an integer; use `0` when the finding is file-scoped without
|
- `line` is an integer; use `0` when the finding is file-scoped without
|
||||||
a specific line (e.g., MISSING_TEST for an entire file).
|
a specific line (e.g., MISSING_TEST for an entire file).
|
||||||
- `rule_key` MUST be in the catalogue. Reviewers that emit unknown rule
|
- `rule_key` MUST be in the catalogue. A finding with a rule key outside
|
||||||
keys are dropped by the coordinator's reasonableness filter.
|
it is not dropped: it is routed to `unverified` by the coordinator's
|
||||||
|
reasonableness filter (Pass 3).
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ description: |
|
||||||
model: opus
|
model: opus
|
||||||
color: magenta
|
color: magenta
|
||||||
tools: ["Read", "Glob", "Grep"]
|
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
|
You are a requirements analyst. Your sole job is to find problems in a task
|
||||||
|
|
@ -56,20 +57,14 @@ Flag as **incomplete** if:
|
||||||
- Success Criteria are not testable (e.g., "it should work well")
|
- Success Criteria are not testable (e.g., "it should work well")
|
||||||
- Scope is unbounded — no non-goals defined
|
- Scope is unbounded — no non-goals defined
|
||||||
|
|
||||||
**Runnable at review.** `/trekreview` runs a criterion's command only when it
|
**Runnable at review, and able to go red.** Judge each criterion by the
|
||||||
is one test-runner invocation with no pipe, redirect or `&&`: `npm test`,
|
preloaded `writing-criteria` skill: which commands the criteria runner
|
||||||
`npm run <script>`, `node --test <file>`, `vitest`, `jest`, `pytest`,
|
accepts, the command as the first backticked span, a script under `tests/`
|
||||||
`python -m pytest`, `uv run pytest`, `cargo test`, `go test`, `make test`,
|
for anything more, and a command that can fail. A criterion the runner
|
||||||
`bash tests/<script>.sh` (or `/bin/bash tests/<script>.sh`), or `git status|log|diff|show|ls-files`.
|
refuses is reported NOT RUN at review; the validator flags it as
|
||||||
It runs with no shell, as plain words: no quote, `$`, brace, leading `~` or
|
`BRIEF_SC_NOT_RUNNABLE`. A criterion that exits 0 whatever the code does is
|
||||||
`@` (a git revision such as `@~1` is the one exception), no glob outside
|
untestable (dimension 3). Every suggestion you make for such a criterion is
|
||||||
`node --test` (Node 21+), no `..` or absolute path, and only the runner's
|
itself one the skill accepts.
|
||||||
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
|
### 2. Consistency
|
||||||
|
|
||||||
|
|
@ -206,7 +201,7 @@ review as a quality gate and need per-dimension granularity.
|
||||||
|
|
||||||
Produce **two artifacts in this order**:
|
Produce **two artifacts in this order**:
|
||||||
|
|
||||||
1. A prose report (for humans and for `planning-orchestrator` Phase 1b).
|
1. A prose report (for humans and for /trekplan Phase 4b).
|
||||||
2. A final fenced `json` block with per-dimension numeric scores (for callers
|
2. A final fenced `json` block with per-dimension numeric scores (for callers
|
||||||
that gate on machine-readable output, such as `/trekbrief` Phase 4).
|
that gate on machine-readable output, such as `/trekbrief` Phase 4).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,33 +9,19 @@ description: |
|
||||||
model: opus
|
model: opus
|
||||||
color: red
|
color: red
|
||||||
tools: ["Read", "Glob", "Grep"]
|
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 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
|
You never praise. You cite `file:line` for every finding. You never invent
|
||||||
problems — every claim is anchored to quoted code.
|
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
|
## Input
|
||||||
|
|
||||||
You will receive a prompt containing:
|
You will receive a prompt containing:
|
||||||
|
|
@ -107,8 +93,9 @@ Cite both the changed file:line AND the regressed file:line.
|
||||||
|
|
||||||
When the brief explicitly asks for tests of a specific behavior and they
|
When the brief explicitly asks for tests of a specific behavior and they
|
||||||
are missing, escalate to `MISSING_TEST` MAJOR. When tests are
|
are missing, escalate to `MISSING_TEST` MAJOR. When tests are
|
||||||
nice-to-have, downgrade is forbidden — emit at the catalogue tier or
|
nice-to-have, downgrade is forbidden — emit at the catalogue tier. Drop
|
||||||
drop the finding.
|
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.
|
||||||
|
|
||||||
### 5. Placeholder code — `PLACEHOLDER_IN_CODE` (MAJOR)
|
### 5. Placeholder code — `PLACEHOLDER_IN_CODE` (MAJOR)
|
||||||
|
|
||||||
|
|
@ -124,9 +111,8 @@ literals or example fenced blocks):
|
||||||
- `// stub`
|
- `// stub`
|
||||||
- `throw new Error('not implemented')`
|
- `throw new Error('not implemented')`
|
||||||
|
|
||||||
Cite the exact line. The MANDATORY OVERRIDE rule above forbids saying
|
Cite the exact line. Never accept "not implemented" placeholders as fine
|
||||||
"not implemented" placeholders are fine "for now" — they are MAJOR
|
"for now" — they are MAJOR findings until removed.
|
||||||
findings until removed.
|
|
||||||
|
|
||||||
### 6. Security surface — `SECURITY_INJECTION` (BLOCKER)
|
### 6. Security surface — `SECURITY_INJECTION` (BLOCKER)
|
||||||
|
|
||||||
|
|
@ -168,8 +154,10 @@ Severity is fixed by `rule_key`. Do NOT override the catalogue:
|
||||||
| `UNDECLARED_DEPENDENCY` | MAJOR |
|
| `UNDECLARED_DEPENDENCY` | MAJOR |
|
||||||
| `COVERAGE_SILENT_SKIP` | MAJOR |
|
| `COVERAGE_SILENT_SKIP` | MAJOR |
|
||||||
|
|
||||||
If a finding feels off-tier, either drop it (it was wrong) or emit it
|
If a finding feels off-tier, emit it at the catalogue's severity. Drop
|
||||||
at the catalogue's severity. Do not invent severity overrides.
|
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.
|
||||||
|
|
||||||
## Output format
|
## Output format
|
||||||
|
|
||||||
|
|
@ -206,6 +194,12 @@ parsers find it by reading the last `json` code fence.
|
||||||
|
|
||||||
(repeat per finding)
|
(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
|
### Verdict
|
||||||
|
|
||||||
- BLOCKER count: {N}
|
- BLOCKER count: {N}
|
||||||
|
|
@ -247,8 +241,9 @@ parsers find it by reading the last `json` code fence.
|
||||||
the canonical SHA1).
|
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;
|
- `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.
|
`0` for file-scoped findings.
|
||||||
- `rule_key` MUST be in the catalogue. Reviewers that emit unknown rule
|
- `rule_key` MUST be in the catalogue. A finding with a rule key outside
|
||||||
keys are dropped by the coordinator's reasonableness filter.
|
it is not dropped: it is routed to `unverified` by the coordinator's
|
||||||
|
reasonableness filter (Pass 3).
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
|
|
@ -263,8 +258,10 @@ parsers find it by reading the last `json` code fence.
|
||||||
injection sink. Never flag a regression without naming both files.
|
injection sink. Never flag a regression without naming both files.
|
||||||
Speculative findings are dropped by the coordinator.
|
Speculative findings are dropped by the coordinator.
|
||||||
- **No silent severity downgrades.** The catalogue tier is the floor.
|
- **No silent severity downgrades.** The catalogue tier is the floor.
|
||||||
If a finding feels less serious than its catalogue severity, either
|
If a finding feels less serious than its catalogue severity, emit it
|
||||||
drop it or emit it as the catalogue says.
|
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.
|
||||||
- **Token budget honesty.** When summary-only is in effect for a file,
|
- **Token budget honesty.** When summary-only is in effect for a file,
|
||||||
state explicitly "summary-only — structural pass" so the coordinator
|
state explicitly "summary-only — structural pass" so the coordinator
|
||||||
knows the depth limit.
|
knows the depth limit.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ model: opus
|
||||||
effort: high
|
effort: high
|
||||||
color: red
|
color: red
|
||||||
tools: ["Read", "Glob", "Grep"]
|
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
|
You are a senior staff engineer whose sole job is to find problems in implementation
|
||||||
|
|
@ -150,11 +151,18 @@ questions, which defeats the purpose.
|
||||||
"not verified end to end".
|
"not verified end to end".
|
||||||
- `Verify:` is ONE command and it is the step's proof of red, so it is the
|
- `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
|
step's own new test. The suite the step must not break goes in the optional
|
||||||
`Regression:` field (K10: one backticked command the criteria runner allows,
|
`Regression:` field (K10), which the executor runs green before the
|
||||||
no pipe, no `&&`), which the executor runs green before the checkpoint. Do
|
checkpoint. Do not demand `npm test` in `Verify:` — that test is not red
|
||||||
not demand `npm test` in `Verify:` — that test is not red before the step.
|
before the step. A step that can break existing tests and has no
|
||||||
A step that can break existing tests and has no `Regression:` is a **minor**
|
`Regression:` is a **minor** finding ("add `Regression: \`npm test\``"), not
|
||||||
finding ("add `Regression: \`npm test\``"), not a major.
|
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.
|
||||||
|
|
||||||
### 9. Headless readiness
|
### 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).
|
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
|
model: opus
|
||||||
color: cyan
|
color: cyan
|
||||||
tools: ["Read", "Glob", "Grep", "Write", "Edit", "Bash"]
|
tools: ["Read", "Glob", "Grep"]
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Phase mapping: orchestrator → command
|
<!-- Phase mapping: orchestrator → command
|
||||||
|
|
@ -87,7 +87,7 @@ Classify:
|
||||||
- **Medium** (50–500 files)
|
- **Medium** (50–500 files)
|
||||||
- **Large** (> 500 files)
|
- **Large** (> 500 files)
|
||||||
|
|
||||||
Codebase size controls `maxTurns` per agent, NOT which agents run.
|
Codebase size decides only whether convention-scanner runs.
|
||||||
|
|
||||||
### Phase 1b — Brief review
|
### Phase 1b — Brief review
|
||||||
|
|
||||||
|
|
@ -120,8 +120,7 @@ scan results only.
|
||||||
**All other modes:** Launch exploration agents **in parallel** using the Agent
|
**All other modes:** Launch exploration agents **in parallel** using the Agent
|
||||||
tool. Use specialized agents from the plugin.
|
tool. Use specialized agents from the plugin.
|
||||||
|
|
||||||
**All agents run for all codebase sizes.** Scale `maxTurns` by size (small: halved,
|
**All agents run for all codebase sizes.**
|
||||||
medium: default, large: default) rather than dropping agents.
|
|
||||||
|
|
||||||
| Agent | Small | Medium | Large | Purpose |
|
| Agent | Small | Medium | Large | Purpose |
|
||||||
|-------|-------|--------|-------|---------|
|
|-------|-------|--------|-------|---------|
|
||||||
|
|
@ -134,7 +133,7 @@ medium: default, large: default) rather than dropping agents.
|
||||||
| `research-scout` | Conditional | Conditional | Conditional | External docs (only when unfamiliar tech detected AND not covered by briefs) |
|
| `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` | No | Yes | Yes | Coding conventions, naming, style, test patterns |
|
||||||
|
|
||||||
**Convention Scanner** — use the `convention-scanner` plugin agent (model: "opus")
|
**Convention Scanner** — use the `convention-scanner` plugin agent (model: phase_signal_result.model, the agent's frontmatter as the fallback)
|
||||||
for medium+ codebases only. Pass the task description as context.
|
for medium+ codebases only. Pass the task description as context.
|
||||||
|
|
||||||
**research-scout** — launch conditionally if the task involves technologies, APIs,
|
**research-scout** — launch conditionally if the task involves technologies, APIs,
|
||||||
|
|
@ -487,7 +486,7 @@ When done, your output message should contain:
|
||||||
You can:
|
You can:
|
||||||
- Review the full plan at {plan path}
|
- Review the full plan at {plan path}
|
||||||
- Ask questions or request changes
|
- Ask questions or request changes
|
||||||
- Say "execute" to implement
|
- Say "execute" for the /trekexecute line
|
||||||
- Say "save" to keep for later
|
- Say "save" to keep for later
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -512,5 +511,4 @@ You can:
|
||||||
If you don't know the exact change, mark it as `[ASSUMPTION]` and explain what
|
If you don't know the exact change, mark it as `[ASSUMPTION]` and explain what
|
||||||
information is missing.
|
information is missing.
|
||||||
- **Honesty:** If the task is trivial, say so. Don't inflate the plan.
|
- **Honesty:** If the task is trivial, say so. Don't inflate the plan.
|
||||||
- **Adaptive:** All agents run for all sizes. Scale turns down for small codebases,
|
- **Adaptive:** All agents run for all sizes.
|
||||||
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).
|
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
|
model: opus
|
||||||
color: cyan
|
color: cyan
|
||||||
tools: ["Read", "Glob", "Grep", "Write", "Edit", "Bash"]
|
tools: ["Read", "Glob", "Grep"]
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Phase mapping: orchestrator → command
|
<!-- Phase mapping: orchestrator → command
|
||||||
|
|
@ -88,12 +88,22 @@ Based on the mode, determine which agent groups to launch:
|
||||||
| `docs-researcher` | Official documentation, RFCs, vendor docs |
|
| `docs-researcher` | Official documentation, RFCs, vendor docs |
|
||||||
| `community-researcher` | Real-world experience, issues, blog posts, discussions |
|
| `community-researcher` | Real-world experience, issues, blog posts, discussions |
|
||||||
| `security-researcher` | CVEs, audit history, supply chain risks |
|
| `security-researcher` | CVEs, audit history, supply chain risks |
|
||||||
| `contrarian-researcher` | Counter-evidence, overlooked alternatives, reasons to reconsider |
|
| `contrarian-researcher` | Counter-evidence, overlooked alternatives, reasons to reconsider; runs in wave 2, against wave 1's leading answer |
|
||||||
|
|
||||||
### Phase 2 — Parallel research
|
### Phase 2 — Parallel research
|
||||||
|
|
||||||
Launch ALL selected agents **in parallel** using the Agent tool — one message,
|
Launch the selected agents in two waves.
|
||||||
multiple tool calls. This maximizes concurrency.
|
|
||||||
|
**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.
|
||||||
|
|
||||||
**Prompting local agents for research (not planning):**
|
**Prompting local agents for research (not planning):**
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ description: |
|
||||||
APIs, or libraries where official documentation and known issues should be checked.
|
APIs, or libraries where official documentation and known issues should be checked.
|
||||||
model: opus
|
model: opus
|
||||||
color: blue
|
color: blue
|
||||||
tools: ["WebSearch", "WebFetch", "Read"]
|
tools: ["WebSearch", "WebFetch", "Read", "mcp__tavily__tavily_search", "mcp__tavily__tavily_research"]
|
||||||
skills: ["voyage:researching-sources"]
|
skills: ["voyage:researching-sources"]
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,27 +10,7 @@ model: opus
|
||||||
effort: high
|
effort: high
|
||||||
color: yellow
|
color: yellow
|
||||||
tools: ["Read", "Glob", "Grep"]
|
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
|
You are a review coordinator (Judge Agent pattern). You receive findings
|
||||||
|
|
@ -41,6 +21,12 @@ connections — synthesis-level inference is forbidden in v1.0.
|
||||||
Your output is the full review.md content (frontmatter + body sections +
|
Your output is the full review.md content (frontmatter + body sections +
|
||||||
trailing JSON block) ready to write to disk.
|
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
|
## Input
|
||||||
|
|
||||||
You will receive a prompt containing:
|
You will receive a prompt containing:
|
||||||
|
|
@ -52,6 +38,9 @@ You will receive a prompt containing:
|
||||||
keys `CODE_REVIEW_DEFECT` / `CODE_REVIEW_IMPROVEMENT` (MINOR: simplification,
|
keys `CODE_REVIEW_DEFECT` / `CODE_REVIEW_IMPROVEMENT` (MINOR: simplification,
|
||||||
efficiency, reuse, style, readability) / `SECURITY_REVIEW_VULNERABILITY` (or a
|
efficiency, reuse, style, readability) / `SECURITY_REVIEW_VULNERABILITY` (or a
|
||||||
narrower key) and are treated exactly like any reviewer's findings.
|
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
|
- **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
|
each engine recorded as not run with its reason. A name that did not report
|
||||||
forbids `ALLOW` (Pass 4).
|
forbids `ALLOW` (Pass 4).
|
||||||
|
|
@ -76,7 +65,8 @@ You will receive a prompt containing:
|
||||||
(reasonableness filter) except the brief-conflict rule, which applies in every mode;
|
(reasonableness filter) except the brief-conflict rule, which applies in every mode;
|
||||||
Passes 1, 2, 4 still run.
|
Passes 1, 2, 4 still run.
|
||||||
- **Rule catalogue** — `lib/review/rule-catalogue.mjs`. Findings whose
|
- **Rule catalogue** — `lib/review/rule-catalogue.mjs`. Findings whose
|
||||||
`rule_key` is not in this set are dropped by Pass 3.
|
`rule_key` is not in this set are routed to `unverified` by Pass 3
|
||||||
|
(`unknown-rule_key`).
|
||||||
|
|
||||||
## Your 4-pass process
|
## Your 4-pass process
|
||||||
|
|
||||||
|
|
@ -87,7 +77,16 @@ re-reading, and fresh finding generation are all forbidden.
|
||||||
### Pass 1 — Dedup by `(file, line, rule_key)` triplet
|
### Pass 1 — Dedup by `(file, line, rule_key)` triplet
|
||||||
|
|
||||||
Two findings collide when their `(file, line, rule_key)` triplets are
|
Two findings collide when their `(file, line, rule_key)` triplets are
|
||||||
identical. When findings collide:
|
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:
|
||||||
- Rank the colliding findings and keep the first:
|
- Rank the colliding findings and keep the first:
|
||||||
1. the higher catalogue tier: the severity `lib/review/rule-catalogue.mjs`
|
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
|
gives the `rule_key`, or the finding's own severity when the key is
|
||||||
|
|
@ -99,7 +98,10 @@ identical. When findings collide:
|
||||||
3. among findings of one kind, the higher asserted severity;
|
3. among findings of one kind, the higher asserted severity;
|
||||||
4. among reviewer-agent findings, prefer the finding from
|
4. among reviewer-agent findings, prefer the finding from
|
||||||
`brief-conformance-reviewer` (its findings are anchored to the brief);
|
`brief-conformance-reviewer` (its findings are anchored to the brief);
|
||||||
5. then the first seen.
|
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.
|
||||||
- Write the kept finding with the highest severity any finding in its
|
- Write the kept finding with the highest severity any finding in its
|
||||||
group asserted, so dropping a duplicate never lowers the group and an
|
group asserted, so dropping a duplicate never lowers the group and an
|
||||||
engine's brief-conflict mark never lowers what a reviewer agent asserted.
|
engine's brief-conflict mark never lowers what a reviewer agent asserted.
|
||||||
|
|
@ -120,7 +122,7 @@ is load-bearing** — see *Suppression is two-valued* below:
|
||||||
| Filter | Test | Fails if | Removed as |
|
| 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. |
|
| 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` is plausible (≥ 0; ≤ file line count when known) | Path traversal escape, negative line, or impossibly large line number | **dropped** (`accuracy:refuted`) |
|
| 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`) |
|
||||||
| Actionability | `recommended_action` is non-empty AND begins with an imperative verb | Empty action, "consider …" hedges, or restating the title | `unverified` (`actionability:empty`) |
|
| 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
|
A finding that carries `engine` (`code-review` / `security-review`) came
|
||||||
|
|
@ -132,8 +134,11 @@ voyage-lekerepo trial, 2026-10-06.)
|
||||||
|
|
||||||
Succinctness and Actionability read the finding's *packaging*; neither
|
Succinctness and Actionability read the finding's *packaging*; neither
|
||||||
examines the claim, so neither can establish the finding is unreal. Accuracy
|
examines the claim, so neither can establish the finding is unreal. Accuracy
|
||||||
does: a citation that escapes the repo root refutes the finding as a claim
|
does: a citation that escapes the repo root, or a negative line, refutes the
|
||||||
about this codebase.
|
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`).
|
||||||
|
|
||||||
**No finding is struck for length** (ordre 5). Before review_version 1.1 an
|
**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
|
over-long `detail` sent a finding to `unverified`, and S118's most serious
|
||||||
|
|
@ -322,7 +327,10 @@ the parser reads; a bare `findings:` is null and fails validation.
|
||||||
withheld `ALLOW`.
|
withheld `ALLOW`.
|
||||||
9. `## Declined to Judge` — REQUIRED. One line per finding you set aside
|
9. `## Declined to Judge` — REQUIRED. One line per finding you set aside
|
||||||
without ruling on it (every `[unverified]` one, and every
|
without ruling on it (every `[unverified]` one, and every
|
||||||
out-of-scope engine finding: `file:line rule_key — reason`), then one line `Trimmed: N` (MINOR/SUGGESTION text cut, findings
|
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
|
||||||
kept). Write `None.` plus `Trimmed: 0` when empty. Borrowed: "Declined to
|
kept). Write `None.` plus `Trimmed: 0` when empty. Borrowed: "Declined to
|
||||||
judge … nothing you set aside is dropped silently" (Superpowers
|
judge … nothing you set aside is dropped silently" (Superpowers
|
||||||
`skills/requesting-code-review/code-reviewer.md:43-48`, MIT).
|
`skills/requesting-code-review/code-reviewer.md:43-48`, MIT).
|
||||||
|
|
@ -428,8 +436,9 @@ for the ID list.
|
||||||
where n is its 1-based position in the JSON block's `findings` array.
|
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
|
`/trekreview` Phase 7 runs `lib/review/fill-finding-ids.mjs`, which
|
||||||
replaces each placeholder with the id computed over `(file, line,
|
replaces each placeholder with the id computed over `(file, line,
|
||||||
rule_key)` (`lib/parsers/finding-id.mjs`) and refuses a placeholder with
|
rule_key)` (`lib/parsers/finding-id.mjs`; the k-th row on one triplet
|
||||||
no finding behind it.
|
gets it over `rule_key#k`) and refuses a placeholder with no finding
|
||||||
|
behind it.
|
||||||
- **Suppressed findings are accountable.** When you remove a finding via
|
- **Suppressed findings are accountable.** When you remove a finding via
|
||||||
Pass 2 or Pass 3, log it in `## Suppressed Findings` with the reason and
|
Pass 2 or Pass 3, log it in `## Suppressed Findings` with the reason and
|
||||||
its fate (`[dropped]` / `[unverified]`), and list every `[unverified]` one
|
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).
|
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
|
model: opus
|
||||||
color: red
|
color: red
|
||||||
tools: ["Read", "Glob", "Grep", "Write", "Edit", "Bash"]
|
tools: ["Read", "Glob", "Grep"]
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Phase mapping: orchestrator → command
|
<!-- Phase mapping: orchestrator → command
|
||||||
|
|
@ -54,8 +54,8 @@ You will receive a prompt containing:
|
||||||
contract that bounds review scope.
|
contract that bounds review scope.
|
||||||
- **Mode** — `default`, `quick`, `validate`, or `dry-run`.
|
- **Mode** — `default`, `quick`, `validate`, or `dry-run`.
|
||||||
- `default` — run the full pipeline.
|
- `default` — run the full pipeline.
|
||||||
- `quick` — skip the coordinator's reasonableness filter; use single
|
- `quick` — skip the coordinator's reasonableness filter except the
|
||||||
reviewer (code-correctness only) for faster turnaround.
|
brief-conflict rule; use single reviewer (code-correctness only) for faster turnaround.
|
||||||
- `validate` — schema-only check on existing review.md, no LLM calls.
|
- `validate` — schema-only check on existing review.md, no LLM calls.
|
||||||
- `dry-run` — print the discovered scope and triage map; skip writes.
|
- `dry-run` — print the discovered scope and triage map; skip writes.
|
||||||
- **Since-ref** (optional) — explicit `--since <ref>` override for the SHA
|
- **Since-ref** (optional) — explicit `--since <ref>` override for the SHA
|
||||||
|
|
@ -72,9 +72,12 @@ Execute these phases in order. Do not skip phases.
|
||||||
|
|
||||||
### Phase 1 — Parse mode and validate input
|
### Phase 1 — Parse mode and validate input
|
||||||
|
|
||||||
Run the arg-parser via Bash:
|
Run the arg-parser via Bash, with the arguments as the one line inside the
|
||||||
|
quoted heredoc (on stdin, never as shell words):
|
||||||
```
|
```
|
||||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview "$@"
|
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview --stdin <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||||
|
$ARGUMENTS
|
||||||
|
VOYAGE_ARGS_EOF_7F3C9E
|
||||||
```
|
```
|
||||||
|
|
||||||
Pull the structured flags from its JSON output. Reject unknown flags. If
|
Pull the structured flags from its JSON output. Reject unknown flags. If
|
||||||
|
|
@ -123,8 +126,8 @@ produces a treatment map:
|
||||||
| Treatment | When |
|
| Treatment | When |
|
||||||
|-----------|------|
|
|-----------|------|
|
||||||
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated-file marker present in first 3 lines |
|
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated-file marker present in first 3 lines |
|
||||||
| `deep-review` | Matches `auth/**`, `crypto/**`, `**/security/**`, `hooks/**` |
|
| `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` | Default treatment for everything else |
|
| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**` |
|
||||||
|
|
||||||
Hard refuse-with-suggestion gates (use AskUserQuestion):
|
Hard refuse-with-suggestion gates (use AskUserQuestion):
|
||||||
- > 100 files in the diff
|
- > 100 files in the diff
|
||||||
|
|
@ -185,9 +188,19 @@ The coordinator runs a 4-pass process:
|
||||||
2. **HubSpot Judge filters** — Accuracy refutes; Actionability sets aside
|
2. **HubSpot Judge filters** — Accuracy refutes; Actionability sets aside
|
||||||
as unverified; Succinctness never removes a finding (only MINOR/SUGGESTION
|
as unverified; Succinctness never removes a finding (only MINOR/SUGGESTION
|
||||||
text is trimmed, and counted).
|
text is trimmed, and counted).
|
||||||
3. **Cloudflare reasonableness** — drop speculative findings without a
|
3. **Cloudflare reasonableness** — drop a finding with no `file:line`
|
||||||
`file:line` citation; drop findings whose `rule_key` is not in
|
citation (`no-citation`) or whose file is in neither the working tree nor
|
||||||
`RULE_CATALOGUE`.
|
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.
|
||||||
4. **Compute verdict** — `BLOCK` if `BLOCKER ≥ 1`, `WARN` if `MAJOR ≥ 1`,
|
4. **Compute verdict** — `BLOCK` if `BLOCKER ≥ 1`, `WARN` if `MAJOR ≥ 1`,
|
||||||
else `ALLOW`.
|
else `ALLOW`.
|
||||||
|
|
||||||
|
|
@ -196,8 +209,8 @@ The coordinator's output is the full review.md content — frontmatter
|
||||||
and `## Remediation Steps` with one numbered step per BLOCKER) + trailing
|
and `## Remediation Steps` with one numbered step per BLOCKER) + trailing
|
||||||
JSON block — ready to write.
|
JSON block — ready to write.
|
||||||
|
|
||||||
In `quick` mode, skip pass 3 (reasonableness filter). Passes 1, 2, 4
|
In `quick` mode, skip pass 3 (reasonableness filter), except the
|
||||||
still run.
|
brief-conflict rule, which applies in every mode. Passes 1, 2, 4 still run.
|
||||||
|
|
||||||
### Phase 7 — Write review.md
|
### Phase 7 — Write review.md
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,19 @@ description: |
|
||||||
model: opus
|
model: opus
|
||||||
color: magenta
|
color: magenta
|
||||||
tools: ["Read", "Glob", "Grep"]
|
tools: ["Read", "Glob", "Grep"]
|
||||||
|
skills: ["voyage:reviewing-adversarially"]
|
||||||
---
|
---
|
||||||
|
|
||||||
You are a scope alignment specialist. Your job is to ensure that an implementation
|
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
|
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 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
|
## Your analysis process
|
||||||
|
|
||||||
### 1. Requirements extraction
|
### 1. Requirements extraction
|
||||||
|
|
@ -141,6 +148,10 @@ range.
|
||||||
- Plan complexity: {low|medium|high}
|
- Plan complexity: {low|medium|high}
|
||||||
- Assessment: {proportional | over-engineered | under-specified}
|
- 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
|
### Verdict
|
||||||
- Scope creep items: N
|
- Scope creep items: N
|
||||||
- Scope gaps: N
|
- Scope gaps: N
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ Extract from the plan:
|
||||||
|
|
||||||
**Manifest handling:**
|
**Manifest handling:**
|
||||||
- If `plan_version: 1.7` or later AND any step is missing a Manifest block:
|
- 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
|
STOP with error "Plan claims v1.7 but step N lacks Manifest.
|
||||||
planning-orchestrator." Do not attempt to synthesize.
|
Re-run /trekplan." Do not attempt to synthesize.
|
||||||
- If no `plan_version` marker is present: treat as legacy v1.6. Synthesize
|
- If no `plan_version` marker is present: treat as legacy v1.6. Synthesize
|
||||||
minimal manifests from `Files:` (expected_paths) and the Checkpoint commit
|
minimal manifests from `Files:` (expected_paths) and the Checkpoint commit
|
||||||
message (commit_message_pattern escaped). Mark output session specs with
|
message (commit_message_pattern escaped). Mark output session specs with
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
name: trekbrief
|
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.
|
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>"
|
argument-hint: "[--quick] <task description> | --approve <project-dir | brief-file>"
|
||||||
allowed-tools: Agent, Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion
|
allowed-tools: Agent, Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion, Skill
|
||||||
---
|
---
|
||||||
|
|
||||||
# Ultrabrief Local v2.1
|
# Ultrabrief Local v2.1
|
||||||
|
|
@ -40,15 +40,25 @@ Parse `$ARGUMENTS`:
|
||||||
2. Otherwise: **mode = default**. Interview probes each section until the
|
2. Otherwise: **mode = default**. Interview probes each section until the
|
||||||
completeness gate (Phase 3) and brief-review gate (Phase 4) both pass.
|
completeness gate (Phase 3) and brief-review gate (Phase 4) both pass.
|
||||||
|
|
||||||
3. `--gates` flag (autonomy control, may combine with any mode): when
|
3. `--gates` flag (autonomy control, may combine with any mode): `--gates`
|
||||||
present, set `gates_mode = true`. This re-enables approval pauses at
|
takes the next token as its value only when it is `true`, `false`,
|
||||||
every phase boundary in the downstream pipeline (research, plan,
|
`closed` or `open` (strip both); any other next token is not its value
|
||||||
execute) and at every wave in the executor. Default `gates_mode = false`
|
(strip only the flag). Run the shim once to map the value, bare when
|
||||||
means auto mode runs continuously until the main-merge gate (which is
|
there is no value:
|
||||||
the one boundary that ALWAYS pauses, regardless of `gates_mode`). Strip
|
|
||||||
the flag from `$ARGUMENTS` before further parsing. The flag is consumed
|
```bash
|
||||||
by the autonomy-gate state machine via the CLI shim:
|
node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state idle --event start --gates [value]
|
||||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
```
|
||||||
|
|
||||||
|
`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.
|
||||||
|
|
||||||
4. `--approve <project-dir | brief-file>`: set **mode = approve**. No
|
4. `--approve <project-dir | brief-file>`: set **mode = approve**. No
|
||||||
interview, no drafting. Set `APPROVE_ARG` to the argument and resolve it:
|
interview, no drafting. Set `APPROVE_ARG` to the argument and resolve it:
|
||||||
|
|
@ -159,17 +169,15 @@ Framing: {preserve | refine | replace | new-direction}
|
||||||
## Phase 3 — Completeness loop
|
## Phase 3 — Completeness loop
|
||||||
|
|
||||||
Phase 3 gathers the brief's content in **one question round**, sized by the
|
Phase 3 gathers the brief's content in **one question round**, sized by the
|
||||||
task's **size class** (ceremony by size). Facts are looked up, never asked;
|
task's **size class** (ceremony by size). Use `AskUserQuestion` for every question.
|
||||||
then every question that can be answered now goes out at once, each with the
|
|
||||||
recommended answer first. Use `AskUserQuestion` for every question.
|
|
||||||
|
|
||||||
### Step 3a — Look up facts first
|
**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
|
||||||
Never ask the operator a fact a helper can look up: which framework the repo
|
form: facts looked up first, never asked; one round with the recommended answer
|
||||||
uses, where a module lives, what the test command is, whether a file exists.
|
first; what you can predict and what is over the budget written down; the stop
|
||||||
Read the repo (Glob / Grep / Read, or a subagent for a wide search — never with
|
rule. This phase holds only what is `/trekbrief`'s own: the size class and its
|
||||||
the Agent tool's `name` parameter) and carry what you found into the round. The
|
budget (Step 3b), the fixed questions and where each answer lands in the brief
|
||||||
operator answers decisions and intent, not lookups.
|
(Step 3c).
|
||||||
|
|
||||||
### Step 3b — Ceremony by size (K1)
|
### Step 3b — Ceremony by size (K1)
|
||||||
|
|
||||||
|
|
@ -196,31 +204,23 @@ Put the task in one of three size classes. In doubt, take the heaviest that fits
|
||||||
|
|
||||||
### Step 3c — The question round
|
### 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,
|
1. **Candidates.** The coverage list is the question bank below (Intent, Goal,
|
||||||
Success Criteria, Research Plan, Non-Goals, Constraints, Preferences, NFRs,
|
Success Criteria, Research Plan, Non-Goals, Constraints, Preferences, NFRs,
|
||||||
Prior Attempts), plus three fixed questions every round carries: framing
|
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
|
(Phase 2.5, first), the size class (Step 3b) and where the brief is stored
|
||||||
(`artifact_store`, below).
|
(`artifact_store`, below).
|
||||||
2. **Drop what you can predict.** If the task description, the repo and the
|
2. **The budget is the class budget** (table below). A `bounded` or
|
||||||
answers so far let you predict the answer, do not ask: write the prediction
|
`architectural` round is consecutive `AskUserQuestion` calls with no
|
||||||
into `## Open Questions / Assumptions`, marked "assumed, not asked", where
|
drafting in between.
|
||||||
the operator sees it before approving.
|
3. **Where the written-down answers land.** Predictions ("assumed, not
|
||||||
3. **Rank the rest by Impact × Uncertainty**: how much the plan changes with
|
asked") and the Deferred list, one line of why each, go into
|
||||||
the answer, times how unsure you are of it. Ask the highest within the
|
`## Open Questions / Assumptions`, where the operator sees them before
|
||||||
class budget. Everything over the budget goes on a **Deferred** list, one
|
approving; the Deferred list is also printed with the round.
|
||||||
line of why each, printed with the round and written into
|
4. **Follow-ups by class.** A follow-up round is only for an answer that opens
|
||||||
`## Open Questions / Assumptions` — the budget never hides a gap.
|
a branch you cannot predict (`small`: never; `bounded`: at most one).
|
||||||
4. **One round.** All questions that can be answered now, in one
|
5. **Answers that decide nothing.** «høres bra ut», «gjør som du vil», "sounds
|
||||||
`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
|
good", "whatever you think" and an empty reply are not a decision. Record
|
||||||
the recommended answer as an assumption ("not confirmed — the answer was
|
the recommended answer as an assumption ("not confirmed — the answer was
|
||||||
«…»"), never as the operator's choice.
|
«…»"), never as the operator's choice.
|
||||||
|
|
@ -251,12 +251,9 @@ names, never the text.
|
||||||
one-way ratchet: obra/superpowers@8ca22db (MIT, © 2025 Jesse Vincent),
|
one-way ratchet: obra/superpowers@8ca22db (MIT, © 2025 Jesse Vincent),
|
||||||
skills/brainstorming. The class ladder: Kiro's docs (kiro.dev — Plan mode,
|
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
|
Quick Spec, full spec; read 2026-10-06; an idea only, Kiro is a closed
|
||||||
product). The round, the recommended answer first and "never ask a fact":
|
product). The answers that decide nothing (Step 3c, point 5):
|
||||||
mattpocock/skills@c55ee46 (MIT), productivity/grilling. The budget,
|
addyosmani/agent-skills@9d0c60d (MIT, © 2025 Addy Osmani), skills/interview-me.
|
||||||
Impact × Uncertainty and the Deferred list: GitHub Spec Kit (MIT),
|
The interview form's own credits are in `voyage:interviewing`.
|
||||||
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
|
### Internal state
|
||||||
|
|
||||||
|
|
@ -327,7 +324,8 @@ sentence with your recommended answer first.
|
||||||
- _Follow-up_: "How would you recognize this is done when looking at
|
- _Follow-up_: "How would you recognize this is done when looking at
|
||||||
the UI / API / codebase?"
|
the UI / API / codebase?"
|
||||||
|
|
||||||
**Success Criteria** (required):
|
**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.
|
||||||
- _Anchor_: "How do we verify it is actually done? List 2–4 concrete,
|
- _Anchor_: "How do we verify it is actually done? List 2–4 concrete,
|
||||||
testable conditions — commands to run, observations, or metrics."
|
testable conditions — commands to run, observations, or metrics."
|
||||||
A command the review can run is one test-runner call (`npm test`,
|
A command the review can run is one test-runner call (`npm test`,
|
||||||
|
|
@ -622,7 +620,8 @@ Build the brief text from Phase 3 state by filling the template:
|
||||||
- **Non-Goals:** from state, or "- None explicitly stated" bullet if empty.
|
- **Non-Goals:** from state, or "- None explicitly stated" bullet if empty.
|
||||||
- **Constraints / Preferences / NFRs:** from state, or "Not discussed — no
|
- **Constraints / Preferences / NFRs:** from state, or "Not discussed — no
|
||||||
constraints assumed" note if empty.
|
constraints assumed" note if empty.
|
||||||
- **Success Criteria:** falsifiable commands/observations from state.
|
- **Success Criteria:** falsifiable commands/observations from state, each
|
||||||
|
written in the form of `voyage:writing-criteria`.
|
||||||
- **Research Plan:** one `### Topic N: {title}` section per topic with the
|
- **Research Plan:** one `### Topic N: {title}` section per topic with the
|
||||||
full structure from the template. If 0 topics: write the "No external
|
full structure from the template. If 0 topics: write the "No external
|
||||||
research needed — user confirmed solid knowledge of all plan
|
research needed — user confirmed solid knowledge of all plan
|
||||||
|
|
@ -664,8 +663,9 @@ 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`.
|
> "Review this task brief for quality: `{PROJECT_DIR}/brief.md.draft`.
|
||||||
> Check completeness, consistency, testability, scope clarity,
|
> Check completeness, consistency, testability, scope clarity,
|
||||||
> research-plan validity, and memory alignment. Report findings, verdict, and
|
> research-plan validity, and memory alignment. Judge the success criteria by
|
||||||
> the required machine-readable JSON block.
|
> `voyage:writing-criteria` and review by `voyage:reviewing-adversarially`.
|
||||||
|
> Report findings, verdict, and the required machine-readable JSON block.
|
||||||
> Operator memory context (compare the brief's Intent/Goal and its declared
|
> Operator memory context (compare the brief's Intent/Goal and its declared
|
||||||
> `framing:` value against these for EXPLICIT contradictions only):
|
> `framing:` value against these for EXPLICIT contradictions only):
|
||||||
> {memory paths or excerpts, or "none supplied"}."
|
> {memory paths or excerpts, or "none supplied"}."
|
||||||
|
|
@ -830,7 +830,8 @@ 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,
|
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
|
note them in the final report — except `BRIEF_SC_NOT_RUNNABLE`: a success
|
||||||
criterion whose command `/trekreview` will never run (the product's own
|
criterion whose command `/trekreview` will never run (the product's own
|
||||||
binary, `jq`, `grep`, a pipe). Name each one to the user in plain words and
|
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
|
||||||
offer to rewrite it as a script under `tests/` that the criterion runs
|
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
|
(`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
|
keeps it, it stays a criterion a human judges, and the report says so. The
|
||||||
|
|
@ -840,14 +841,11 @@ sub-point) and `BRIEF_SC_BASH_NOT_PINNED` (the brief requires bash 3.2 but a
|
||||||
criterion runs plain `bash`: offer `/bin/bash`).
|
criterion runs plain `bash`: offer `/bin/bash`).
|
||||||
|
|
||||||
**Build the operator-annotation HTML, then print the report.** After the
|
**Build the operator-annotation HTML, then print the report.** After the
|
||||||
brief is validated, run `scripts/annotate.mjs` to produce a self-contained
|
brief is validated, run `scripts/annotate.mjs` to build the page where the
|
||||||
HTML file the operator opens in their browser. The HTML renders the brief
|
operator writes their own notes. The loop that follows is the skill
|
||||||
with line numbers, lets the operator click any line to attach their own
|
`voyage:annotating`: call it when the operator pastes the notes back (a
|
||||||
note (not Claude-generated suggestions — the operator drives every
|
Question is answered, not applied; after Phase 4h, a note on `## Intent` or
|
||||||
annotation), keeps a sidebar of all notes, persists state in localStorage,
|
`## Goal` makes the approval stale, and that is said before the edit).
|
||||||
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
|
```bash
|
||||||
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{PROJECT_DIR}/brief.md" 2>&1)
|
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{PROJECT_DIR}/brief.md" 2>&1)
|
||||||
|
|
@ -876,9 +874,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,
|
Click any line to add YOUR OWN note. The sidebar collects every note,
|
||||||
the "Copy Prompt" button gathers them into one structured prompt.
|
the "Copy Prompt" button gathers them into one structured prompt.
|
||||||
Paste that prompt back into this chat and Claude revises brief.md
|
Paste that prompt back into this chat: Claude answers each Question
|
||||||
from your notes. Annotations persist in your browser if you close
|
and revises brief.md from your Fix and Change notes. Annotations
|
||||||
the tab and reopen the same file.
|
persist in your browser if you close the tab and reopen the same file.
|
||||||
────────────────────────────────────────────────────────────────────
|
────────────────────────────────────────────────────────────────────
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -977,7 +975,10 @@ printed `stamped: true`, then stop and print the next step:
|
||||||
|
|
||||||
## Phase 5 — Auto-orchestration opt-in (if research_topics > 0)
|
## Phase 5 — Auto-orchestration opt-in (if research_topics > 0)
|
||||||
|
|
||||||
**Skip this phase if research_topics = 0.** Proceed directly to Phase 6.
|
**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.
|
||||||
|
|
||||||
Ask the user via `AskUserQuestion`:
|
Ask the user via `AskUserQuestion`:
|
||||||
|
|
||||||
|
|
@ -1011,13 +1012,13 @@ Then:
|
||||||
/trekexecute --project {PROJECT_DIR}
|
/trekexecute --project {PROJECT_DIR}
|
||||||
```
|
```
|
||||||
|
|
||||||
Stop. Do not continue to Phase 6.
|
Run Phase 7 (`auto_result: manual`), then stop. Do not continue to Phase 6.
|
||||||
|
|
||||||
### Auto path
|
### Auto path
|
||||||
|
|
||||||
**Auto requires an approved intent.** If Phase 4h ended "Leave unapproved",
|
**Auto requires an approved intent.** If Phase 4h ended "Leave unapproved",
|
||||||
the auto chain would halt at `/trekplan` anyway — print the manual-path
|
the auto chain would halt at `/trekplan` anyway — print the manual-path
|
||||||
output instead and stop.
|
output instead, run Phase 7 (`auto_result: manual`) and stop.
|
||||||
|
|
||||||
Set `auto_research: true` in the brief's frontmatter (edit the file).
|
Set `auto_research: true` in the brief's frontmatter (edit the file).
|
||||||
|
|
||||||
|
|
@ -1026,18 +1027,18 @@ stamp — on both paths — so it is not emitted again here.
|
||||||
|
|
||||||
If `gates_mode == true`: pause here via `AskUserQuestion` —
|
If `gates_mode == true`: pause here via `AskUserQuestion` —
|
||||||
"Auto-mode confirmed. Proceed to research now? (yes/no)". If the user
|
"Auto-mode confirmed. Proceed to research now? (yes/no)". If the user
|
||||||
answers no, fall back to the manual path output and stop. Otherwise
|
answers no, fall back to the manual path output, run Phase 7
|
||||||
proceed to Phase 6.
|
(`auto_result: cancelled`) and stop. Otherwise proceed to Phase 6.
|
||||||
|
|
||||||
If `gates_mode == false` (default in auto): proceed directly to Phase 6.
|
If `gates_mode == false` (default in auto): proceed directly to Phase 6.
|
||||||
The chain stops only at the main-merge gate (see `commands/trekexecute.md`
|
The chain ends when `/trekplan` has written the plan (Step 6e); it never
|
||||||
Phase 8).
|
starts `/trekexecute`.
|
||||||
|
|
||||||
Proceed to Phase 6.
|
Proceed to Phase 6.
|
||||||
|
|
||||||
## Phase 6 — Auto research dispatch (auto path only)
|
## Phase 6 — Auto research dispatch (auto path only)
|
||||||
|
|
||||||
**Runs only when user opted into auto mode.**
|
**Runs only when user opted into auto mode, and only after Phase 4h approved the intent.**
|
||||||
|
|
||||||
### Step 6a — Confirm proceed
|
### Step 6a — Confirm proceed
|
||||||
|
|
||||||
|
|
@ -1051,9 +1052,10 @@ Continue?"
|
||||||
| Option | Action |
|
| Option | Action |
|
||||||
|--------|--------|
|
|--------|--------|
|
||||||
| **Continue — auto** | Proceed. |
|
| **Continue — auto** | Proceed. |
|
||||||
| **Cancel — do manual** | Revert to manual path (print commands, stop). |
|
| **Cancel — do manual** | Revert to manual path (run Phase 7 with `auto_result: cancelled`, print commands, stop). |
|
||||||
|
|
||||||
If cancelled → fall back to manual path output and stop.
|
If cancelled → fall back to manual path output, run Phase 7
|
||||||
|
(`auto_result: cancelled`) and stop.
|
||||||
|
|
||||||
### Step 6b — Run research topics sequentially (inline)
|
### Step 6b — Run research topics sequentially (inline)
|
||||||
|
|
||||||
|
|
@ -1090,7 +1092,8 @@ ls -1 {PROJECT_DIR}/research/*.md | wc -l
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected count: N. If any are missing, report and ask the user how to
|
Expected count: N. If any are missing, report and ask the user how to
|
||||||
proceed (retry, skip missing topic, cancel).
|
proceed (retry, skip missing topic, cancel). On cancel, run Phase 7
|
||||||
|
(`auto_result: cancelled`) and stop.
|
||||||
|
|
||||||
Update brief frontmatter: `research_status: complete`.
|
Update brief frontmatter: `research_status: complete`.
|
||||||
|
|
||||||
|
|
@ -1104,11 +1107,12 @@ Invoke the planning command inline in this session:
|
||||||
|
|
||||||
The planning pipeline runs all phases (exploration, synthesis, review) in
|
The planning pipeline runs all phases (exploration, synthesis, review) in
|
||||||
main context. Wait for the plan to be written to `{PROJECT_DIR}/plan.md`
|
main context. Wait for the plan to be written to `{PROJECT_DIR}/plan.md`
|
||||||
before continuing.
|
before continuing. If `/trekplan` stops before it writes the plan, report
|
||||||
|
where it stopped, run Phase 7 (`auto_result: failed`) and stop.
|
||||||
|
|
||||||
### Step 6e — Report completion
|
### Step 6e — Report completion
|
||||||
|
|
||||||
When the planning-orchestrator finishes, present:
|
When /trekplan finishes, present:
|
||||||
|
|
||||||
```
|
```
|
||||||
## Ultrabrief + Ultraresearch + Voyage Complete (auto mode)
|
## Ultrabrief + Ultraresearch + Voyage Complete (auto mode)
|
||||||
|
|
@ -1196,9 +1200,6 @@ Examples:
|
||||||
VOYAGE_PROFILE=balanced /trekbrief
|
VOYAGE_PROFILE=balanced /trekbrief
|
||||||
```
|
```
|
||||||
|
|
||||||
Stats records emit `profile`, `phase_models`, and `profile_source` so operators
|
|
||||||
can audit which profile drove which session.
|
|
||||||
|
|
||||||
## Hard rules
|
## Hard rules
|
||||||
|
|
||||||
1. **Interactive only.** This command requires user input. There is no
|
1. **Interactive only.** This command requires user input. There is no
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,22 @@ See **Handover 7** in `docs/HANDOVER-CONTRACTS.md` for the full schema.
|
||||||
|
|
||||||
## Phase 0 — `--help` handling
|
## Phase 0 — `--help` handling
|
||||||
|
|
||||||
Parse `$ARGUMENTS` with `parseArgs($ARGUMENTS, 'trekcontinue')` from
|
Parse `$ARGUMENTS` with the shared arg-parser. Run first, exactly like this:
|
||||||
`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):
|
```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):
|
||||||
|
|
||||||
- `flags['--help'] === true`, OR
|
- `flags['--help'] === true`, OR
|
||||||
- `positional[0] === '-h'` (single-dash short form — the parser keeps it as
|
- `positional[0] === '-h'` (single-dash short form — the parser keeps it as
|
||||||
|
|
@ -75,7 +88,7 @@ Typical flow:
|
||||||
|
|
||||||
## Phase 0.5 — Cleanup mode dispatch
|
## Phase 0.5 — Cleanup mode dispatch
|
||||||
|
|
||||||
After `parseArgs` has resolved `$ARGUMENTS`, check the parsed `flags`
|
After the parser has printed its parse of `$ARGUMENTS`, check the parsed `flags`
|
||||||
object directly (NOT a string contains-check on raw `$ARGUMENTS` — that
|
object directly (NOT a string contains-check on raw `$ARGUMENTS` — that
|
||||||
substring pattern was the root cause of Bug 1).
|
substring pattern was the root cause of Bug 1).
|
||||||
|
|
||||||
|
|
@ -174,23 +187,28 @@ locations; this phase refuses ambiguity before validating the state file.
|
||||||
After resolving the project directory and state-file path, look for two
|
After resolving the project directory and state-file path, look for two
|
||||||
`NEXT-SESSION-PROMPT.local.md` candidates:
|
`NEXT-SESSION-PROMPT.local.md` candidates:
|
||||||
|
|
||||||
a. `<plugin-root>/NEXT-SESSION-PROMPT.local.md` — operator-managed master file
|
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
|
||||||
b. `<project-dir>/NEXT-SESSION-PROMPT.local.md` — producer-written sibling
|
b. `<project-dir>/NEXT-SESSION-PROMPT.local.md` — producer-written sibling
|
||||||
|
|
||||||
**If both exist:**
|
**If both exist:**
|
||||||
|
|
||||||
- Read both via the **Read tool** (NOT Bash — same anti-substitution rule
|
- Read both via the **Read tool** (NOT Bash — same anti-substitution rule
|
||||||
as Phase 2).
|
as Phase 2).
|
||||||
- Invoke the consistency validator with both paths emitted as concrete
|
- Invoke the consistency validator with the paths emitted as concrete
|
||||||
literal tokens (no template substitution at the Bash boundary):
|
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):
|
||||||
|
|
||||||
```
|
```
|
||||||
node ${CLAUDE_PLUGIN_ROOT}/lib/validators/next-session-prompt-validator.mjs --json --consistency <RESOLVED-PATH-A> <RESOLVED-PATH-B>
|
node ${CLAUDE_PLUGIN_ROOT}/lib/validators/next-session-prompt-validator.mjs --json --consistency <RESOLVED-PATH-A> <RESOLVED-PATH-B> --state-file <RESOLVED-PATH-STATE>
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `<RESOLVED-PATH-A>` and `<RESOLVED-PATH-B>` with the two concrete
|
Replace `<RESOLVED-PATH-A>` and `<RESOLVED-PATH-B>` with the two concrete
|
||||||
filesystem paths you have in your working context. The validator emits
|
filesystem paths you have in your working context, and
|
||||||
`{valid, errors, warnings}` JSON on stdout.
|
`<RESOLVED-PATH-STATE>` with the concrete path of the project's
|
||||||
|
`.session-state.local.json`. The validator emits `{valid, errors, warnings}`
|
||||||
|
JSON on stdout.
|
||||||
|
|
||||||
- **If `valid: false`** (typically `NEXT_SESSION_PROMPT_PRODUCER_MISMATCH`):
|
- **If `valid: false`** (typically `NEXT_SESSION_PROMPT_PRODUCER_MISMATCH`):
|
||||||
print the structured `errors[]` (each `[code] message` on its own line),
|
print the structured `errors[]` (each `[code] message` on its own line),
|
||||||
|
|
@ -328,8 +346,6 @@ Examples:
|
||||||
VOYAGE_PROFILE=economy /trekcontinue # env-var override
|
VOYAGE_PROFILE=economy /trekcontinue # env-var override
|
||||||
```
|
```
|
||||||
|
|
||||||
Stats records emit `profile` and `profile_source` per Phase 5 record.
|
|
||||||
|
|
||||||
## Hard rules
|
## Hard rules
|
||||||
|
|
||||||
- **Idempotent.** Running `/trekcontinue` twice in the same Claude session
|
- **Idempotent.** Running `/trekcontinue` twice in the same Claude session
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
name: trekendsession
|
name: trekendsession
|
||||||
description: Mark the current session as complete and write session-state pointing at the next session. Helper for informal multi-session flows.
|
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"
|
argument-hint: "<next-brief-path> <next-label> | --help"
|
||||||
|
disable-model-invocation: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Voyage End-Session Local v1.0
|
# Voyage End-Session Local v1.0
|
||||||
|
|
@ -29,8 +30,32 @@ See **Handover 7** in `docs/HANDOVER-CONTRACTS.md` for the schema.
|
||||||
|
|
||||||
## Phase 0 — `--help` handling
|
## Phase 0 — `--help` handling
|
||||||
|
|
||||||
If `$ARGUMENTS` contains `--help` or `-h`, print the usage block below and exit
|
Parse `$ARGUMENTS` with the arg parser. Run this via the Bash tool at runtime
|
||||||
cleanly. Do NOT proceed to any further phase.
|
(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.
|
||||||
|
|
||||||
```
|
```
|
||||||
/trekendsession — Mark current session done; point at next session.
|
/trekendsession — Mark current session done; point at next session.
|
||||||
|
|
@ -76,8 +101,10 @@ Decision tree:
|
||||||
|
|
||||||
## Phase 2 — Required args check (headless-safe)
|
## Phase 2 — Required args check (headless-safe)
|
||||||
|
|
||||||
Read `$ARGUMENTS`. Both `<next-brief-path>` and `<next-label>` are required.
|
Read the parse result from Phase 0: `<next-brief-path>` is `positional[0]`
|
||||||
If either is missing or empty:
|
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:
|
||||||
|
|
||||||
```
|
```
|
||||||
Error: missing required args.
|
Error: missing required args.
|
||||||
|
|
@ -108,29 +135,41 @@ 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
|
`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).
|
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
|
This phase ALSO writes a sibling `NEXT-SESSION-PROMPT.local.md` in the
|
||||||
project directory with YAML frontmatter (`produced_by: trekendsession`,
|
project directory with YAML frontmatter (`produced_by: trekendsession`,
|
||||||
`produced_at: {ISO-8601}`, `project: {project_dir}`). Both files are written
|
`produced_at: {ISO-8601}`, `project: {project_dir}`). Both files are written
|
||||||
in a single ESM block so the writes succeed or fail together.
|
in a single ESM block so the writes succeed or fail together.
|
||||||
|
|
||||||
Run the block below via the Bash tool at runtime, substituting the resolved
|
Run the block below via the Bash tool at runtime, exactly as written: put no
|
||||||
values for the `{curly}` placeholders (Phase 1 gives `{project_dir}`, Phase 2
|
value from Phase 1 or Phase 2 into it. This is NOT an eager-exec block — the
|
||||||
gives `{next_brief_path}` and `{next_label}`). This is NOT an eager-exec
|
files do not exist at command-load time. The block takes nothing on its shell
|
||||||
block — the values do not exist at command-load time. The import path must
|
line: it re-reads the arguments as the one line inside the quoted heredoc, on
|
||||||
stay absolute via `${CLAUDE_PLUGIN_ROOT}` — your Bash cwd is the user's
|
stdin, never as shell words (the heredoc is the last thing in the command),
|
||||||
repo, not the plugin root, so a cwd-relative import throws
|
parses them with the same `parseArgs` as Phase 0 (the brief path is
|
||||||
`ERR_MODULE_NOT_FOUND`:
|
`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`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node --input-type=module -e "
|
node --input-type=module -e "
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { writeFileSync } from 'node:fs';
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||||
import { atomicWriteJson } from '${CLAUDE_PLUGIN_ROOT}/lib/util/atomic-write.mjs';
|
import { atomicWriteJson } from '${CLAUDE_PLUGIN_ROOT}/lib/util/atomic-write.mjs';
|
||||||
const [, dir, brief, label] = process.argv;
|
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 now = new Date().toISOString();
|
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 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');
|
const stateFile = path.join(dir, '.session-state.local.json');
|
||||||
|
|
@ -140,7 +179,9 @@ const promptBody = '---\\nproduced_by: trekendsession\\nproduced_at: ' + now + '
|
||||||
writeFileSync(promptFile, promptBody);
|
writeFileSync(promptFile, promptBody);
|
||||||
console.log(stateFile);
|
console.log(stateFile);
|
||||||
console.log(promptFile);
|
console.log(promptFile);
|
||||||
" '{project_dir}' '{next_brief_path}' '{next_label}'
|
" <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||||
|
$ARGUMENTS
|
||||||
|
VOYAGE_ARGS_EOF_7F3C9E
|
||||||
```
|
```
|
||||||
|
|
||||||
## Phase 4 — Validate + narrate
|
## Phase 4 — Validate + narrate
|
||||||
|
|
@ -176,6 +217,7 @@ before retrying — usually means a bad path or label argument.
|
||||||
- **Atomic write only.** Tmp + rename — no partial state files on disk.
|
- **Atomic write only.** Tmp + rename — no partial state files on disk.
|
||||||
- **Zero secrets.** Status, paths, labels — never API keys, never user content
|
- **Zero secrets.** Status, paths, labels — never API keys, never user content
|
||||||
beyond filenames.
|
beyond filenames.
|
||||||
- **NEVER auto-invoke this command.** It is operator-typed only at session-end.
|
- **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).
|
||||||
- **Idempotent within a session.** Running twice with the same args
|
- **Idempotent within a session.** Running twice with the same args
|
||||||
overwrites cleanly (atomic rename); does not double-advance.
|
overwrites cleanly (atomic rename); does not double-advance.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
name: trekexecute
|
name: trekexecute
|
||||||
description: Disciplined plan executor — single-session, or multi-session through session orders the user starts, with failure recovery
|
description: Disciplined plan executor — single-session, or multi-session through session orders the user starts, with failure recovery
|
||||||
argument-hint: "[--project <dir>] [--fg | --resume | --dry-run | --validate | --step N | --session N] [plan.md]"
|
argument-hint: "[--project <dir>] [--profile <name>] [--gates [true|false|closed|open]] [--fg | --resume | --dry-run | --validate | --step N | --session N] [plan.md]"
|
||||||
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent, Skill
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent, Skill
|
||||||
disallowed-tools: TeamCreate
|
disallowed-tools: TeamCreate
|
||||||
---
|
---
|
||||||
|
|
@ -48,6 +48,22 @@ Parse `$ARGUMENTS` for mode flags:
|
||||||
use that path but keep `project_dir` set (user may be pointing at a
|
use that path but keep `project_dir` set (user may be pointing at a
|
||||||
recovery session spec inside the project).
|
recovery session spec inside the project).
|
||||||
- Continue parsing remaining flags (they combine with `--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**.
|
2. If arguments contain `--fg`: extract the file path. Set **mode = foreground**.
|
||||||
3. If arguments contain `--resume`: extract the file path. Set **mode = resume**.
|
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**.
|
4. If arguments contain `--dry-run`: extract the file path. Set **mode = dry-run**.
|
||||||
|
|
@ -56,10 +72,22 @@ Parse `$ARGUMENTS` for mode flags:
|
||||||
Set **mode = step**, **target-step = N**.
|
Set **mode = step**, **target-step = N**.
|
||||||
7. If arguments contain `--session N` (N is a positive integer): extract N and the file path.
|
7. If arguments contain `--session N` (N is a positive integer): extract N and the file path.
|
||||||
Set **mode = session**, **target-session = N**.
|
Set **mode = session**, **target-session = N**.
|
||||||
8. If arguments contain `--gates`: set `gates_mode = true`. Default
|
8. If arguments contain `--gates`: `--gates` takes the next token as its
|
||||||
`gates_mode = false`. The flag is consumed by the autonomy-gate state
|
value only when it is `true`, `false`, `closed` or `open` (strip both);
|
||||||
machine via the CLI shim:
|
any other next token is not its value (strip only the flag). Run the shim
|
||||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
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).
|
||||||
It no longer adds a question of the executor's own before a merge. The
|
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
|
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,
|
asked by the guard, which asks before every merge into main and every push,
|
||||||
|
|
@ -67,7 +95,9 @@ Parse `$ARGUMENTS` for mode flags:
|
||||||
(operator decision 2026-10-08: two questions for one merge became one). The
|
(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
|
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.
|
a lock, and the guard's question is the one question.
|
||||||
9. Otherwise: the entire argument string is the file path. Set **mode = execute**.
|
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**.
|
||||||
|
|
||||||
If no path is provided (and `--project` was not used to derive one), output
|
If no path is provided (and `--project` was not used to derive one), output
|
||||||
usage and stop:
|
usage and stop:
|
||||||
|
|
@ -81,6 +111,7 @@ Usage: /trekexecute <plan.md>
|
||||||
/trekexecute --validate <plan.md>
|
/trekexecute --validate <plan.md>
|
||||||
/trekexecute --step N <plan.md>
|
/trekexecute --step N <plan.md>
|
||||||
/trekexecute --session N <plan.md>
|
/trekexecute --session N <plan.md>
|
||||||
|
/trekexecute --profile <name> <plan.md>
|
||||||
/trekexecute --project <dir> --resume
|
/trekexecute --project <dir> --resume
|
||||||
/trekexecute --project <dir> --session N
|
/trekexecute --project <dir> --session N
|
||||||
|
|
||||||
|
|
@ -94,6 +125,8 @@ Modes:
|
||||||
--validate Schema-only check — parse steps + manifests, no security scan, no execution
|
--validate Schema-only check — parse steps + manifests, no security scan, no execution
|
||||||
--step N Execute only step N (foreground)
|
--step N Execute only step N (foreground)
|
||||||
--session N Execute only session N from the plan's Execution Strategy
|
--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:
|
Examples:
|
||||||
/trekexecute .claude/plans/trekplan-2026-04-06-auth-refactor.md
|
/trekexecute .claude/plans/trekplan-2026-04-06-auth-refactor.md
|
||||||
|
|
@ -236,7 +269,7 @@ mode; absence or <1.7 as legacy mode.
|
||||||
- If any step is missing its Manifest, or YAML is malformed, STOP with:
|
- 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.
|
Error: plan_version=1.7 but step {N} has invalid/missing Manifest.
|
||||||
Re-run planning-orchestrator — plan is not executable.
|
Re-run /trekplan — the plan is not executable.
|
||||||
```
|
```
|
||||||
|
|
||||||
**Legacy mode (no plan_version, or < 1.7):**
|
**Legacy mode (no plan_version, or < 1.7):**
|
||||||
|
|
@ -334,11 +367,11 @@ Reason: {specific error from Phase 2}
|
||||||
{if format not recognized}:
|
{if format not recognized}:
|
||||||
Detected heading format: {e.g. "### Fase 1:", "## Phase 1"}
|
Detected heading format: {e.g. "### Fase 1:", "## Phase 1"}
|
||||||
Expected: "### Step N: <description>"
|
Expected: "### Step N: <description>"
|
||||||
Fix: re-run /trekplan — planning-orchestrator must emit v1.7 format
|
Fix: re-run /trekplan — the plan must use v1.7 format
|
||||||
|
|
||||||
{if missing manifest}:
|
{if missing manifest}:
|
||||||
Step {N} has no Manifest block (plan_version=1.7 requires one per step)
|
Step {N} has no Manifest block (plan_version=1.7 requires one per step)
|
||||||
Fix: re-run /trekplan — planning-orchestrator must include manifest YAML
|
Fix: re-run /trekplan — every step needs a Manifest YAML block
|
||||||
|
|
||||||
{if malformed YAML or invalid regex}:
|
{if malformed YAML or invalid regex}:
|
||||||
Step {N}: {specific YAML/regex error}
|
Step {N}: {specific YAML/regex error}
|
||||||
|
|
@ -432,6 +465,7 @@ Determine how to execute this plan:
|
||||||
- `--step N` mode
|
- `--step N` mode
|
||||||
- `--resume` mode
|
- `--resume` mode
|
||||||
- `--session N` mode (runs only that session's steps, foreground)
|
- `--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 no `## Execution Strategy` section
|
||||||
- Plan has Execution Strategy with only 1 session
|
- Plan has Execution Strategy with only 1 session
|
||||||
|
|
||||||
|
|
@ -582,9 +616,8 @@ These sessions cannot safely run in parallel.
|
||||||
Fix the Execution Strategy in the plan, or use --fg for sequential execution.
|
Fix the Execution Strategy in the plan, or use --fg for sequential execution.
|
||||||
```
|
```
|
||||||
|
|
||||||
Stop execution. This is a defense-in-depth check — the planning-orchestrator
|
Stop execution. This check runs at execution time, so it also catches a plan
|
||||||
should have prevented this, but verifying at execution time catches plans
|
that was edited by hand after planning.
|
||||||
that were manually edited or have bugs.
|
|
||||||
|
|
||||||
### Check 4 — Stale worktree cleanup
|
### Check 4 — Stale worktree cleanup
|
||||||
|
|
||||||
|
|
@ -1151,6 +1184,7 @@ progress file.
|
||||||
"exit_condition_checked": false,
|
"exit_condition_checked": false,
|
||||||
"plan_verification": null,
|
"plan_verification": null,
|
||||||
"end_to_end": null,
|
"end_to_end": null,
|
||||||
|
"run_seen": null,
|
||||||
"arch_rules": null,
|
"arch_rules": null,
|
||||||
"scope_sweep": null,
|
"scope_sweep": null,
|
||||||
"simplify": null,
|
"simplify": null,
|
||||||
|
|
@ -1173,6 +1207,7 @@ 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}.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 |
|
| `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)) |
|
| `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) |
|
| `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
|
`progress-validator.mjs` rejects `fix_rounds` outside 0–5 (there is no sixth
|
||||||
|
|
@ -1275,7 +1310,7 @@ but do not block.
|
||||||
**Also write sibling `NEXT-SESSION-PROMPT.local.md`** with frontmatter
|
**Also write sibling `NEXT-SESSION-PROMPT.local.md`** with frontmatter
|
||||||
(`produced_by: trekexecute`, `produced_at: <ISO-8601>`,
|
(`produced_by: trekexecute`, `produced_at: <ISO-8601>`,
|
||||||
`status: stopped`) — same combined ESM pattern as Phase 8 — so Phase 1.5
|
`status: stopped`) — same combined ESM pattern as Phase 8 — so Phase 1.5
|
||||||
of `/trekcontinue` can compare project-dir and plugin-root candidates.
|
of `/trekcontinue` can compare project-dir and repo-root candidates.
|
||||||
|
|
||||||
If the entry condition **passes**:
|
If the entry condition **passes**:
|
||||||
```
|
```
|
||||||
|
|
@ -1522,7 +1557,21 @@ 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
|
**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
|
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: launch a fresh
|
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
|
||||||
`build` helper for the revised step.
|
`build` helper for the revised step.
|
||||||
|
|
||||||
- **Never pass the Agent tool's `name` parameter.** A named spawn becomes an
|
- **Never pass the Agent tool's `name` parameter.** A named spawn becomes an
|
||||||
|
|
@ -1839,7 +1888,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 |
|
| 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 |
|
| 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 diff {start_sha}` to
|
**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
|
||||||
`{report dir}/step-{N}-upward.diff` and write `{report dir}/step-{N}-upward.md`:
|
`{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 step verbatim, every round's findings and verdicts, and the question for
|
||||||
the planner — which assumption in the step (its Changes, its Interface, its
|
the planner — which assumption in the step (its Changes, its Interface, its
|
||||||
|
|
@ -1862,7 +1911,9 @@ 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}
|
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 —
|
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.
|
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).
|
||||||
When the guard refuses the restore (it is destructive git: in the permission
|
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
|
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`
|
the operator declines it, nothing was restored: write in `step-{N}-upward.md`
|
||||||
|
|
@ -1906,6 +1957,10 @@ or 5). Release the step's test lock before stopping
|
||||||
command exactly as written in the plan. (The test files are listed apart
|
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
|
from `Files:` in the plan; staging only `Files:` would leave the step's
|
||||||
test uncommitted and charge it to the next step's diff.)
|
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
|
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.
|
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
|
2. **The done line**, at the step's own commit. A step is done only when a
|
||||||
|
|
@ -1944,7 +1999,7 @@ already passed) but is recorded as `checkpoint_drift: {expected_pattern,
|
||||||
actual_message}` in the progress file. Phase 7.5 audit reports drift as
|
actual_message}` in the progress file. Phase 7.5 audit reports drift as
|
||||||
an advisory.
|
an advisory.
|
||||||
|
|
||||||
Update progress: `steps.{N}.status = "completed"`, `steps.{N}.commit = {hash}`,
|
Update progress: `steps.{N}.status = "completed"`, `steps.{N}.commit = {hash}` (the full commit id),
|
||||||
`steps.{N}.completed_at = now`, `steps.{N}.manifest_audit = "pass"`.
|
`steps.{N}.completed_at = now`, `steps.{N}.manifest_audit = "pass"`.
|
||||||
|
|
||||||
### Step mode exit
|
### Step mode exit
|
||||||
|
|
@ -2072,7 +2127,9 @@ verification failure must not hide a manifest drift.
|
||||||
|
|
||||||
### End to end — "run the thing" (P9 (6))
|
### End to end — "run the thing" (P9 (6))
|
||||||
|
|
||||||
Tests passing is not the product working. Copy `end_to_end.status` from the
|
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
|
||||||
runner's JSON into `end_to_end` — the runner decides it, not this prose:
|
runner's JSON into `end_to_end` — the runner decides it, not this prose:
|
||||||
|
|
||||||
- `"verified"` — the verification passed and at least one passed criterion
|
- `"verified"` — the verification passed and at least one passed criterion
|
||||||
|
|
@ -2089,6 +2146,12 @@ 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
|
`End-to-end:` command missing from `## Verification`: the plan validator
|
||||||
rejects that as `PLAN_END_TO_END_NOT_VERIFIED`.)
|
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)
|
### Architecture rules (K5) and the plan-file sweep (K6)
|
||||||
|
|
||||||
Two whole-run checks, for a trekplan and a session spec alike, in one Bash
|
Two whole-run checks, for a trekplan and a session spec alike, in one Bash
|
||||||
|
|
@ -2208,18 +2271,26 @@ never typed by the operator, in this order (Cherny's):
|
||||||
run — no project directory", and the merge stays closed (Phase 8).
|
run — no project directory", and the merge stays closed (Phase 8).
|
||||||
**Its writes are committed.** `/trekreview` may have written approved
|
**Its writes are committed.** `/trekreview` may have written approved
|
||||||
project-memory lines (`.claude/rules/voyage-review-lessons.md`) and a
|
project-memory lines (`.claude/rules/voyage-review-lessons.md`) and a
|
||||||
one-line pointer in `CLAUDE.md`. Commit exactly those paths, when they
|
one-line pointer in `CLAUDE.md`. Commit only those of them that changed
|
||||||
changed, as `docs(voyage): review lessons (round {R})`: a process commit
|
and git does not ignore (`git check-ignore -q -- {path}` exits 1; exit 0
|
||||||
(Phase 7.5 step 3). Nothing the review wrote is left uncommitted for the
|
means ignored), as `docs(voyage): review lessons (round {R})`: a process
|
||||||
next round's checks or for the merge.
|
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.
|
||||||
4. **`verdict-gate.mjs`** — the review's verdict decides, as a command:
|
4. **`verdict-gate.mjs`** — the review's verdict decides, as a command:
|
||||||
```bash
|
```bash
|
||||||
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{project_dir}/review.md"
|
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{project_dir}/review.md" --repo .
|
||||||
```
|
```
|
||||||
Record `review = {round, path, gate_exit, verdict}`. Exit 0 (ALLOW/WARN) →
|
`--repo .` checks that an ALLOW/WARN review is of the commit being merged:
|
||||||
Phase 7.5. Exit 2 (could not decide, or a reviewer or engine that did not
|
its `scope_sha_end` is HEAD, or an ancestor of HEAD whose later commits
|
||||||
run) → Phase 7.5 with the merge closed: never green. Exit 1 (BLOCK) → the
|
change only the review lessons and the `CLAUDE.md` pointer (step 3's
|
||||||
loop below.
|
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.
|
||||||
|
|
||||||
**A BLOCK is fixed by new plan steps, in a bounded loop.** The review writes
|
**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`
|
every BLOCKER as a numbered `### Step R<n>` under `## Remediation Steps`
|
||||||
|
|
@ -2359,7 +2430,7 @@ Record in progress file:
|
||||||
> 1. **Objective predicate** — the **Phase 7.5** manifest audit (above) PASSED,
|
> 1. **Objective predicate** — the **Phase 7.5** manifest audit (above) PASSED,
|
||||||
> re-verified directly from the filesystem + git log, ignoring the executor's
|
> re-verified directly from the filesystem + git log, ignoring the executor's
|
||||||
> own per-step bookkeeping. "The audit wins"; a self-reported `completed` over
|
> own per-step bookkeeping. "The audit wins"; a self-reported `completed` over
|
||||||
> a drifting audit is OVERRIDDEN to `partial` (Phase 7.5, `:1221`).
|
> a drifting audit is OVERRIDDEN to `partial` (Phase 7.5).
|
||||||
> 2. **Explicit stop-signal** — a signal *distinct from the executor's
|
> 2. **Explicit stop-signal** — a signal *distinct from the executor's
|
||||||
> self-assessment* is satisfied: the plan's Verify command(s) **passed (exit
|
> 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
|
> 0)** / lint clean / an explicit **DONE token emitted AFTER the Phase 7.5
|
||||||
|
|
@ -2370,14 +2441,14 @@ Record in progress file:
|
||||||
> from `lib/verification/criteria-runner.mjs`, on the single-session path as
|
> from `lib/verification/criteria-runner.mjs`, on the single-session path as
|
||||||
> well as the multi-session one. `"failed"` or `"not-run"` OVERRIDES
|
> well as the multi-session one. `"failed"` or `"not-run"` OVERRIDES
|
||||||
> `completed` to `failed`, exactly as the audit-override does.
|
> `completed` to `failed`, exactly as the audit-override does.
|
||||||
> 3. **Counter liveness (deterministic, defeats "never decremented")** — the gate
|
> 3. **Counter liveness (checked by the executor against the audit's counts,
|
||||||
> reconciles the budget counter against the ground-truth counters the Phase 7.5
|
> defeats "never decremented")** — the gate reconciles the budget counter
|
||||||
> audit already derives:
|
> 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))`
|
> `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).
|
> (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
|
> A field left un-decremented (or tampered) fails this reconciliation and the
|
||||||
> result is OVERRIDDEN `completed → partial`, exactly as the audit-override
|
> result is OVERRIDDEN `completed → partial`, exactly as the audit-override
|
||||||
> already does (`:1221`). So the counter's liveness is auditable at the gate,
|
> already does (Phase 7.5). So the counter's liveness is auditable at the gate,
|
||||||
> not merely asserted in prose.
|
> not merely asserted in prose.
|
||||||
> 4. **End to end** — for a trekplan, Phase 7's `end_to_end == "verified"`.
|
> 4. **End to end** — for a trekplan, Phase 7's `end_to_end == "verified"`.
|
||||||
> `"not-verified"` OVERRIDES `completed → partial` with the reason
|
> `"not-verified"` OVERRIDES `completed → partial` with the reason
|
||||||
|
|
@ -2388,12 +2459,20 @@ Record in progress file:
|
||||||
> the files outside the plan. `"not-measured"` does not override, and it is
|
> the files outside the plan. `"not-measured"` does not override, and it is
|
||||||
> never reported as a pass.
|
> 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
|
> 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
|
> Phase 8: in the closing run, a closed lock or a declined merge turns
|
||||||
> `completed` into `partial`, as a declined gate always has.
|
> `completed` into `partial`, as a declined gate always has.
|
||||||
>
|
>
|
||||||
> Termination authority therefore rests on the deterministic audit + an
|
> Termination authority therefore rests on the audit and an objective
|
||||||
> objective stop-signal, never on the model's narrative. Native `/goal` (when
|
> stop-signal, never on the model's narrative. Native `/goal` (when
|
||||||
> capability-probed and wired) is an OPTIONAL accelerator only: transcript-only,
|
> 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.
|
> it cannot run the real check, so it can never be the sole gate.
|
||||||
|
|
||||||
|
|
@ -2525,7 +2604,7 @@ event, merge nothing, and their result is left as Phase 7.5 decided it
|
||||||
a summary:
|
a summary:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{review_path}"
|
node ${CLAUDE_PLUGIN_ROOT}/lib/review/verdict-gate.mjs --json "{review_path}" --repo .
|
||||||
```
|
```
|
||||||
|
|
||||||
`{review_path}` is `review.path` from Phase 7.2. No review (Phase 7.2 did not
|
`{review_path}` is `review.path` from Phase 7.2. No review (Phase 7.2 did not
|
||||||
|
|
@ -2538,13 +2617,23 @@ exit 2 without the call.
|
||||||
| 1 | BLOCK | closed |
|
| 1 | BLOCK | closed |
|
||||||
| 2 | not measured | closed: a review that could not decide is never green |
|
| 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
|
The merge runs only on exit 0 and a `completed` result. **Closed:** emit
|
||||||
`main-merge-declined` with the reason `review-block`, `review-not-measured` or
|
`main-merge-declined` with the reason `review-block`, `review-stale`,
|
||||||
`run-not-completed`. Nothing is finalized: a `completed` result becomes
|
`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
|
`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
|
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, or a run
|
BLOCKERs fixed through Phase 7.2's loop, a review that runs in full, a review
|
||||||
that completes.
|
of this commit, or a run that completes.
|
||||||
|
|
||||||
**2. Open: the merge, and the one question.** Find the run's branch and where
|
**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:
|
main is checked out, in a Bash call of its own:
|
||||||
|
|
@ -2648,7 +2737,7 @@ JSON
|
||||||
```
|
```
|
||||||
|
|
||||||
The reason is one of the literal words above (`review-block`,
|
The reason is one of the literal words above (`review-block`,
|
||||||
`review-not-measured`, `run-not-completed`, `no-main-branch`, `hold-for-review`,
|
`review-stale`, `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).
|
`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.
|
On decline, nothing is cleared: the merged-waves record is kept.
|
||||||
|
|
@ -2656,8 +2745,9 @@ On decline, nothing is cleared: the merged-waves record is kept.
|
||||||
**Recovery surface:** on the single-session path, if declined,
|
**Recovery surface:** on the single-session path, if declined,
|
||||||
`--resume re-enters at the gate` — re-running
|
`--resume re-enters at the gate` — re-running
|
||||||
`/trekexecute --resume --project <dir>` skips the completed steps and returns
|
`/trekexecute --resume --project <dir>` skips the completed steps and returns
|
||||||
to the main-merge gate: the lock reads `review.md` again (a review fixed or
|
to the main-merge gate: the lock reads the review again (a review fixed or re-run
|
||||||
re-run in between counts), and when it opens, the guard asks again. On the
|
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
|
||||||
multi-session wave path,
|
multi-session wave path,
|
||||||
re-run the same `/trekexecute` command instead, not `--resume` (Phase 2.5 runs
|
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
|
a `--resume` as a single session): the waves are already merged on the current
|
||||||
|
|
@ -2698,7 +2788,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
|
contract — see `docs/HANDOVER-CONTRACTS.md` § Handover 7 Lifecycle) in the
|
||||||
project directory. The frontmatter MUST contain `produced_by: trekexecute`
|
project directory. The frontmatter MUST contain `produced_by: trekexecute`
|
||||||
and `produced_at: <ISO-8601>` so `/trekcontinue` Phase 1.5 can detect
|
and `produced_at: <ISO-8601>` so `/trekcontinue` Phase 1.5 can detect
|
||||||
producer drift between project-dir and plugin-root candidates. Use a single
|
producer drift between project-dir and repo-root candidates. Use a single
|
||||||
ESM inline block so state-file + prompt-file writes succeed or fail together:
|
ESM inline block so state-file + prompt-file writes succeed or fail together:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -2730,6 +2820,12 @@ 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
|
Phase 2.3 (validate exit) and Phase 5 (dry-run) intentionally do not write
|
||||||
— neither path is resumable.
|
— 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
|
## Ultraexecute Local Complete
|
||||||
|
|
||||||
|
|
@ -2738,6 +2834,7 @@ Phase 2.3 (validate exit) and Phase 5 (dry-run) intentionally do not write
|
||||||
**Mode:** {execute | resume | step N}
|
**Mode:** {execute | resume | step N}
|
||||||
**Result:** {COMPLETED | FAILED at step N | STOPPED (escalation) | PARTIAL (N/total passed)}
|
**Result:** {COMPLETED | FAILED at step N | STOPPED (escalation) | PARTIAL (N/total passed)}
|
||||||
**End to end:** {verified | not verified end to end}
|
**End to end:** {verified | not verified end to end}
|
||||||
|
**Seen with `run`:** {yes | no — {reason}}
|
||||||
|
|
||||||
### Step Results
|
### Step Results
|
||||||
|
|
||||||
|
|
@ -2863,6 +2960,7 @@ To continue (multi-session waves): re-run the same /trekexecute command (not --r
|
||||||
"legacy_plan": false,
|
"legacy_plan": false,
|
||||||
"progress_file": "{path}",
|
"progress_file": "{path}",
|
||||||
"end_to_end": "{verified | not-verified | n/a}",
|
"end_to_end": "{verified | not-verified | n/a}",
|
||||||
|
"run_seen": "{yes | no — reason}",
|
||||||
"steps_without_red_proof": 0,
|
"steps_without_red_proof": 0,
|
||||||
"stop_class": "{none | 1 | 2 | 3 | 4}",
|
"stop_class": "{none | 1 | 2 | 3 | 4}",
|
||||||
"decisions": 0,
|
"decisions": 0,
|
||||||
|
|
@ -2930,8 +3028,8 @@ Resolution order (per `lib/profiles/resolver.mjs`):
|
||||||
3. Inherited from `plan.md` frontmatter `profile:` field (source: `inheritance`)
|
3. Inherited from `plan.md` frontmatter `profile:` field (source: `inheritance`)
|
||||||
4. `premium` default for v4.0-style plans without `profile:` (source: `default`)
|
4. `premium` default for v4.0-style plans without `profile:` (source: `default`)
|
||||||
|
|
||||||
The selected profile drives `phase_models.execute` (model for execution
|
The selected profile goes to the resolver. It changes no model here: the step helper and the
|
||||||
orchestrator) and `parallel_agents` for wave-parallel sessions.
|
controller run opus (Composition rule below), and nothing in this command reads `parallel_agents`.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
```
|
```
|
||||||
|
|
@ -2939,9 +3037,6 @@ Examples:
|
||||||
VOYAGE_PROFILE=balanced /trekexecute --project ...
|
VOYAGE_PROFILE=balanced /trekexecute --project ...
|
||||||
```
|
```
|
||||||
|
|
||||||
Stats records emit `profile`, `phase_models`, and `profile_source` per
|
|
||||||
Phase 9 record.
|
|
||||||
|
|
||||||
## Composition rule (v5.1)
|
## Composition rule (v5.1)
|
||||||
|
|
||||||
Independent of the profile system. When `brief.md` carries
|
Independent of the profile system. When `brief.md` carries
|
||||||
|
|
@ -2955,7 +3050,7 @@ model_for_phase = brief.phase_signals[<phase>]?.model ?? profile.phase_models[
|
||||||
|
|
||||||
The brief signal wins per-phase when present; the profile fills any
|
The brief signal wins per-phase when present; the profile fills any
|
||||||
gaps. Both fields are mechanically resolved by the single composed CLI,
|
gaps. Both fields are mechanically resolved by the single composed CLI,
|
||||||
invoked in Phase 2.4 alongside the sequencing-gate brief-validator call:
|
invoked in Phase 1 alongside the sequencing-gate brief-validator call:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# v5.9 — composed phase-model resolution (brief > profile > default) for the
|
# v5.9 — composed phase-model resolution (brief > profile > default) for the
|
||||||
|
|
@ -2967,21 +3062,18 @@ node ${CLAUDE_PLUGIN_ROOT}/lib/profiles/resolver.mjs --resolve-phase-model --pha
|
||||||
```
|
```
|
||||||
|
|
||||||
`phase_signal_result.effort` (absent = `standard`) is consumed when picking the execution
|
`phase_signal_result.effort` (absent = `standard`) is consumed when picking the execution
|
||||||
strategy (gates auto-escalation, parallel-wave choice — see High-effort
|
strategy (the parallel-wave choice, Phase 2.5). The resolver does NOT control the orchestrator's own
|
||||||
behavior below). The resolver does NOT control the orchestrator's own
|
|
||||||
model — that is fixed at invocation time (command frontmatter omits
|
model — that is fixed at invocation time (command frontmatter omits
|
||||||
`model:`, so it follows the session model) and cannot be switched mid-turn.
|
`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
|
`/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
|
(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
|
controller's `model: "opus"` — so `phase_signal_result.model` still has no
|
||||||
spawn site here; it is returned for cross-command uniformity and stats.
|
spawn site here; it is returned for cross-command uniformity; no stats record carries it.
|
||||||
|
|
||||||
For `/trekexecute` specifically: `effort == 'low'` activates `--gates open`
|
For `/trekexecute` specifically: `effort == 'low'` runs the plan as one
|
||||||
+ sequential-only execution (no worktree-isolated parallel waves — runs
|
session, step after step (Phase 2.5). `effort == 'standard'` (or absent) →
|
||||||
all sessions in a single foreground loop). `effort == 'standard'` (or
|
no change (default execution strategy applies). `effort == 'high'`: see
|
||||||
absent) → no change (default execution strategy applies). `effort == 'high'`
|
`### High-effort behavior (v5.1.1)` below.
|
||||||
activates the high-effort behavior documented under `### High-effort
|
|
||||||
behavior (v5.1.1)` below.
|
|
||||||
|
|
||||||
### Sequencing gate surface
|
### Sequencing gate surface
|
||||||
|
|
||||||
|
|
@ -2995,32 +3087,9 @@ commands surface, don't re-enforce.
|
||||||
|
|
||||||
### High-effort behavior (v5.1.1)
|
### High-effort behavior (v5.1.1)
|
||||||
|
|
||||||
When `phase_signal_result.effort == 'high'` for the `execute` phase,
|
High effort changes nothing in `/trekexecute`: the step helper and the
|
||||||
set `gates_mode = 'closed'` automatically (equivalent to passing
|
controller already run opus, and every gate already runs. No `gates_mode` is
|
||||||
`--gates closed` on the command line). All autonomy boundaries become
|
set from the effort.
|
||||||
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
|
## Hard rules
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,12 +124,23 @@ Parse `$ARGUMENTS` for mode flags. Order of precedence:
|
||||||
7. **`--quick`** — set **mode = quick**. Skip agent swarm; use lightweight
|
7. **`--quick`** — set **mode = quick**. Skip agent swarm; use lightweight
|
||||||
Glob/Grep scan and go directly to planning + adversarial review.
|
Glob/Grep scan and go directly to planning + adversarial review.
|
||||||
|
|
||||||
8. **`--gates`** — autonomy control. When present, set `gates_mode = true`.
|
8. **`--gates`** — autonomy control. `--gates` takes the next token as its
|
||||||
Pause for operator confirmation after Phase 5 (exploration), Phase 7
|
value only when it is `true`, `false`, `closed` or `open` (strip both);
|
||||||
(synthesis), and Phase 9 (adversarial review). Default `gates_mode =
|
any other next token is not its value (strip only the flag). Run the shim
|
||||||
false` lets phases flow continuously. The flag is consumed by the
|
once to map the value, bare when there is no value:
|
||||||
autonomy-gate state machine via the CLI shim:
|
|
||||||
`node ${CLAUDE_PLUGIN_ROOT}/lib/util/autonomy-gate.mjs --state X --event Y --gates {true|false}`.
|
```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.
|
||||||
|
|
||||||
9. **`--min-brief-version <ver>`** — (optional) version floor. Set
|
9. **`--min-brief-version <ver>`** — (optional) version floor. Set
|
||||||
**min_brief_version = {ver}** (e.g. `2.2`). Forwarded to the brief-validator
|
**min_brief_version = {ver}** (e.g. `2.2`). Forwarded to the brief-validator
|
||||||
|
|
@ -314,6 +325,10 @@ Determine the output directory from the plan slug:
|
||||||
|
|
||||||
Launch the **session-decomposer** agent:
|
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}
|
Plan file: {plan path}
|
||||||
Plugin root: ${CLAUDE_PLUGIN_ROOT}
|
Plugin root: ${CLAUDE_PLUGIN_ROOT}
|
||||||
|
|
@ -412,7 +427,7 @@ Then continue to the next phase inline.
|
||||||
|
|
||||||
## Phase 4 — Codebase sizing
|
## Phase 4 — Codebase sizing
|
||||||
|
|
||||||
Determine codebase scale to calibrate agent turns (not agent count).
|
Determine codebase scale to decide whether convention-scanner runs.
|
||||||
|
|
||||||
Run via Bash:
|
Run via Bash:
|
||||||
```
|
```
|
||||||
|
|
@ -444,11 +459,20 @@ 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
|
pass, or a brief from another producer) or 2 (could not run): review it as
|
||||||
below (operator decision 2026-10-08).
|
below (operator decision 2026-10-08).
|
||||||
|
|
||||||
Launch the **brief-reviewer** agent:
|
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.
|
||||||
Prompt: "Review this task brief for quality: {brief_path}. Check completeness,
|
Prompt: "Review this task brief for quality: {brief_path}. Check completeness,
|
||||||
consistency, testability, scope clarity, and research-plan validity.
|
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)."
|
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:
|
Handle the verdict:
|
||||||
- **PROCEED** — continue to Phase 5.
|
- **PROCEED** — continue to Phase 5.
|
||||||
- **PROCEED_WITH_RISKS** — continue, carry flagged risks as `[ASSUMPTION]` in the plan.
|
- **PROCEED_WITH_RISKS** — continue, carry flagged risks as `[ASSUMPTION]` in the plan.
|
||||||
|
|
@ -489,8 +513,7 @@ message). Use the specialized agents from the `agents/` directory.
|
||||||
> 2026-08-17: named 0/5 returned, unnamed 3/3. Mechanism, denominators, and the
|
> 2026-08-17: named 0/5 returned, unnamed 3/3. Mechanism, denominators, and the
|
||||||
> on-disk recovery path: `docs/agent-return-channel-defect.md`.
|
> on-disk recovery path: `docs/agent-return-channel-defect.md`.
|
||||||
|
|
||||||
**All agents run for all codebase sizes.** Scale `maxTurns` by size (small: halved,
|
**All agents run for all codebase sizes.**
|
||||||
medium: default, large: default) instead of dropping agents.
|
|
||||||
|
|
||||||
| Agent | Small | Medium | Large | Purpose |
|
| Agent | Small | Medium | Large | Purpose |
|
||||||
|-------|-------|--------|-------|---------|
|
|-------|-------|--------|-------|---------|
|
||||||
|
|
@ -507,6 +530,10 @@ research-scout's web search is not a local read; the line above bounds its local
|
||||||
|
|
||||||
### Always launch (all codebase sizes):
|
### 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.
|
**architecture-mapper** — full codebase structure, tech stack, patterns, anti-patterns.
|
||||||
Prompt: "Analyze the architecture of this codebase. The task being planned is: {task}.
|
Prompt: "Analyze the architecture of this codebase. The task being planned is: {task}.
|
||||||
Brief file: {brief_path} — read it first.
|
Brief file: {brief_path} — read it first.
|
||||||
|
|
@ -544,7 +571,7 @@ Read local files only inside the repo under exploration, plus paths this prompt
|
||||||
|
|
||||||
### Launch for medium+ codebases (50+ files):
|
### Launch for medium+ codebases (50+ files):
|
||||||
|
|
||||||
**Convention Scanner** — use the `convention-scanner` plugin agent (model: "opus")
|
**Convention Scanner** — use the `convention-scanner` plugin agent (model: phase_signal_result.model, the agent's frontmatter as the fallback)
|
||||||
for medium+ codebases only.
|
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."
|
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."
|
||||||
|
|
||||||
|
|
@ -562,6 +589,9 @@ topics have corresponding research files, skip research-scout entirely.
|
||||||
|
|
||||||
If yes (and not covered by attached briefs): launch **research-scout** in
|
If yes (and not covered by attached briefs): launch **research-scout** in
|
||||||
parallel with the other agents.
|
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}.
|
Prompt: "Research the following technologies for this task: {task}.
|
||||||
Specific questions: {list specific questions about the technology}.
|
Specific questions: {list specific questions about the technology}.
|
||||||
Technologies to research: {list}. Brief file: {brief_path} — read it first.
|
Technologies to research: {list}. Brief file: {brief_path} — read it first.
|
||||||
|
|
@ -582,7 +612,8 @@ Common reasons for deep-dives:
|
||||||
- A test pattern was identified but the test infrastructure needs more detail
|
- A test pattern was identified but the test infrastructure needs more detail
|
||||||
- A risk was flagged but the actual impact needs verification
|
- A risk was flagged but the actual impact needs verification
|
||||||
|
|
||||||
For each significant gap, spawn a targeted deep-dive agent (model: "opus",
|
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,
|
||||||
subagent_type: "Explore") with a narrow, specific brief. Each deep-dive prompt
|
subagent_type: "Explore") with a narrow, specific brief. Each deep-dive prompt
|
||||||
carries these two lines:
|
carries these two lines:
|
||||||
Brief file: {brief_path} — read it first.
|
Brief file: {brief_path} — read it first.
|
||||||
|
|
@ -709,7 +740,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
|
> **Two step rules at every plan_version** (no version bump; a plan without
|
||||||
> the field is unchanged): the optional `Regression:` field (K10) holds ONE
|
> the field is unchanged): the optional `Regression:` field (K10) holds ONE
|
||||||
> backticked command the criteria runner allows, with no pipe and no `&&` —
|
> backticked command the criteria runner accepts (`voyage:writing-criteria`) —
|
||||||
> usually `npm test`, the suite the step must not break. `Verify:` stays the
|
> 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
|
> 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
|
> executor runs green before the checkpoint, so a step whose red test is a
|
||||||
|
|
@ -787,17 +818,17 @@ Write the plan following the template structure. The plan MUST include:
|
||||||
(`PLAN_STEP_TESTS_ONLY`).
|
(`PLAN_STEP_TESTS_ONLY`).
|
||||||
|
|
||||||
**The "run the thing" step.** At least one step carries
|
**The "run the thing" step.** At least one step carries
|
||||||
`End-to-end: \`<command>\` → expected: <what the user sees>`: the product run
|
`End-to-end: \`<command>\` → expected: <what the user sees>`: the product run the way a
|
||||||
the way a user runs it (the CLI, the server and a request, the app; for iOS,
|
user runs it (the CLI, the server and a request, the app; for iOS, the simulator). Without
|
||||||
the simulator). Without it the result is "not verified end to end", never
|
it the result is "not verified end to end", never green. To see and drive the app, use
|
||||||
green. The command passes the criteria runner's allowlist — the product's
|
Claude Code's built-in `run` skill; the verdict is still the `End-to-end:` command, because
|
||||||
own binary does not, so the run is wrapped in a script:
|
`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: \`bash tests/e2e.sh\``. The same command is also listed under
|
`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
|
`## Verification`: Phase 7 of `/trekexecute` runs that section, and a passed criterion that
|
||||||
criterion that runs the step's `End-to-end:` command is what verifies the
|
runs the step's `End-to-end:` command is what verifies the run end to end. `End-to-end:`
|
||||||
run end to end. `End-to-end:` rides on the last step that builds behaviour,
|
rides on the last step that builds behaviour, with `tests/e2e.sh` in that step's `Files:`:
|
||||||
with `tests/e2e.sh` in that step's `Files:`: a step of its own that only adds
|
a step of its own that only adds the script is a step of only tests, and it can never be proven red.
|
||||||
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
|
10. **Execution Strategy** — For plans with > 5 steps: group steps into sessions
|
||||||
(3–5 steps each), organize sessions into waves (parallel where independent),
|
(3–5 steps each), organize sessions into waves (parallel where independent),
|
||||||
specify scope fences per session. Omit for plans with ≤ 5 steps.
|
specify scope fences per session. Omit for plans with ≤ 5 steps.
|
||||||
|
|
@ -824,24 +855,13 @@ Write the plan following the template structure. The plan MUST include:
|
||||||
npm test
|
npm test
|
||||||
node --test tests/lib/x.test.mjs
|
node --test tests/lib/x.test.mjs
|
||||||
```
|
```
|
||||||
The command must also be one the criteria runner is allowed to run: a test
|
Each command is written by the `voyage:writing-criteria` skill (use it by
|
||||||
runner (`npm test`, `npm run <script>`, `node --test <file>`, `vitest`,
|
name before you write this section and the steps' `Verify:`, `Regression:`
|
||||||
`jest`, `pytest`, `python -m pytest`, `uv run pytest`, `cargo test`,
|
and `End-to-end:` lines): one command the criteria runner accepts, in plain
|
||||||
`go test`, `make test`), `bash <script under tests/>` (also
|
words, a script under `tests/` (`bash tests/<script>.sh`) for anything
|
||||||
`/bin/bash <script under tests/>`, to pin the system shell), or a read-only
|
more, and a command that can go red. Anything the runner refuses is
|
||||||
`git` subcommand (`status`, `log`, `diff`, `show`, `ls-files` — not `git
|
reported NOT RUN, never executed and never failed, and an unrunnable plan
|
||||||
grep`) — with no pipe, redirect or `&&`. It runs with no shell: its words
|
criterion stops `/trekexecute` Phase 7.
|
||||||
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.
|
9. **Estimated Scope** — File counts and complexity rating.
|
||||||
|
|
||||||
### Quality standards
|
### Quality standards
|
||||||
|
|
@ -962,11 +982,24 @@ 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
|
single assistant message turn** (same pattern as Phase 5 exploration). They
|
||||||
have zero data dependencies; serializing them wastes 30–60 seconds per run.
|
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.
|
**plan-critic** — adversarial review of the plan.
|
||||||
Prompt: "Review this implementation plan for the task: {task}.
|
Prompt: "Review this implementation plan for the task: {task}.
|
||||||
Plan file: {plan path}. Read it and find every problem — missing steps,
|
Plan file: {plan path}. Read it and find every problem — missing steps,
|
||||||
wrong ordering, fragile assumptions, missing error handling, scope creep,
|
wrong ordering, fragile assumptions, missing error handling, scope creep,
|
||||||
underspecified steps. Rate each finding as blocker, major, or minor.
|
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
|
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
|
(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.
|
dedup helper. You have no Write tool — return the block inline, do not write a file.
|
||||||
|
|
@ -980,7 +1013,10 @@ Task: {task}. Brief file: {brief_path}. Plan file: {plan path}.
|
||||||
Find scope creep (plan does more than the brief requires) and scope gaps
|
Find scope creep (plan does more than the brief requires) and scope gaps
|
||||||
(plan misses brief requirements). Check that referenced files and functions
|
(plan misses brief requirements). Check that referenced files and functions
|
||||||
exist. Verify that every Success Criterion in the brief is covered by the
|
exist. Verify that every Success Criterion in the brief is covered by the
|
||||||
plan's Verification section. End your response with the REQUIRED machine-readable
|
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
|
||||||
`json` findings block (schema in `agents/scope-guardian.md`). You have no Write
|
`json` findings block (schema in `agents/scope-guardian.md`). You have no Write
|
||||||
tool — return the block inline, do not write a file.
|
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)."
|
Read local files only inside the repo under exploration, plus paths this prompt gives you (the brief, the plan, and templates it names)."
|
||||||
|
|
@ -1120,13 +1156,13 @@ Present a summary to the user:
|
||||||
You can:
|
You can:
|
||||||
- Say which open minors to fix ("fix 1 and 3")
|
- Say which open minors to fix ("fix 1 and 3")
|
||||||
- Ask questions or request changes to refine the plan
|
- Ask questions or request changes to refine the plan
|
||||||
- Say **"execute"** to start implementing ← only when the gate exited 0
|
- Say **"execute"** for the `/trekexecute` line to run ← only when the gate exited 0
|
||||||
- Say **"save"** to keep the plan for later
|
- Say **"save"** to keep the plan for later
|
||||||
```
|
```
|
||||||
|
|
||||||
When the gate exited 1, replace the "execute" line with
|
When the gate exited 1, replace the "execute" line with
|
||||||
`Execution is blocked: {the gate's reasons}` and do not start implementing,
|
`Execution is blocked: {the gate's reasons}` and do not print the `/trekexecute`
|
||||||
whatever is said next, until the gate exits 0.
|
line, whatever is said next, until the gate exits 0.
|
||||||
|
|
||||||
**What counts as approval.** "Execute", "go" or "start" (or the plan-mode
|
**What counts as approval.** "Execute", "go" or "start" (or the plan-mode
|
||||||
approval below) approves the plan. A hedged reply — "sounds good", "looks
|
approval below) approves the plan. A hedged reply — "sounds good", "looks
|
||||||
|
|
@ -1165,8 +1201,11 @@ plan-approval prompt:
|
||||||
plan back.
|
plan back.
|
||||||
3. **Approved:** the session leaves plan mode. Copy the plan file to the plan
|
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
|
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
|
exit 0 again, which also proves the copy is the reviewed text. Then go
|
||||||
continue with the operator's choice (Phase 11).
|
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.
|
||||||
4. **"No, keep planning":** revise per the operator's words, run one Phase 9
|
4. **"No, keep planning":** revise per the operator's words, run one Phase 9
|
||||||
round, and present again from step 1.
|
round, and present again from step 1.
|
||||||
|
|
||||||
|
|
@ -1178,15 +1217,11 @@ plan mode's restrictions). Until an operator has run it, both paths stay.
|
||||||
|
|
||||||
### Build the operator-annotation HTML and print the link
|
### Build the operator-annotation HTML and print the link
|
||||||
|
|
||||||
After the plan summary, run `scripts/annotate.mjs` to produce a
|
After the plan summary, run `scripts/annotate.mjs` to build the page
|
||||||
self-contained HTML the operator opens in their browser. The HTML renders
|
where the operator writes their own notes on `plan.md`. The loop that
|
||||||
`plan.md` with line numbers, lets the operator click any line to attach
|
follows is the skill `voyage:annotating`: call it when the operator pastes
|
||||||
their own note (not Claude-generated suggestions — the operator drives
|
the notes back (a Question is answered, not applied; an approved plan that
|
||||||
every annotation), keeps a sidebar of all notes, persists state in
|
changes needs a new approval before `/trekexecute`, said before the edit).
|
||||||
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
|
```bash
|
||||||
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{plan_path}" 2>&1)
|
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{plan_path}" 2>&1)
|
||||||
|
|
@ -1210,9 +1245,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,
|
Click any line to add YOUR OWN note. The sidebar collects every note,
|
||||||
the "Copy Prompt" button gathers them into one structured prompt.
|
the "Copy Prompt" button gathers them into one structured prompt.
|
||||||
Paste that prompt back into this chat and Claude revises plan.md
|
Paste that prompt back into this chat: Claude answers each Question
|
||||||
from your notes. Annotations persist in your browser if you close
|
and revises plan.md from your Fix and Change notes. Annotations
|
||||||
the tab and reopen the same file.
|
persist in your browser if you close the tab and reopen the same file.
|
||||||
────────────────────────────────────────────────────────────────────
|
────────────────────────────────────────────────────────────────────
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -1258,15 +1293,16 @@ Confirm the plan and brief file locations and exit.
|
||||||
|
|
||||||
### "execute" / "go" / "start"
|
### "execute" / "go" / "start"
|
||||||
|
|
||||||
Begin implementing the plan step by step in this session. Follow the plan exactly.
|
Do not implement in this session. Print the line the operator gives
|
||||||
Mark each step complete as you go.
|
`/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.
|
||||||
|
|
||||||
### "execute with team" / "team"
|
### "execute with team" / "team"
|
||||||
|
|
||||||
There is no team path. Tell the user that parallel team execution is not available
|
There is no team path. Print the same `/trekexecute` line, then run Phase 12
|
||||||
from `/trekplan`, then proceed exactly as for "execute" (sequential, in this
|
(`outcome: execute_team`); parallel work is `--decompose` followed by `/trekexecute`'s session orders.
|
||||||
session). Parallel implementation is `--decompose` followed by `/trekexecute`'s
|
|
||||||
multi-session waves.
|
|
||||||
|
|
||||||
## Phase 12 — Session tracking
|
## Phase 12 — Session tracking
|
||||||
|
|
||||||
|
|
@ -1327,9 +1363,6 @@ Examples:
|
||||||
VOYAGE_PROFILE=balanced /trekplan --project ...
|
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)
|
## Composition rule (v5.1)
|
||||||
|
|
||||||
Independent of the profile system. When `brief.md` carries
|
Independent of the profile system. When `brief.md` carries
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ Supported flags:
|
||||||
is `{model, source}`, plus
|
is `{model, source}`, plus
|
||||||
`effort` only when the brief's phase signal sets one (without it the
|
`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 runs at effort `standard`: no change). It is captured as
|
||||||
`phase_signal_result` and used at Agent-spawn sites in Phase 4 to inject
|
`phase_signal_result` and used at Agent-spawn sites in Phase 4 and Phase 5 to inject
|
||||||
the resolved model:
|
the resolved model:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -72,12 +72,23 @@ Supported flags:
|
||||||
node ${CLAUDE_PLUGIN_ROOT}/lib/profiles/resolver.mjs --resolve-phase-model --phase research --brief-path "{dir}/brief.md" [--profile {profile}] --json
|
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. When present, set `gates_mode = true`. The
|
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
|
||||||
research command will pause after each topic completes ("Topic N
|
research command will pause after each topic completes ("Topic N
|
||||||
complete. Proceed to topic N+1? (yes/no)"). Default `gates_mode = false`
|
complete. Proceed to topic N+1? (yes/no)"). Default `gates_mode = false`
|
||||||
means topics run continuously. The flag is consumed by the autonomy-gate
|
means topics run continuously.
|
||||||
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
|
7. `--min-brief-version <ver>` — (optional) version floor for an attached
|
||||||
`--project` brief. Set **min_brief_version = {ver}** (e.g. `2.2`). Forwarded
|
`--project` brief. Set **min_brief_version = {ver}** (e.g. `2.2`). Forwarded
|
||||||
|
|
@ -373,7 +384,8 @@ changes nothing (SC1). Keep the native-swarm anchors intact ("in parallel",
|
||||||
5. **On a real report:** keep `effective_engine = deep-research`, log
|
5. **On a real report:** keep `effective_engine = deep-research`, log
|
||||||
`Engine: deep-research (active)`, and carry the report into Phase 6 triangulation
|
`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
|
as the external-findings input (adapted in Phase 7 — see the Deep-research engine
|
||||||
adapter below).
|
adapter below); then run wave 2 (`contrarian-researcher`, see Launch rules)
|
||||||
|
from the report's leading answer.
|
||||||
|
|
||||||
### External agents (scope = both or external)
|
### External agents (scope = both or external)
|
||||||
|
|
||||||
|
|
@ -402,7 +414,22 @@ ticket IDs) already removed: the agents search with the words they are given.
|
||||||
|
|
||||||
### Launch rules
|
### Launch rules
|
||||||
|
|
||||||
- Launch ALL selected agents **in parallel** in a single message
|
- 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.
|
||||||
- Inject the resolved model at every spawn: `phase_signal_result.model` (brief
|
- Inject the resolved model at every spawn: `phase_signal_result.model` (brief
|
||||||
signal > profile), with the agent's frontmatter `model:` as the fallback — see
|
signal > profile), with the agent's frontmatter `model:` as the fallback — see
|
||||||
Hard rules → Cost. The orchestrator itself follows the session model.
|
Hard rules → Cost. The orchestrator itself follows the session model.
|
||||||
|
|
@ -418,8 +445,6 @@ 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,
|
Measured 2026-08-17: named 0/5 returned, unnamed 3/3. Mechanism,
|
||||||
denominators, and the on-disk recovery path:
|
denominators, and the on-disk recovery path:
|
||||||
`docs/agent-return-channel-defect.md`.
|
`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)
|
- convention-scanner: medium+ codebases only (50+ files)
|
||||||
|
|
||||||
## Phase 4.5 — Dimension discovery
|
## Phase 4.5 — Dimension discovery
|
||||||
|
|
@ -493,7 +518,9 @@ Review all agent results. Identify knowledge gaps — dimensions where findings
|
||||||
are thin, contradictory, or missing (**under-illuminated dimensions**).
|
are thin, contradictory, or missing (**under-illuminated dimensions**).
|
||||||
|
|
||||||
**Standard and low effort — unchanged single pass.** For each significant gap,
|
**Standard and low effort — unchanged single pass.** For each significant gap,
|
||||||
launch a targeted follow-up agent (model: "opus") with a narrow, specific
|
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
|
||||||
brief; a follow-up that searches the web names the `researching-sources` skill
|
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
|
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.
|
sufficient — no follow-ups needed." Then go to Phase 6.
|
||||||
|
|
@ -621,6 +648,10 @@ 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
|
rewrite can clear it, so treat it as a hard stop and say so, rather than
|
||||||
rewriting a query that was never the problem.
|
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
|
**Empty turns.** A turn that returns no findings, or findings without
|
||||||
citations, is marked `empty`. An empty turn is counted in `empty_turns` and
|
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
|
does NOT re-target the same dimension — re-asking the same question of the
|
||||||
|
|
@ -731,7 +762,10 @@ raw report. Specifically:
|
||||||
- Reduce the report to ≥ 1 `### {Dimension} -- Confidence: {high|medium|low|contradictory}`
|
- Reduce the report to ≥ 1 `### {Dimension} -- Confidence: {high|medium|low|contradictory}`
|
||||||
entry, each carrying **External findings** bullets with per-claim source URLs.
|
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
|
Local findings still come from the local agents (Phase 4) and are merged in per
|
||||||
dimension as usual.
|
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.
|
||||||
- Emit a numeric `confidence ∈ [0,1]` in frontmatter and a 3-sentence
|
- Emit a numeric `confidence ∈ [0,1]` in frontmatter and a 3-sentence
|
||||||
`## Executive Summary` (answer, confidence, key caveat).
|
`## Executive Summary` (answer, confidence, key caveat).
|
||||||
- Populate `## Sources` from the report's citations.
|
- Populate `## Sources` from the report's citations.
|
||||||
|
|
@ -867,9 +901,7 @@ Examples:
|
||||||
VOYAGE_PROFILE=balanced /trekresearch
|
VOYAGE_PROFILE=balanced /trekresearch
|
||||||
```
|
```
|
||||||
|
|
||||||
Stats records emit `profile`, `phase_models`, `parallel_agents`,
|
Stats records emit `engine` so operators can audit which engine drove which session.
|
||||||
`external_research_enabled`, `profile_source`, and `engine` so operators can
|
|
||||||
audit which profile and engine drove which session.
|
|
||||||
|
|
||||||
## Composition rule (v5.1)
|
## Composition rule (v5.1)
|
||||||
|
|
||||||
|
|
@ -914,12 +946,11 @@ commands surface, don't re-enforce.
|
||||||
### High-effort behavior (v5.1.1)
|
### High-effort behavior (v5.1.1)
|
||||||
|
|
||||||
When `phase_signal_result.effort == 'high'` for the `research` phase,
|
When `phase_signal_result.effort == 'high'` for the `research` phase,
|
||||||
run the FULL swarm regardless of normal triggering rules: 5 local
|
run the FULL swarm regardless of normal selection rules: 5 local
|
||||||
agents + 4 external agents, AND force `contrarian-researcher` to
|
agents + 4 external agents, AND force `contrarian-researcher` to
|
||||||
always-on. Normally `contrarian-researcher` triggers conditionally when
|
always-on: in high-effort mode `contrarian-researcher` runs
|
||||||
a leading recommendation is emerging from initial agents; in
|
unconditionally, as wave 2 (see Launch rules), so the final brief
|
||||||
high-effort mode it runs unconditionally so the final brief always
|
always carries an adversarial counter-evidence pass.
|
||||||
carries an adversarial counter-evidence pass.
|
|
||||||
|
|
||||||
The former third-party second-opinion bridge pass is **unavailable,
|
The former third-party second-opinion bridge pass is **unavailable,
|
||||||
skipped** (dropped in v5.10.1 by operator directive). High effort no
|
skipped** (dropped in v5.10.1 by operator directive). High effort no
|
||||||
|
|
@ -934,7 +965,9 @@ turns per under-illuminated dimension, budgeted by
|
||||||
`--local`, `external_research_enabled: false`) overrides the effort
|
`--local`, `external_research_enabled: false`) overrides the effort
|
||||||
signal whenever the external phase does not run at all.
|
signal whenever the external phase does not run at all.
|
||||||
|
|
||||||
Standard effort (or absent): use the existing conditional triggers.
|
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).
|
||||||
Low effort: inline research only, no agent swarm (existing
|
Low effort: inline research only, no agent swarm (existing
|
||||||
`--quick`-equivalent code-path).
|
`--quick`-equivalent code-path).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,13 @@ command executes inline.
|
||||||
## Phase 1 — Parse mode and validate input
|
## Phase 1 — Parse mode and validate input
|
||||||
|
|
||||||
Parse the arguments with the shared arg-parser. Run it first, exactly like
|
Parse the arguments with the shared arg-parser. Run it first, exactly like
|
||||||
this, before anything else:
|
this, before anything else (the arguments reach the parser as the one line
|
||||||
|
inside the quoted heredoc, on stdin, never as shell words):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview -- $ARGUMENTS
|
node ${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs --command trekreview --stdin <<'VOYAGE_ARGS_EOF_7F3C9E'
|
||||||
|
$ARGUMENTS
|
||||||
|
VOYAGE_ARGS_EOF_7F3C9E
|
||||||
```
|
```
|
||||||
|
|
||||||
It prints the parse as JSON on stdout. It also checks the required flag
|
It prints the parse as JSON on stdout. It also checks the required flag
|
||||||
|
|
@ -62,7 +65,7 @@ FLAG_SCHEMA `trekreview` entry):
|
||||||
|------|------|---------|
|
|------|------|---------|
|
||||||
| `--project <dir>` | valued | Required. Path to trekplan project folder containing `brief.md`. |
|
| `--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`. |
|
| `--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. |
|
| `--quick` | boolean | Skip the brief-conformance pass; run only the code-correctness reviewer; skip the coordinator's reasonableness filter except the brief-conflict rule. |
|
||||||
| `--validate` | boolean | Schema-only check on existing `{project_dir}/review.md`. No LLM calls. |
|
| `--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. |
|
| `--dry-run` | boolean | Print the discovered scope and triage map. Skip writes. |
|
||||||
| `--fg` | boolean | No-op alias (foreground is default). |
|
| `--fg` | boolean | No-op alias (foreground is default). |
|
||||||
|
|
@ -184,8 +187,8 @@ every file from Phase 3 into a treatment bucket:
|
||||||
| Treatment | When |
|
| 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`). |
|
| `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` | Matches `auth/**`, `crypto/**`, `**/security/**`, `hooks/**`. |
|
| `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` | Default treatment for everything else. |
|
| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. |
|
||||||
|
|
||||||
Hard refuse-with-suggestion gates — use `AskUserQuestion`:
|
Hard refuse-with-suggestion gates — use `AskUserQuestion`:
|
||||||
|
|
||||||
|
|
@ -381,6 +384,15 @@ message, multiple tool calls.
|
||||||
|
|
||||||
Reviewers run independently. Do NOT pre-feed findings between them.
|
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 |
|
| 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. |
|
| `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. |
|
||||||
|
|
@ -478,7 +490,11 @@ forbids `ALLOW` (`lib/review/coordinator-contract.mjs`, `missing_reviewers`).
|
||||||
Launch `review-coordinator` (Agent tool) with the merged findings array
|
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
|
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
|
metadata, SHA range, the expected reviewer set (engines included), and each
|
||||||
not-run engine with its reason.
|
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.
|
||||||
|
|
||||||
**Brief choices.** Next to the brief metadata, pass the brief's choices
|
**Brief choices.** Next to the brief metadata, pass the brief's choices
|
||||||
verbatim: extract the `## Non-Goals`, `## Constraints` and `## Preferences`
|
verbatim: extract the `## Non-Goals`, `## Constraints` and `## Preferences`
|
||||||
|
|
@ -497,8 +513,15 @@ The coordinator runs the 4-pass process documented in
|
||||||
Succinctness never removes a finding: only MINOR/SUGGESTION text is
|
Succinctness never removes a finding: only MINOR/SUGGESTION text is
|
||||||
trimmed, and every trim is counted. A long BLOCKER or MAJOR keeps every
|
trimmed, and every trim is counted. A long BLOCKER or MAJOR keeps every
|
||||||
character.
|
character.
|
||||||
3. **Cloudflare reasonableness** — remove speculative or catalogue-violating
|
3. **Cloudflare reasonableness** (skipped in `quick` mode) — drop a finding
|
||||||
findings (skipped in `quick` mode).
|
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.
|
||||||
4. **Verdict** — BLOCK / WARN / ALLOW per the threshold table.
|
4. **Verdict** — BLOCK / WARN / ALLOW per the threshold table.
|
||||||
|
|
||||||
**Fail-closed.** Every removal in Pass 2 and Pass 3 is either
|
**Fail-closed.** Every removal in Pass 2 and Pass 3 is either
|
||||||
|
|
@ -546,11 +569,8 @@ 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`);
|
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).
|
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), every engine finding the
|
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.
|
||||||
coordinator did not return at its exact `(file, line, rule_key)` is put back at its own
|
So the workflow path is stricter than the prose path.
|
||||||
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):
|
Contract (verified in S10 part B — follow exactly):
|
||||||
- **Pass `args` as a JSON object.** The script defensively re-parses a JSON *string*, but
|
- **Pass `args` as a JSON object.** The script defensively re-parses a JSON *string*, but
|
||||||
|
|
@ -682,13 +702,11 @@ the main workflow, but it is reported, not skipped silently.
|
||||||
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{review_path}" 2>&1)
|
ANNOT_HTML=$(node ${CLAUDE_PLUGIN_ROOT}/scripts/annotate.mjs "{review_path}" 2>&1)
|
||||||
```
|
```
|
||||||
|
|
||||||
`stdout` is the absolute path to the `.html` on success. The HTML renders
|
`stdout` is the absolute path to the `.html` on success: the page where the
|
||||||
`review.md` with line numbers, lets the operator click any line to attach
|
operator writes their own notes on `review.md`. The loop that follows is the
|
||||||
their own note (not Claude-generated suggestions — the operator drives
|
skill `voyage:annotating`: call it when the operator pastes the notes back.
|
||||||
every annotation), keeps a sidebar of all notes, persists state in
|
If `annotate.mjs` exits non-zero, surface a one-line warning and continue —
|
||||||
localStorage, and exposes a "Copy Prompt" button. If `annotate.mjs`
|
the annotation HTML is a convenience, not a gate.
|
||||||
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`)
|
## Phase 8.5 — Validate-only mode (`--validate`)
|
||||||
|
|
||||||
|
|
@ -733,8 +751,8 @@ carries one line in the format **mistake · fix · how to check**:
|
||||||
|
|
||||||
**The operator approves every line.** For each proposal, use
|
**The operator approves every line.** For each proposal, use
|
||||||
`AskUserQuestion` (up to 4 proposals per call), in plain language, showing
|
`AskUserQuestion` (up to 4 proposals per call), in plain language, showing
|
||||||
the line and its two pieces of evidence. Options: **"Skriv linja inn"**
|
the line and its two pieces of evidence. Options: **"Add the line"**
|
||||||
(recommended: the class has recurred) and **"Ikke nå"**; the operator may
|
(recommended: the class has recurred) and **"Not now"**; the operator may
|
||||||
answer with an edited line through "Other". Never write a line the operator
|
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
|
did not approve, and never treat "sounds good" or "do as you like" as a yes
|
||||||
to a line it was not shown.
|
to a line it was not shown.
|
||||||
|
|
@ -808,9 +826,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,
|
Click any line to add YOUR OWN note. The sidebar collects every note,
|
||||||
the "Copy Prompt" button gathers them into one structured prompt.
|
the "Copy Prompt" button gathers them into one structured prompt.
|
||||||
Paste that prompt back into this chat and Claude revises review.md
|
Paste that prompt back into this chat: Claude answers each Question
|
||||||
from your notes. Annotations persist in your browser if you close
|
and revises review.md from your Fix and Change notes. Annotations
|
||||||
the tab and reopen the same file.
|
persist in your browser if you close the tab and reopen the same file.
|
||||||
────────────────────────────────────────────────────────────────────
|
────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
You can also:
|
You can also:
|
||||||
|
|
@ -845,8 +863,6 @@ Examples:
|
||||||
VOYAGE_PROFILE=premium /trekreview --project ...
|
VOYAGE_PROFILE=premium /trekreview --project ...
|
||||||
```
|
```
|
||||||
|
|
||||||
Stats records emit `profile` and `profile_source`.
|
|
||||||
|
|
||||||
## Composition rule (v5.1)
|
## Composition rule (v5.1)
|
||||||
|
|
||||||
Independent of the profile system. When `brief.md` carries
|
Independent of the profile system. When `brief.md` carries
|
||||||
|
|
@ -890,8 +906,8 @@ readable.
|
||||||
### High-effort behavior (v5.1.1)
|
### High-effort behavior (v5.1.1)
|
||||||
|
|
||||||
When `phase_signal_result.effort == 'high'` for the `review` phase,
|
When `phase_signal_result.effort == 'high'` for the `review` phase,
|
||||||
skip Pass 3 (Cloudflare reasonableness filter) in
|
skip Pass 3 (Cloudflare reasonableness filter) in `agents/review-coordinator.md`, except the brief-conflict rule, which applies in every mode.
|
||||||
`agents/review-coordinator.md`. Passes 1, 2, and 4 still run.
|
Passes 1, 2, and 4 still run.
|
||||||
Rationale: high-effort review trusts the operator to weigh borderline
|
Rationale: high-effort review trusts the operator to weigh borderline
|
||||||
findings rather than have the coordinator drop them. To prevent
|
findings rather than have the coordinator drop them. To prevent
|
||||||
unknown `rule_key` values from polluting downstream remediation plans
|
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.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. |
|
| **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) |
|
| 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) → 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`). |
|
| 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`). |
|
||||||
|
|
||||||
**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.
|
**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).
|
**Producer:** `/trekresearch` Phase 7 (synthesis + brief writer).
|
||||||
|
|
||||||
**Consumer:** `/trekplan` Phase 1 (project-dir auto-discovery) + `planning-orchestrator` (consumes findings as context).
|
**Consumer:** `/trekplan` Phase 1 (project-dir auto-discovery) + `/trekplan` Phase 3 and Phase 7 (consumes findings as context).
|
||||||
|
|
||||||
**Path conventions:**
|
**Path conventions:**
|
||||||
- Project-dir mode: `.claude/projects/{YYYY-MM-DD}-{slug}/research/{NN}-{topic-slug}.md` (sorted by filename).
|
- 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).
|
**Producer:** external opt-in architect plugin (no longer publicly distributed).
|
||||||
|
|
||||||
**Consumer:** `/trekplan` Phase 1 (architecture-discovery) + `planning-orchestrator` Phase 7 (cross-reference architecture-note as priors during synthesis).
|
**Consumer:** `/trekplan` Phase 1 (architecture-discovery) + `/trekplan` Phase 7 (cross-reference architecture-note as priors during synthesis).
|
||||||
|
|
||||||
**Path conventions:**
|
**Path conventions:**
|
||||||
- Canonical: `{project_dir}/architecture/overview.md`
|
- 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
|
## Handover 4 — `plan.md` → execute
|
||||||
|
|
||||||
**Producer:** `planning-orchestrator` Phase 5 (plan synthesis) + Phase 5.5 (schema self-check via `plan-validator --strict`).
|
**Producer:** `/trekplan` Phase 8 (plan synthesis, then the schema self-check via `plan-validator --strict`).
|
||||||
|
|
||||||
**Consumer:** `/trekexecute` Phase 2 (plan parsing) + `--validate` mode.
|
**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:**
|
**Validation strategy:**
|
||||||
|
|
||||||
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`.
|
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`.
|
||||||
|
|
||||||
| Code | Meaning | Recovery |
|
| Code | Meaning | Recovery |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
|
@ -358,6 +358,7 @@ 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 |
|
| `session_end_sha` | string | optional | git sha at execute end |
|
||||||
| `steps` | object | yes | Map of step number → step record |
|
| `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)) |
|
| `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) |
|
| `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:**
|
**Per-step record:**
|
||||||
|
|
@ -368,7 +369,7 @@ Rule B is stated by the reviewers and recorded by the gate from round 1 (`lowere
|
||||||
| `attempts` | number | 1..N |
|
| `attempts` | number | 1..N |
|
||||||
| `error` | string \| null | |
|
| `error` | string \| null | |
|
||||||
| `completed_at` | ISO string \| null | |
|
| `completed_at` | ISO string \| null | |
|
||||||
| `commit` | string \| null | git sha after Checkpoint |
|
| `commit` | string \| null | full commit id (`git rev-parse HEAD`) after Checkpoint |
|
||||||
| `manifest_audit` | string | `pass \| fail \| pass-with-note \| n/a` |
|
| `manifest_audit` | string | `pass \| fail \| pass-with-note \| n/a` |
|
||||||
| `note` | string | optional human-readable annotation |
|
| `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}` |
|
| `start_sha` | string \| null | optional (wave 1) — git sha the step started from; every check of the step reads `git diff {start_sha}` |
|
||||||
|
|
@ -431,7 +432,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.
|
**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. 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. 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).
|
||||||
|
|
||||||
**Path conventions:**
|
**Path conventions:**
|
||||||
- Project-dir mode (recommended): `{project_dir}/review.md` (one per review iteration; subsequent runs overwrite atomically).
|
- Project-dir mode (recommended): `{project_dir}/review.md` (one per review iteration; subsequent runs overwrite atomically).
|
||||||
|
|
@ -442,12 +443,12 @@ missing `exit_code` (C15, `PROGRESS_FAILED_CRITERIA_KEY`).
|
||||||
| Field | Type | Required | Allowed values | Notes |
|
| Field | Type | Required | Allowed values | Notes |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `type` | string | yes | `trekreview` | Hard-coded discriminator |
|
| `type` | string | yes | `trekreview` | Hard-coded discriminator |
|
||||||
| `review_version` | string | yes | `"1.0"` (current) | Bump on schema change |
|
| `review_version` | string | yes | `"1.1"` (current) | Bump on schema change |
|
||||||
| `task` | string | yes | one-line description | Mirrors brief task |
|
| `task` | string | yes | one-line description | Mirrors brief task |
|
||||||
| `slug` | string | yes | URL-safe slug | Used in project_dir |
|
| `slug` | string | yes | URL-safe slug | Used in project_dir |
|
||||||
| `project_dir` | string | yes | `.claude/projects/{date}-{slug}/` | |
|
| `project_dir` | string | yes | `.claude/projects/{date}-{slug}/` | |
|
||||||
| `brief_path` | string | yes | path to consumed `brief.md` | Audit trail back to brief |
|
| `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 | Defines "after" boundary |
|
| `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 |
|
||||||
| `reviewed_files_count` | number | yes | ≥ 0 | From triage gate Coverage |
|
| `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 |
|
| `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) |
|
| `verdict` | string | yes (1.1; strict at write, warning at read) | `BLOCK \| WARN \| ALLOW` | Coordinator output; equals the trailing JSON block's `verdict` (K7) |
|
||||||
|
|
@ -484,7 +485,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.
|
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,
|
`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.
|
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), 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).
|
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).
|
||||||
A plan made from the review skips a lowered finding: it is MINOR, and `/trekplan` takes BLOCKER and MAJOR findings only.
|
A plan made from the review skips a lowered finding: it is MINOR, and `/trekplan` takes BLOCKER and MAJOR findings only.
|
||||||
|
|
||||||
**Validation strategy:**
|
**Validation strategy:**
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Imported from `CLAUDE.md` via pointer.
|
||||||
Wiring points (replaces previous prose-grep instructions):
|
Wiring points (replaces previous prose-grep instructions):
|
||||||
- `/trekbrief` Phase 4g → `brief-validator` (post-write sanity check)
|
- `/trekbrief` Phase 4g → `brief-validator` (post-write sanity check)
|
||||||
- `/trekplan` Phase 1 → `brief-validator --soft`, `research-validator --dir`, `architecture-discovery`
|
- `/trekplan` Phase 1 → `brief-validator --soft`, `research-validator --dir`, `architecture-discovery`
|
||||||
- `planning-orchestrator` Phase 5.5 → `plan-validator --strict` (replaces 3 `grep -cE` calls)
|
- `/trekplan` Phase 8 → `plan-validator --strict` (replaces 3 `grep -cE` calls)
|
||||||
- `/trekexecute --validate` → `plan-validator --strict` + `progress-validator`
|
- `/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).
|
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).
|
**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 = `--gates open` + sequential-only). 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 = one session at a time). 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`.
|
**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-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 (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.
|
**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.
|
||||||
|
|
||||||
**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.
|
**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 |
|
| _(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 |
|
| `--quick` | Proposes `small` as the class (still said aloud, overridable, raised when the task proves bigger) → brief.md with research plan |
|
||||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
| `--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`. |
|
||||||
| `--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`. |
|
| `--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`. |
|
| `--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) |
|
| `--local` | Only codebase analysis agents (skip external research) |
|
||||||
| `--external` | Only external research agents (skip codebase analysis) |
|
| `--external` | Only external research agents (skip codebase analysis) |
|
||||||
| `--fg` | No-op alias (foreground is default since v2.4.0) |
|
| `--fg` | No-op alias (foreground is default since v2.4.0) |
|
||||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
| `--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`. |
|
||||||
| `--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 |
|
| `--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. |
|
| `--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`. |
|
| `--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 |
|
| `--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) |
|
| `--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) |
|
| `--decompose <plan>` | Split plan into self-contained session specs + `orders.md` (one starter line per session) |
|
||||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
| `--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`. |
|
||||||
| `--profile <name>` | (v4.1.0) Model profile for the plan phase (and others, since plan emits `profile:` to plan.md frontmatter). |
|
| `--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.
|
**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 |
|
| `--step N` | Execute only step N |
|
||||||
| `--fg` | Force foreground — run all steps sequentially, ignore Execution Strategy |
|
| `--fg` | Force foreground — run all steps sequentially, ignore Execution Strategy |
|
||||||
| `--session N` | Execute only session N from plan's Execution Strategy |
|
| `--session N` | Execute only session N from plan's Execution Strategy |
|
||||||
| `--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). |
|
| `--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) Model profile for the execute phase. Inherited from plan.md frontmatter `profile:` if present. |
|
| `--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. |
|
||||||
|
|
||||||
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.
|
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) |
|
| _(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` |
|
| `--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` |
|
| `--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 — fast correctness-only pass |
|
| `--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 |
|
||||||
| `--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) |
|
| `--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 |
|
| `--dry-run` | Print discovered scope + triage map; skip writes |
|
||||||
| `--fg` | No-op alias (foreground is default) |
|
| `--fg` | No-op alias (foreground is default) |
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,9 @@ Imported from `CLAUDE.md` via pointer.
|
||||||
|
|
||||||
## Autonomy mode (`--gates`, v3.4.0)
|
## Autonomy mode (`--gates`, v3.4.0)
|
||||||
|
|
||||||
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.
|
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).
|
||||||
|
|
||||||
`/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)):
|
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`.
|
||||||
|
|
||||||
| `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.
|
**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.
|
||||||
|
|
||||||
|
|
@ -32,7 +24,7 @@ A revived Path C (post-v2.2.xxx) would require: (1) re-architecting tool-list to
|
||||||
|
|
||||||
## Profile system (`--profile`, v4.1.0)
|
## 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>` and emitted to `${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl` for cost-attribution.
|
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>`.
|
||||||
|
|
||||||
| Profile | Brief | Research | Plan | Execute | Review | Continue | Use case |
|
| Profile | Brief | Research | Plan | Execute | Review | Continue | Use case |
|
||||||
|---------|-------|----------|------|---------|--------|----------|----------|
|
|---------|-------|----------|------|---------|--------|----------|----------|
|
||||||
|
|
|
||||||
|
|
@ -118,20 +118,16 @@ Voyage resolves the profile in this priority order:
|
||||||
3. **`VOYAGE_PROFILE` environment variable** — useful for headless CI
|
3. **`VOYAGE_PROFILE` environment variable** — useful for headless CI
|
||||||
4. **Default `premium`** — final fallback
|
4. **Default `premium`** — final fallback
|
||||||
|
|
||||||
The resolved value is recorded in two places:
|
The plan-file fields for the resolved value:
|
||||||
|
|
||||||
- Plan-file frontmatter `profile: <name>` and `phase_models: [...]`
|
- 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
|
## Custom profiles
|
||||||
|
|
||||||
Drop a YAML file at `lib/profiles/<name>.yaml` to define a new tier.
|
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.
|
||||||
The validator (`lib/validators/profile-validator.mjs`) enforces:
|
The validator (`lib/validators/profile-validator.mjs`) enforces:
|
||||||
|
|
||||||
- Every `phase_models[].phase` must be a known phase enum:
|
- Every `phase_models[].phase` must be a known phase enum:
|
||||||
|
|
@ -203,9 +199,8 @@ execute + review) on a moderate-complexity task. Numbers scale roughly
|
||||||
linearly with the size of the resulting plan (10 steps ≈ baseline; 30
|
linearly with the size of the resulting plan (10 steps ≈ baseline; 30
|
||||||
steps ≈ 3× the execute column).
|
steps ≈ 3× the execute column).
|
||||||
|
|
||||||
Per-profile actuals are emitted to JSONL stats — pipe them through the
|
The stats records carry no profile field, so they cannot split cost by
|
||||||
OTel export (`docs/observability.md`) to get real cost-attribution
|
profile. Replace the table above with your own measured
|
||||||
graphs in Grafana. Replace the table above with your own measured
|
|
||||||
numbers after ≥ 3 runs of each profile.
|
numbers after ≥ 3 runs of each profile.
|
||||||
|
|
||||||
## Deferred to v4.2
|
## Deferred to v4.2
|
||||||
|
|
|
||||||
|
|
@ -225,14 +225,18 @@ changes introduced by commits that are not ancestors of the previously
|
||||||
reverted merge." Revert the revert commit instead, and release it as a new
|
reverted merge." Revert the revert commit instead, and release it as a new
|
||||||
version.
|
version.
|
||||||
|
|
||||||
## Not built yet: the eval gate (P10)
|
## Exempted: the eval gate (P10)
|
||||||
|
|
||||||
The local gate before a release that reads the date and score of the last run
|
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
|
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
|
configuration paths (commands, agents, skills, hooks, and a changed model alias
|
||||||
counts as a change). It waits for the test set to run again; a gate that can
|
counts as a change). It is exempted from the release, with a reason: it waits
|
||||||
never fire is not built. When it comes, it is one more check in
|
for the fixed test set to run again, and a gate that can never fire is not
|
||||||
`scripts/release-check.mjs`, before the door check, and one more step in § 1.
|
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.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,10 @@ 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
|
- 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
|
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 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.
|
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.
|
||||||
- The thresholds are pinned in `tests/lib/skill-routing.test.mjs` and never lowered. A failing case
|
- 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
|
is fixed in a description, never in a number. You do not change another component's
|
||||||
description to make room for yours.
|
description to make room for yours.
|
||||||
|
|
@ -72,6 +75,10 @@ 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.
|
`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`
|
- A **skill-trigger** case has one grader: `type: tool_used`, `tool: Skill`, with an `input_match`
|
||||||
that accepts `voyage:<name>` and the bare name.
|
that accepts `voyage:<name>` and the bare name.
|
||||||
|
|
@ -120,12 +127,15 @@ The pressure itself did not break the control in any run. The skills target what
|
||||||
|
|
||||||
## Adding a skill: checklist
|
## Adding a skill: checklist
|
||||||
|
|
||||||
1. Run the red baseline; keep the transcripts' findings.
|
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.
|
||||||
2. Write `skills/<name>/SKILL.md` in the S1 form; run `node lib/skills/skill-lint.mjs`.
|
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`.
|
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.
|
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.
|
5. Run the scenarios with the skill; record both arms.
|
||||||
6. Add one row to `## Skills` in `README.md` and `CLAUDE.md`.
|
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).
|
||||||
|
|
||||||
## Credits
|
## 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)."
|
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."
|
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]
|
tags: [proevesett, from=proevesett-intent-gate]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 15
|
max_turns: 15
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: "/trekplan on a brief_version 2.1 brief without phase_signals halts at the sequencing gate."
|
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."
|
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]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 15
|
max_turns: 15
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: "/trekplan --project on a missing folder stops before any exploration."
|
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."
|
expected_outcome: "'Error: project directory not initialized. Run /trekbrief to create it.'; no Agent call, no plan.md."
|
||||||
tags: [proevesett]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 8
|
max_turns: 8
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: "/trekplan --export with a removed format names the format and stops."
|
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."
|
expected_outcome: "'Error: export format 'pr' is not supported.'; no Agent call, no file written."
|
||||||
tags: [proevesett]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 8
|
max_turns: 8
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: "/trekplan with no arguments prints usage and stops."
|
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."
|
expected_outcome: "Usage block ending in 'A brief is required. Produce one with /trekbrief first.'; no Agent call, no file written."
|
||||||
tags: [proevesett]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 8
|
max_turns: 8
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: "/trekreview with no arguments demands --project and stops."
|
description: "/trekreview with no arguments demands --project and stops."
|
||||||
expected_outcome: "'Error: --project <dir> is required.' plus usage; no Agent call, no file written."
|
expected_outcome: "'Error: --project <dir> is required.' plus usage; no Agent call, no file written."
|
||||||
tags: [proevesett]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 8
|
max_turns: 8
|
||||||
timeout_seconds: 300
|
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."
|
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."
|
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]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 10
|
max_turns: 10
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
description: "KNOWN-NEGATIVE. /trekreview --validate on a valid review.md passes and raises no error code."
|
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."
|
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]
|
tags: [proevesett, from=proevesett-eval-suite]
|
||||||
runs: 1
|
runs: 1
|
||||||
max_turns: 10
|
max_turns: 10
|
||||||
timeout_seconds: 300
|
timeout_seconds: 300
|
||||||
|
|
|
||||||
4
evals/skill-annotating-effect/case.yaml
Normal file
4
evals/skill-annotating-effect/case.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
schema_version: "1.1"
|
||||||
|
name: skill-annotating-effect
|
||||||
|
context:
|
||||||
|
scaffold_script: scaffold.sh
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
24
evals/skill-annotating-effect/prompt.md
Normal file
24
evals/skill-annotating-effect/prompt.md
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
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?
|
||||||
88
evals/skill-annotating-effect/scaffold.sh
Executable file
88
evals/skill-annotating-effect/scaffold.sh
Executable file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/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
|
||||||
5
evals/skill-annotating-fires-1/graders/skill-fired.md
Normal file
5
evals/skill-annotating-fires-1/graders/skill-fired.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||||
|
---
|
||||||
10
evals/skill-annotating-fires-1/prompt.md
Normal file
10
evals/skill-annotating-fires-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
5
evals/skill-annotating-fires-2/graders/skill-fired.md
Normal file
5
evals/skill-annotating-fires-2/graders/skill-fired.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||||
|
---
|
||||||
19
evals/skill-annotating-fires-2/prompt.md
Normal file
19
evals/skill-annotating-fires-2/prompt.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
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?
|
||||||
5
evals/skill-annotating-fires-3/graders/skill-fired.md
Normal file
5
evals/skill-annotating-fires-3/graders/skill-fired.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||||
|
---
|
||||||
10
evals/skill-annotating-fires-3/prompt.md
Normal file
10
evals/skill-annotating-fires-3/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
8
evals/skill-annotating-quiet-1/graders/skill-quiet.md
Normal file
8
evals/skill-annotating-quiet-1/graders/skill-quiet.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-annotating-quiet-1/prompt.md
Normal file
10
evals/skill-annotating-quiet-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
8
evals/skill-annotating-quiet-2/graders/skill-quiet.md
Normal file
8
evals/skill-annotating-quiet-2/graders/skill-quiet.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?annotating"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-annotating-quiet-2/prompt.md
Normal file
10
evals/skill-annotating-quiet-2/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
20
evals/skill-interviewing-effect-hollow/prompt.md
Normal file
20
evals/skill-interviewing-effect-hollow/prompt.md
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
4
evals/skill-interviewing-effect-round/case.yaml
Normal file
4
evals/skill-interviewing-effect-round/case.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
schema_version: "1.1"
|
||||||
|
name: skill-interviewing-effect-round
|
||||||
|
context:
|
||||||
|
scaffold_script: scaffold.sh
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
15
evals/skill-interviewing-effect-round/prompt.md
Normal file
15
evals/skill-interviewing-effect-round/prompt.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
92
evals/skill-interviewing-effect-round/scaffold.sh
Executable file
92
evals/skill-interviewing-effect-round/scaffold.sh
Executable file
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/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
|
||||||
5
evals/skill-interviewing-fires-1/graders/skill-fired.md
Normal file
5
evals/skill-interviewing-fires-1/graders/skill-fired.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||||
|
---
|
||||||
10
evals/skill-interviewing-fires-1/prompt.md
Normal file
10
evals/skill-interviewing-fires-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
5
evals/skill-interviewing-fires-2/graders/skill-fired.md
Normal file
5
evals/skill-interviewing-fires-2/graders/skill-fired.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||||
|
---
|
||||||
10
evals/skill-interviewing-fires-2/prompt.md
Normal file
10
evals/skill-interviewing-fires-2/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
5
evals/skill-interviewing-fires-3/graders/skill-fired.md
Normal file
5
evals/skill-interviewing-fires-3/graders/skill-fired.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||||
|
---
|
||||||
10
evals/skill-interviewing-fires-3/prompt.md
Normal file
10
evals/skill-interviewing-fires-3/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
8
evals/skill-interviewing-quiet-1/graders/skill-quiet.md
Normal file
8
evals/skill-interviewing-quiet-1/graders/skill-quiet.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-interviewing-quiet-1/prompt.md
Normal file
10
evals/skill-interviewing-quiet-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
8
evals/skill-interviewing-quiet-2/graders/skill-quiet.md
Normal file
8
evals/skill-interviewing-quiet-2/graders/skill-quiet.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?interviewing"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-interviewing-quiet-2/prompt.md
Normal file
10
evals/skill-interviewing-quiet-2/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
4
evals/skill-reviewing-adversarially-effect/case.yaml
Normal file
4
evals/skill-reviewing-adversarially-effect/case.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
schema_version: "1.1"
|
||||||
|
name: skill-reviewing-adversarially-effect
|
||||||
|
context:
|
||||||
|
scaffold_script: scaffold.sh
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
type: regex
|
||||||
|
pattern: "#{2,3} Declined to Judge[\\s\\S]*receipt\\.mjs"
|
||||||
|
---
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
11
evals/skill-reviewing-adversarially-effect/prompt.md
Normal file
11
evals/skill-reviewing-adversarially-effect/prompt.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
85
evals/skill-reviewing-adversarially-effect/scaffold.sh
Executable file
85
evals/skill-reviewing-adversarially-effect/scaffold.sh
Executable file
|
|
@ -0,0 +1,85 @@
|
||||||
|
#!/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
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||||
|
---
|
||||||
10
evals/skill-reviewing-adversarially-fires-1/prompt.md
Normal file
10
evals/skill-reviewing-adversarially-fires-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||||
|
---
|
||||||
10
evals/skill-reviewing-adversarially-fires-2/prompt.md
Normal file
10
evals/skill-reviewing-adversarially-fires-2/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||||
|
---
|
||||||
10
evals/skill-reviewing-adversarially-fires-3/prompt.md
Normal file
10
evals/skill-reviewing-adversarially-fires-3/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-reviewing-adversarially-quiet-1/prompt.md
Normal file
10
evals/skill-reviewing-adversarially-quiet-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?reviewing-adversarially"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-reviewing-adversarially-quiet-2/prompt.md
Normal file
10
evals/skill-reviewing-adversarially-quiet-2/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
4
evals/skill-writing-criteria-effect/case.yaml
Normal file
4
evals/skill-writing-criteria-effect/case.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
schema_version: "1.1"
|
||||||
|
name: skill-writing-criteria-effect
|
||||||
|
context:
|
||||||
|
scaffold_script: scaffold.sh
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: regex
|
||||||
|
pattern: '&&'
|
||||||
|
match: not_contains
|
||||||
|
---
|
||||||
34
evals/skill-writing-criteria-effect/prompt.md
Normal file
34
evals/skill-writing-criteria-effect/prompt.md
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
60
evals/skill-writing-criteria-effect/scaffold.sh
Executable file
60
evals/skill-writing-criteria-effect/scaffold.sh
Executable file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#!/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
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||||
|
---
|
||||||
10
evals/skill-writing-criteria-fires-1/prompt.md
Normal file
10
evals/skill-writing-criteria-fires-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||||
|
---
|
||||||
10
evals/skill-writing-criteria-fires-2/prompt.md
Normal file
10
evals/skill-writing-criteria-fires-2/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||||
|
---
|
||||||
10
evals/skill-writing-criteria-fires-3/prompt.md
Normal file
10
evals/skill-writing-criteria-fires-3/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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?
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
type: tool_used
|
||||||
|
tool: Skill
|
||||||
|
input_match: '"skill"\s*:\s*"(?:voyage:)?writing-criteria"'
|
||||||
|
min: 0
|
||||||
|
max: 0
|
||||||
|
arm: both
|
||||||
|
---
|
||||||
10
evals/skill-writing-criteria-quiet-1/prompt.md
Normal file
10
evals/skill-writing-criteria-quiet-1/prompt.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
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.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
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