The three producing commands name voyage:annotating where they build the page; the description of the page and the freehand revision left them. The skill: the person writes every note, Fix/Change edit only the quoted text, a Question is answered and changes nothing, the approval an edit costs is said before the edit, the page is rebuilt. Research documents on request (decision 62). Red baseline 3 runs per scenario without and with the skill; six eval cases; 11 pins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A brief success criterion and a plan's Verify, Regression, End-to-end and
Verification lines are each one command the criteria runner accepts, written
as the line's first backticked span; anything more is bash tests/<name>.sh,
and each must be able to go red (the runner reads the exit code only).
- skills/writing-criteria/SKILL.md (S1 form), with Runs:/Refused:/Never red:
examples that a pin runs through the criteria runner
- brief-reviewer and plan-critic preload writing-criteria and
reviewing-adversarially (S3 + S4); the copied runner rules leave them, the
two templates and /trekplan, which names the skill where the plan is written
and where its three reviewers start
- eval cases 3 fire / 2 quiet / 1 effect; tests/lib/skills-criteria-prose-pins
- review-630 @~1 pin follows the text into the skill; trekplan-stats line_ref
re-measured
Baseline without the skill: 24 of 27 written checks refused by the runner,
and 0 of 3 reviewers saw that git status/git log can never go red. With it:
0 of 27 refused, 3 of 3 reviewers flagged both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 8 (0f400d3..29b4ac9, BLOCK: 1 BLOCKER, 12 MAJOR, 1 MINOR). Each fix
began with a test that failed on 29b4ac9 (13 tests, all red there); suite
2221 (2219/0/2).
- BLOCKER: a backticked check whose trailing comment holds a quote, $,
backtick or backslash is refused, not dropped. The comment was never
screened, while the executor hands the Verify span as written to red
proof, the test lock and the done line inside --cmd "...", where a $(...)
runs and a quote ends the argument. trekplan's text and the reviewer's
NOT RUN table say so.
- A span that is only a comment is not-a-command, not a placeholder. The
dropComment text says the allowlist still refuses a word with a # in it.
- The criteria runner, comparison-gate and end-state-gate use isMain: they
did nothing and exited 0 under a symlinked path. The test now refuses any
process.argv[1] comparison outside lib/util/is-main.mjs.
- Files: in a field with backticked paths, a plain word counts only before
the entry's description (a dash, or a colon after the path); a name with
no slash only first in its entry or after and/or/+/&. "mocks
fs.readFileSync", "runs on Node.js 22.x" or "no change to package.json"
no longer make a tests-only step look like it builds something.
Lowercase makefile, rakefile and justfile are build files. Measured on the
520 Files: fields in 48 plans of the marketplace and the test repo:
3 fields read differently (two notes no longer read as files, one
duplicate name dropped), tests-only changed in 0.
- The test lock compares --cmd without its trailing comment, and the test
lock and the done line read a stop with stoppedBy, the one reading.
red-proof drops its second reading, spawnError.
- release-check reads a relative --review in --repo or, when only that one
exists, from the current directory as 6.3.0 did; two different files are
exit 2, never guessed. The runbook says so.
- One trailing-json reader: a closing fence may be longer than three
backticks, in the block reader and the verdict gate alike, and the review
validator and the synthesis digest use it, so three backticks inside a
JSON string no longer hide a BLOCKER from the remediation-step check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 7 (516dffa..45aa9e1, WARN: 12 MAJOR, 0 BLOCKER) and the fence defect
found while writing its review.md. Each fix began with a test that failed on
0f400d3 (v6.3.0); suite 2208 (2206/0/2), 14 tests more.
- Tests-only (operator 2026-10-11): the plan's Files: alone decides, and the
text says so (red-proof, trekexecute Sub-step B, step-implementer,
HANDOVER-CONTRACTS). red-proof no longer reads the step's diff, so a change
already in the tree when the step began no longer counts against it, and a
plan placed outside .claude/ reads the same. The round-6 test that had the
diff overrule the plan is rewritten to the new rule.
- The Files: reader keeps a plain file beside a backticked path
(", Dockerfile", "the CLI entry src/cli.mjs", "and Makefile"). Measured on
the 520 Files: fields in 182 plans: no field reads differently.
- Red proof reports a command its timeout killed as killed after the timeout,
not "could not start"; the release check tells a timeout from output past
its buffer and from another signal. One reading of a stop
(criteria-runner stoppedBy) for red proof, the criteria runner and the
release check.
- A trailing `# comment` is dropped in a backticked check too, and in a
command passed as written, so the words screened are the words run.
- The release check reads a relative --review in --repo.
- The 15-minute timeout is defined once (criteria-runner.mjs).
- The findings check reads each cited file once per validation.
- One isMain helper (lib/util/is-main.mjs) for every CLI: the 31 copies of
the realpath guard and the 20 modules still on the file:// guard, which
exited 0 having done nothing under a symlink or a path with a space.
- The Bash guard writes its no-one-to-ask refusal once, on a direct condition.
- The findings check ends a ```json block only at a fence on its own line, so
three backticks inside a JSON string no longer end it (also in 6.2.0).
- Brief-conformance notes: a test for test-lock green on exit 127 (it
passed at once; it fails when 127 is read as could-not-run); the prose now
names the git revision `@~1` as the one leading-@ exception.
Not changed: the example plan's steps 1-2 keep their tests-only warning
(operator decision 2026-10-09; the r5 test records it). Brief note 4 (a
Regression: whose runner is not installed goes to the fix rounds) is a
routing question for the operator.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 6 (v6.2.0..c3641ff, WARN: 11 MAJOR, 3 MINOR; 0 BLOCKER). The round-5
fixes hold (code-correctness-reviewer); three of the new MAJOR were side
effects of running checks with no shell. Each fixed behind a test that
failed first on c3641ff.
- git checks stay in the repo too: no path that climbs out with .., starts
at / or reads <rev>:../x, and no --no-index (both reviewers).
- A trailing `# comment` on a shell-fence line is dropped: with no shell,
its words made an honest check NOT RUN, among them the first check of the
shipped example plan.
- A glob reaches `node --test` only on Node 21 and later, which expands it
itself; on an older Node it is refused with that reason (engines >=18).
- With no shell, exit 126/127 is the test program's own: red proof reads it
as a red (the control run still tells an environment fault apart), the
done line and the test lock as a failure.
- A runner that could not start (not installed) is NOT RUN in the criteria
runner and not-run (exit 2) in regression-check, as red-proof and
done-line already said; never a red suite.
- Tests-only: a backticked `Makefile` alone in its entry is a path, and red
proof confirms the plan's tests-only reading against the step's own diff
(the altitude finding: the diff is a fact, the Files: prose is not).
- release-check stops a suite that never ends (15 minutes) and reads it as
not measured (exit 2).
- The two lines this release added to pre-bash-executor.mjs are ASCII.
- MINOR: git and the other runners share one plain-word pattern.
Not in this round: MINOR f00a2eb8 (shared norm/ticked-path and isMain
helpers) and MINOR on plan-review-dedup's repeated tokenizing.
Suite 2194 (2192/0/2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 5 (v6.2.0..d37e538, WARN: 11 MAJOR, 2 MINOR). The patching did not
converge (the same two places every round), so the operator chose a
structural fix on 2026-10-11. Each change behind a test that failed first.
- A check runs with no shell. criteria-runner's runCommand starts the runner
with the very words the screen checked (spawnSync(words[0], words.slice(1)),
without NODE_TEST_CONTEXT); Phase 7 criteria, Regression: (its exec copy is
gone, MINOR 0e98d5c7), proof of red, the done line and the test lock all
run through it. No quote, glob, tilde or variable can rewrite a checked
word any more. The screen stays and says why: a word that means something
else in a shell (quote, backslash, $, brace, leading ~) is refused; a glob
reaches only node --test, which expands its own patterns (sh read
`tests/.?/` as `tests/../`); no path climbs out with .. or starts at /;
a word starting with @ is refused (pytest reads @file as more arguments).
- The K6 plan-file sweep has v6.2.0's own Files: reader again (516dffa):
backticked paths, and plain words only in a field without them. The
shared reader from round 3 planned directories a description named and
dropped paths v6.2.0 planned. fieldPaths stays for the tests-only check,
with a path test on spans (`parse()`, `p.parse()` are no paths), plain
descriptions ignored when the field has backticked paths, dotfiles,
backslash paths and glued spans read.
- Skill frontmatter reads a value as YAML does: trailing space is nothing,
and a comment ends a plain value, a flow list or a block indicator
(`model: opus # pinned`). A comment that cuts a plain description, or is
the whole value, is still a hazard.
- release-check reads the diff with --no-renames: a test moved into an
allowed place after the review shows as removed.
- The example plan's step 2 heading no longer says "must FAIL initially";
steps 1-2 keep the tests-only warning (operator 2026-10-09, 73262b6).
Open: MINOR c1fef1ad (one shared isMain helper) is not in this round.
Measured: 0 of 463 Files: fields with backticked paths (520 fields in 182
plans across the marketplace repos) carry another path-like word.
Suite 2185 (2183/0/2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The review of v6.2.0..f669b87 (BLOCK: 1 BLOCKER, 12 MAJOR, 1 MINOR), each
fixed behind a test that failed first, or, for the two missing tests, a test
shown to fail on a stub of the branch it covers.
- Review steps appended by /trekexecute Phase 7.2 are held to the step rules
on any plan version: plan-validator --steps-from <N> (on a plan below 1.8 a
template review step validated and was executed).
- The guard refuses where no one can be asked also when its rules will not
load; the wave merge path names that refusal instead of MERGE_REFUSED.
Tests for the classifier-error refusal and post-approval-log's own check.
- release-check: the version files may change only in their version after
the review (JSON compared without it), README diff lines are read inside
hunks only, an unreadable diff is exit 2, and npm test runs without
NODE_TEST_CONTEXT.
- What counts as a step of only tests: a note in parentheses is not a path,
and a data file under specs/ is not a test. End-to-end: rides on the last
step that builds behaviour (validator hint, trekplan, template).
- A removed line is cited as <rev>:<path>:<line> (findings-schema hint,
trekreview re-ask).
- skill-lint counts a trailing newline as no line; regression-check takes
commandEnv from lib/util/command-env.mjs; CLAUDE.md names four mode-read
exemptions.
- /security-review, older than v6.2.0: the criteria runner refuses git
--output, which writes a file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1. A step of only tests can never be proven red. One reading,
stepTestsOnly (lib/parsers/plan-schema.mjs, test paths from the new
lib/util/test-path.mjs): the plan validator warns PLAN_STEP_TESTS_ONLY,
red-proof --plan/--step adds tests_only to a not-red-at-base, and
/trekexecute and the step helper send such a step straight up to the
plan instead of into fix rounds that cannot succeed. /trekplan, the plan
template and plan-critic (dimension 8, still 12) say the test belongs in
the step that builds the behaviour.
2. Timing tests under load: the hook helper's kill limit is 30 s and per
call overridable; SC #14 passes on the fastest of up to three runs
against the same 800 ms limit (tests/helpers/timing.mjs).
3. The example plan's On failure lines open with a K11 word.
4. /trekreview saves the reviewer's whole answer for the findings check and
names FINDING_PROSE_LINE_OUT_OF_RANGE (error: re-ask; warning: report).
5. The criteria runner's commands run without NODE_TEST_CONTEXT
(commandEnv, moved to lib/util/command-env.mjs).
6. The resolver returns effort only when the brief's phase signal sets one;
the four commands said it always did.
Also: the K2 hook tests used fixed session ids in a per-user temp dir, so
two suites running at once took each other's approval records; the ids are
now unique per run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The minor points (B8-B12, C13, C14, C16, C17) of the second voyage-lekerepo
trial (2026-10-08), each verified against the code and started with a test
that failed first.
- K10: optional step field `Regression:` - one command the criteria runner
allows, unpiped; plan-validator refuses one that can never run
(PLAN_STEP_REGRESSION_NOT_RUNNABLE). Any plan_version, no bump.
- K11: `On failure:` opens with revert | retry | skip | escalate, or the
validator warns (PLAN_STEP_ON_FAILURE_UNKNOWN); onFailureAction in
plan-schema.
- B8 (operator decision 2026-10-08): minors open after the last critic round
are listed numbered in the Phase 10 summary; the ones the operator picks are
fixed and get one more round (--extra-round when the 3 are spent).
- B11: plan-review dedup merges two reviewers' findings on the same file:line
with the same content (trial pair: Jaccard 0.44, overlap 0.83); the Jaccard
threshold for every other pair is unchanged.
- B12: /trekbrief Step 4c says the reviewer runs in the background and is
waited for, not "foreground, blocking".
- C13: the Phase 4 size count includes .mjs, .cjs, .mts, .cts.
- C14: --evidence shows the first output line on PASS rows.
- C16: findings-schema checks path:line citations in finding prose (error) and
in the prose around the block (warning) against the file.
- C17: git-historian gets the brief, never proposes changing a frozen file,
and names the remote from `git remote -v`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voyage-lekerepo trial 2 (2026-10-08), report section A; the operator decided
they are fixed before the next release:
- A1: a /code-review finding whose category is simplification, efficiency,
style or readability enters as CODE_REVIEW_IMPROVEMENT (MINOR), not MAJOR.
- A2: recommended_action is the engine's own fix when transcribed, otherwise
a test-first step; never the failure scenario dressed as a remedy.
- A3: a /code-review finding outside the exact range it was given is declined
and listed, but no longer holds ALLOW back; /security-review's still does.
- A4: the manifest must_contain recipe uses grep -E -e ... -- so a pattern
like --sep is not read as an option.
- A5: indented sub-points belong to their criterion (counted), and a
criterion with sub-points and no command warns BRIEF_SC_SUBPOINTS.
- A6: a brief requiring bash 3.2 whose criterion runs plain bash warns
BRIEF_SC_BASH_NOT_PINNED; /trekbrief proposes /bin/bash.
- A7: the plan template's and /trekplan's checkpoints stage the step's files.
Tests fail on 5f9faee first (tests/lib/trial2-fixes.test.mjs, 11 of 14).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voyage-lekerepo trial (2026-10-06) point 6, operator decision 2026-10-08
(«samme skala, og du spør»): the critics rated a non-discriminating test
minor in round 3, there was no way to fix it after the last round, it was
built, and /trekreview called the same weakness MAJOR (MISSING_TEST).
- plan-critic, scope-guardian: rate on the review catalogue's tiers; a test
that cannot fail on a wrong implementation is major, never minor.
- plan-gate: an open MAJOR stops (PLAN_GATE_OPEN_MAJOR: revise and run the
next round; PLAN_GATE_OPEN_MAJOR_FINAL after the last round: ask the
operator). --accept-open records "build as is" after their yes, bound to
the round and the plan hash; never for a blocker.
- trekplan Phase 9: REVISE after the last round asks fix now (one extra
round) or build as is, instead of carrying the majors silently.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voyage-lekerepo trial (2026-10-06) point 14, operator decision 2026-10-08
(«alle agenter, ny briefsjekk bare ved endring»):
- trekplan: the "Adaptive" hard rule (a 10-file project does not need 7
agents) contradicted Phase 5 ("All agents run for all codebase sizes");
it is gone, in line with quality before cost.
- brief-review-stamp.mjs: /trekbrief stamps the brief body when its
brief-reviewer gate passes; /trekplan Phase 4b skips its own review only
while the stamp is current. Stale (edited) or absent (another producer,
or a gate that did not pass) reviews as before. Additive optional
frontmatter fields, documented in Handover 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voyage-lekerepo end-to-end trial (2026-10-06), report points 2, 3, 4, 9:
11 of 13 brief criteria were NOT RUN at review with no warning in /trekbrief;
a plan `git grep` criterion passed validator, gate and three critic rounds,
then felled the run in Phase 7; the End-to-end field and Phase 7's text
search never met; a prose Verify left the test command undefined.
- criteria-runner: runnableCheck() screens a declared check without running
it (same allowlist; an npm run script is not looked up at write time);
/bin/bash tests/<script> allowed; the plan report carries end_to_end,
verified when a passed criterion runs a step's End-to-end command (the
older text form still counts).
- plan-validator 1.8: PLAN_VERIFICATION_NOT_RUNNABLE,
PLAN_STEP_VERIFY_NOT_RUNNABLE, PLAN_END_TO_END_NOT_RUNNABLE,
PLAN_END_TO_END_NOT_VERIFIED (the gate inherits them).
- brief-validator: BRIEF_SC_NOT_RUNNABLE warning; /trekbrief offers a
tests/ script; brief-reviewer no longer proposes unrunnable commands.
- trekexecute: Phase 7 copies end_to_end from the runner; Verify's test
command is its first backticked span.
Measured on the trial's own brief and plan: 11 warnings (the 11 NOT RUN),
and the plan stops on V5 git grep and the unlisted End-to-end command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wave 1, order 3 (P3 plan mode as the start, P2 design as its own part, P9
plan side). Contracts K3-K6 for the later merges.
- plan_version 1.8 (1.7 plans stay valid): Test first on every step, one
End-to-end ("run the thing") step, optional Interface in / Interface out /
Review focus fields, a ceremony class in the header (absent =
architectural), and for architectural plans a ## Design part: module map
without cycles, architecture rules that name their enforcer and the step
that proves them, a requirements check asked as keep / change.
- K3 lib/validators/plan-gate.mjs: the critic verdict is recorded INSIDE the
plan (Claude Code's plan approval hands a hook only the plan file's text),
bound to the hash taken before the reviewers read it; 0 go / 1 stop / 2
could not run; at most 3 critic rounds, then stop and ask.
- K5 lib/verification/arch-rules.mjs: runs the target repo's own
dependency-cruiser or import-linter (installs nothing; 2 = not measured,
never green); --prove --rule shows pass -> fail on a planted violation of
that rule -> pass. Verified against dependency-cruiser 18.5.0 and
import-linter 2.15; madge 8.0.0 left out (missed a planted .mjs cycle).
- K6 lib/verification/plan-scope-sweep.mjs: changed files no step names.
- /trekplan Phases 8-10: design part, bounded critic loop, the gate before
"execute", a plan-mode path through ExitPlanMode (not yet run end to end
inside plan mode). plan-critic 10 -> 12 dimensions; scope-guardian checks
the ceremony.
- Fixed on the way: plan-validator and plan-review-dedup used the
file://argv[1] main guard (no-op under a symlink or a space); CRLF plans
failed every manifest; the dedup dropped finding severity.
Borrowed, credited in place: obra/superpowers, Kiro (docs), addyosmani/
agent-skills, mattpocock/skills, GitHub Spec Kit, bashebr/ai-native-sdlc,
Boris Cherny's public threads.
Suite 1497 (1495 / 0 / 2), 86 new tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
P1 (order 2, wave 1). /trekbrief puts the task in a size class
(ceremony: small|bounded|architectural, K1; heaviest in doubt, said
aloud, overridable, only moved up) that sets the question budget and the
review cap, and asks one round of questions: facts looked up, never
asked; recommendation first; ranked by impact x uncertainty with a
visible Deferred list; stop when the next three answers can be predicted.
"høres bra ut", "gjør som du vil" and an empty answer are not approval.
K2: lib/util/approval-log.mjs, an append-only hash-chained log in the
target repo (.claude/voyage/approvals.jsonl) bound to the approved
content's sha256; append/verify (0/1/2), answer, digest. Committed by
lib/util/artifact-commit.mjs: the log always, the brief and plan only
with artifact_store: git (operator decision 2026-10-06). /trekplan
Phase 1 halts on a broken, diverged, missing or mismatched log entry;
Phase 11 logs and commits an explicit plan approval before any handoff.
Both new brief fields are optional: no brief_version bump. The
main-module guard in intent-approval.mjs and brief-validator.mjs now
compares real paths. Borrowings credited in the prose and module headers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verified 2026-10-02 against code.claude.com/docs/en/model-config and
/sub-agents. On the Anthropic API opus -> Opus 5.5 and sonnet ->
Sonnet 5.5 (default effort medium), fable -> Fable 5.1 (default high).
Three more claims in the same section were false and are corrected:
an agent without effort: inherits the session level, not the model
default; MAX_THINKING_TOKENS=0 has no effect on Opus 5.5, Sonnet 5.5
or Fable; effort is capped by maxEffortLevel or an organization cap.
"Mythos-class" is replaced by the docs' own wording. History is
untouched (CHANGELOG, the measurement docs, the Path C line).
STATE said seven files but listed six; the red pin found exactly
these six. The end-state registry line names a CC changelog fact and
stays as history.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Operator decision 27.09.2026: Voyage works the PM way, so nothing in it
starts Claude Code. Work that needs another session becomes an order plus
a starter line the user gives a session they open themselves; Voyage
never starts the session.
/trekexecute's multi-session path (Phase 2.6) now prepares one wave at a
time: worktree per session, then lib/util/session-orders.mjs writes one
order per session (worktree, steps, done-condition, starter) plus
orders/wave.json, and the run stops. Running the same command again reads
each session's progress file (status mode), merges sequentially with
push-before-cleanup as before, and prepares the next wave. Phase 2.5 skips
the destructive pre-flight while a wave is in flight. Phase 7.6 recovery is
handed over the same way. Hard rule 21: never start Claude Code.
Removed with it, because they existed only for launched children: the
ANTHROPIC_API_KEY billing check (and its dry-run line and Hard rule 1
exception), the hooks-fire version precheck, the safety preamble, the
scoped-tool/turn/budget flags, templates/headless-launch-template.md, the
decomposer's launch.sh (now orders.md), /trekplan's "launch", the README
billing and MCP tuning sections, and scripts/q3-cache-prefix-experiment.mjs
(an experiment that spawned the binary; its results stay in docs/).
/trekresearch's deep-research pre-gate no longer runs the binary for its
version; the post-hoc check was already the authoritative guard.
Chose orders + starters over in-session subagents because the order's done
criterion asks for exactly that, and because /trekexecute disallows the
Agent tool on purpose (Hard rule 10); reopening that is a separate change.
Gate: 54 -> 0 hit lines outside EXEMPT. npm test 1250 (1245 pass, 0 fail,
5 skipped: 3 are the retired-reference scan without its local list).
verify.sh 7/0. The fixture run (tests/lib/session-orders.test.mjs) writes
two orders and wave.json for wave 1 and leaves a trap binary untouched.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M3: the header claimed "reflowing a paragraph keeps the approval"; joining
lines gives STALE (PM probe iii-c). It now says what keeps the approval
(indentation, in-line spacing, blank lines, CRLF) and that joining or
splitting lines makes it stale — erring safe. Also states the one-section
and code-block/comment rules from M1.
M7: the trekreview exemption is read from the brief's own frontmatter, so a
relabelled brief walks past the gate — the same trust class as self-stamping.
Now said in the module header, HANDOVER-CONTRACTS and /trekplan's gate prose.
HANDOVER-CONTRACTS also names both brief modes the --approve path reaches.
Red 097bae8 (M3, M7) → green. Suite 1224: 1222 pass / 0 fail / 2 skip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M1: headings inside fenced code blocks and HTML comments are text, not
headings, and ## Intent / ## Goal must each appear exactly once. A second
section, an example section in a code block or comment, or a '## ' line in
a code block inside Intent no longer carries the old approval: check gives
INVALID (duplicate) or STALE, stamp refuses a duplicate. A plain brief
hashes exactly as before (pinned), so no stamped brief goes stale.
Re-run of the PM's 29 probes: vi-a, vi-b, vii-a, vii-b now stop; the rest
unchanged. The PM's p7c probe was a no-op (its replace string is not in the
base brief); vii-c is covered by its own test, red on 66e1fa1.
M2: /trekbrief --approve takes <project-dir | brief-file>. New
intent-approval.mjs --resolve decides: a directory → <dir>/brief.md and
/trekplan --project; a file → itself and /trekplan --brief. Phase 4h and the
stamp line use {BRIEF_PATH}; /trekplan's halt table names
/trekbrief --approve {brief_path}, which works on both brief modes, and so
does the gate's hint. HANDOVER-CONTRACTS' "open to every producer's brief"
is now true. Chose fixing the path over rewording the contract because two
real briefs (docs/*-brief.md) had no approval path at all.
Red ff760ed 9/29 → green 29/29. Suite 1219: 1217 pass / 0 fail / 2 skip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New lib/stats/stats-append.mjs: one record on stdin, appended to
<data dir>/<kind>-stats.jsonl. The data dir is CLAUDE_PLUGIN_DATA, else
~/.claude/plugins/data/voyage-ktg-plugin-marketplace (the yardstick's
default). A failed write exits 1 with a reason: reported, never silent.
/trekbrief Phase 7 and /trekplan Phase 12 now run it instead of
"append to ${CLAUDE_PLUGIN_DATA}/…; skip silently". intent-approval's
resolveApprovalDataDir delegates to the same resolver.
Chose a stdin heredoc over a --json argument because a JSON record in a
shell argument breaks on quotes in task text. Only trekbrief and trekplan
are rewired (økt 2's countable form needs exactly those two); the other
commands' stats prose is unchanged and docs/architecture.md says so.
Red a358059 7/7 → green 7/7. Suite 1208: 1206 pass / 0 fail / 2 skip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Veikart steg 1, økt 1 av 2. The three holes measured in the grounds:
(1) ## Intent / ## Goal were only checked for existence, (2) no approval
marker existed, (3) brief-approved was emitted only on the auto path.
- lib/validators/intent-approval.mjs: --check / --stamp. The marker is
intent_approved_hash (sha256 over normalized ## Intent + ## Goal) +
intent_approved_at. Editing either section after approval → STALE.
- /trekplan Phase 1 (Read the brief, both --brief and --project): runs
--check and HALTS on BRIEF_INTENT_NOT_APPROVED / _STALE / _INVALID with
the remedy spelled out; an unrunnable check halts too.
- /trekbrief Phase 4h (before the Phase 5 fork, asked even in --quick):
shows Intent + Goal verbatim, AskUserQuestion Approve / Revise / Leave;
only "Approve" runs --stamp. --stamp emits brief-approved, so the manual
(default) path records it; the auto path's own emission is removed.
New mode /trekbrief --approve <project-dir> = Phase 4h alone.
- README, CLAUDE.md, command-modes, HANDOVER-CONTRACTS §Handover 1,
jsonl-schemas (trekbrief-stats gains intent_approved).
Valgt ingen brief_version-bump fordi skjemaendringen er rent additiv (to
valgfrie felt) og kravet sitter i /trekplan — enhver produsents brief kan
godkjennes via /trekbrief --approve uten produsentendring. Valgt eget
--check-kall i stedet for et flagg på brief-validator fordi --brief-stien
i dag ikke kjører validatoren i det hele tatt; et nytt validatorkall der
ville også stoppe på andre feil. Valgt fallback-datamappe = målestokkens
(plugins/data/voyage-…) fordi CLAUDE_PLUGIN_DATA er tom i Bash-miljøet og
event-emits egen fallback er stille skip — slik ble brief-approved 0 records.
What the marker does NOT prove (module header, command prose, contract):
same user, same machine — any session can stamp. A trace, not a signature.
Suite 1183 → 1201 (1199/0/2). Mutants M1–M5 (stale check off, check
always valid, gate line removed, stamp emits nothing, no normalization)
each fell ≥ 1 test. yardstick unchanged: RED, 1 of 3 countable.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured 2026-09-18: nine ordinary shapes of a plan's `## Verification`
section parsed to zero criteria - an untagged fence, a ```text fence, a
markdown table, `## Verification (acceptance)`, `## Verification:`,
`### Verification`, an unclosed fence earlier in the document. Every one came
out as `0 of 0`, NOT OK, exit 1, and Phase 7 then forbade `result: completed`
without anyone being told that the FORMAT, not the code, was the problem.
"The section is empty" and "I cannot read this format" are different facts.
Three changes, one hole:
- The runner reports `NO_CRITERIA` with a source line (`plan.md:NN`) when the
section is there and nothing in it parsed, and names the two forms it does
read. Same for a brief's `## Success Criteria`, so the evidence block the
conformance reviewer gets says which of the two it is looking at rather than
showing an empty table.
- Phase 7 says it out loud instead of failing silently: report the source line
and the two forms, and say that the plan is what failed there, not the run.
- `/trekplan` now pins what it produces to what the runner reads: the heading
is exactly `## Verification`, the criteria are a bullet whose first
backticked span is the command or a shell-tagged fence, and the command must
be one the allowlist runs. A doc-consistency test holds the writer and the
reader together, so a runner that learns a new form must update the source.
Honest about the round trip: the two round-trip tests were GREEN on arrival -
the template already writes the bullet form the runner reads. What was missing
was not the format but the PIN: `/trekplan` mandated neither the heading string
nor the format, so a plan could satisfy the command's own instructions and
still parse to nothing. The tests now hold that.
Red first: 5 of the 7 new tests failed before the change (3 NO_CRITERIA, 2
doc-consistency); the 2 round-trip tests are guards, and said so above.
Suite 1161 (1159/0/2). Gate unchanged: defects 0 of 7, intact, exit 1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude Code 2.1.233 stopped offering the task/todo tools on Opus 4.8, Sonnet 5, Fable 5
and newer unless CLAUDE_CODE_ENABLE_TODO_TOOLS=1 is set. /trekplan still listed
TaskCreate and TaskUpdate in allowed-tools. So did the two orchestrator reference docs,
which mirror the command but are never spawned. No prose in any command calls either tool.
Runtime effect, measured BEFORE removal on CC 2.1.274, claude-opus-5, with
CLAUDE_CODE_ENABLE_TODO_TOOLS unset:
- Probe: a throwaway project command whose frontmatter is
`allowed-tools: Read, TaskCreate, TaskUpdate`, run headless
(`claude -p --output-format stream-json --verbose`).
- The session had 151 tools. The only Task* names among them were Task, TaskOutput and
TaskStop; neither TaskCreate nor TaskUpdate was there.
- The command loaded (listed in slash_commands) and completed with subtype=success,
is_error=false and 0 tool calls. The model reported the tool as not available.
- `claude plugin validate` does not flag the unknown names either: only the one
accepted warning appears, before and after.
Verdict: harmless dead weight, no error anywhere, so this is a correctness-of-docs fix
rather than a runtime fix.
End-state gate D-05: open -> closed (defects 5 -> 4 of 7). Suite 1059 (1057/0/2), run
on a clean export of the index.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude Code 2.1.178 removed the TeamCreate and TeamDelete tools, so /trekplan's
"execute with team" handoff could never create a team: it always ended in its own
fallback (sequential execution). The path is removed and the fallback is now the only
behaviour. The handoff no longer offers "execute with team"; if a user asks for it
anyway, /trekplan says there is no team path and executes sequentially. Parallel
implementation stays where it already was: --decompose plus /trekexecute's
multi-session waves. No new orchestration replaces it.
- commands/trekplan.md: TeamCreate/TeamDelete removed from allowed-tools; the offered
option and the team section are gone.
- agents/planning-orchestrator.md (reference doc): the offered option is gone.
- docs/cc-upgrade-2.1.181-decision-matrix.md still names the team path: a historical
record, left as written.
End-state gate D-01: open -> closed (defects 7 -> 6 of 7). Suite 1059 (1057/0/2), run
on a clean export of the index.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gemini-bridge is dropped by operator directive (three repetitions). The drop is
permanent, not a wait-for-SDK-upgrade state, so the change clears every LIVE
surface that could still steer a run toward the agent and leaves the historical
record alone.
Live surfaces cleared: agents/gemini-bridge.md deleted; trekresearch (bridge
launch block, --local help, high-effort always-on pair, stats record,
degradation list), trekplan, trekbrief, research-orchestrator (mode table,
agent table, prompting block, summary line), README (feature prose, mode table,
agent prose, mermaid EXTERNAL node, conditional legend, optional-MCP
requirement, --local section), CLAUDE.md, settings.json (the whole
trekresearch.geminiBridge block), both templates, architecture.md,
command-modes.md.
trekplan high-effort Adversarial Pass 2 now degrades EXPLICITLY: it emits its
section with status "unavailable, skipped" instead of failing or vanishing. A
high-effort plan carrying no Pass 2 marker is indistinguishable from one whose
Pass 2 crashed, which is the failure mode this wording exists to prevent.
gemini_used is deliberately KEPT as a vestigial trekresearch stats field pinned
to false. Removing it would break the observability export schema for existing
consumers, and the directive was about the agent, not the field.
Not touched: CHANGELOG history and the measurement/decision docs keep their
gemini references. They record what a past version did or what was measured
then; rewriting them is the same defect class as bumping a version string
inside a measurement doc.
Driven test-first. Five new pins in tests/lib/doc-consistency.test.mjs, verified
RED before the edits, including a KNOWN-POSITIVE CONTROL asserting the
historical records still DO carry gemini references — so the empty result on
live surfaces is a measurement and not a broken query (Verifiseringsloven
ansikt 4). Agent inventory 24 -> 23 (20 spawnable + 3 orchestrator reference
docs); the <example>-block floor moves 34 -> 32 because an agent legitimately
left the inventory, not because examples went missing from a surviving one.
Docs: docs/T1-cc26-delegated-orchestration.md §8 item 3 claimed both the §6
synthesis-agent PoC and the §5 bake-off were "designed but unbuilt". That was
written in S7 and falsified the same afternoon by S12, which ran the §6 PoC and
recorded Δ main-context (faithful flow) = 0.0%, NEGATIVE. The stale wording is
what caused the settled PoC to be re-ordered as new work on 2026-09-02, so it is
struck rather than deleted and §6 gained a RUN AND DECLINED status block. The
finding is structural, not stochastic: Phase 5 spawns the exploration swarm
foreground (trekplan.md:158,338-341), so the outputs are already resident in
main before Phase 7 — delegating only the Phase-7 digest evicts nothing.
Also measured 2026-09-03 (CC 2.1.259): claude -p --output-format stream-json
runs on subscription auth with no ANTHROPIC_API_KEY and now emits a
subagent_stats block, so S12's environment-block premise is half stale. Recorded
in §8 item 4. It lowers the cost of §5; it changes nothing about §6.
Suite 1041 (1039/0/2), up from 1036 by exactly the five tests added.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
akashic-intelligence lost /trekplan Phase 9 twice to reviewer agents that
never returned. Reproduced here and measured: the cause is the Agent tool's
`name` parameter, not the agent definitions.
Passing `name` does not label a subagent - it changes its kind. The spawn is
recorded as taskKind "in_process_teammate" (spawnDepth 0) instead of a real
subagent (spawnDepth 1). A teammate's final assistant text is not a return
value; it reaches the parent only if the teammate itself calls
SendMessage(to: "main"). plan-critic and scope-guardian declare
tools: [Read, Glob, Grep] - no SendMessage - so as teammates they are
structurally incapable of returning, whatever the prompt says.
Denominators: named 0/5 returned; named + explicit SendMessage 1/1; unnamed
3/3 (plan-critic and scope-guardian each returned full findings + the JSON
block in ~110s). Model override 2/2 non-returning, so the override is not
the variable. All 5 named agents produced correct final text in their
transcripts - only delivery failed, and that output is recoverable on disk.
The defect is a harness behaviour, so it is documented rather than silently
worked around: docs/agent-return-channel-defect.md carries the mechanism,
every denominator, the two broken queries that nearly became facts, the
unmeasured cells, and a recommended working shape for consumers (use agents,
drop `name`; do not fall back to inline review, which costs the dedup step).
Prevention is pinned, TDD red->green: the four spawning commands each state
the rule and name the mechanism, and doc-consistency derives the spawning set
from the command files so the pin cannot go vacuous.
Suite 1013 (1011/0/2), +5 from baseline 1008.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014MfB5Ecp8vvGyou8uFGxBV
Drop the pr/issue/markdown variants from `/trekplan --export`. Claude Code
reformats a plan into a PR body, issue comment, or stripped markdown ad-hoc
on request, so a dedicated export path added maintenance without value.
Keep `--export headless` as a backwards-compatible alias for `--decompose`
and relabel it as the decomposition entry it actually is.
- commands/trekplan.md: Phase 1 parse rejects non-headless formats and sets
mode = decompose for headless; delete the Export phase; rename Phase 1.6 →
Phase 1.5 (Decompose); update the mode enum, argument-hint, and usage block.
- docs/command-modes.md, README.md: export row relabeled as a --decompose alias.
- tests/commands/trekplan.test.mjs: +2 V15 pins (variants gone, headless kept).
Non-breaking (plan D-register). Tests 731 (729 pass / 2 skip / 0 fail), bar
`node --test`; `claude plugin validate` green (1 accepted warning).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
Phase 9's dedup hand-off was broken on two layers, both surfaced by the S22
dogfood: (a) plan-critic + scope-guardian (Read/Glob/Grep, no Write) were told
to write /tmp/*-out.json the dedup helper reads — they cannot; (b) even with
Write, their Output format emits markdown, not the helper's
{agent,findings:[{file,line,rule_key,text}]} schema. readJsonOrNull then
swallowed the absent files -> a silent empty merge that discarded every finding.
Fix (operator-chosen A'): keep the reviewers read-only; make the hand-off run.
- plan-review-dedup.mjs gains a --stdin mode reading {plan_critic,scope_guardian};
malformed stdin exits non-zero so a broken hand-off surfaces loudly instead of
collapsing into a silent empty merge. File mode + its tests are untouched.
- plan-critic.md + scope-guardian.md now emit a trailing machine-readable `json`
findings block (the inline hand-off; no Write tool needed).
- trekplan.md + planning-orchestrator.md Phase 9 rewritten in lockstep: extract
both blocks, pipe via heredoc into --stdin. No temp files, portable, no
pathguard dependency.
TDD: malformed-stdin test failed first (CLI ignored stdin -> exit 0 = the bug),
green after impl. New S23 doc-pin asserts both docs use --stdin (not the dead
/tmp paths) and both agents declare the json block. Suite 724 (722/2/0); live
HEAD baseline was 720, not the stale 705 STATE carried forward.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
Closes devils-advocate audit #4–#6 (MAJOR×MED). Four additive, non-breaking
changes to the v5.5 framing-alignment machinery:
1. --min-brief-version <ver> gate (audit #4). Opt-in version floor on
/trekplan + /trekresearch, forwarded to brief-validator as --min-version.
New opts.minBriefVersion warns BRIEF_VERSION_BELOW_MINIMUM (never blocks)
when a brief declares a version below the floor; trekreview exempt; absent
opt = no check. CLI shim parses --min-version and skips its value token in
filePath detection.
2. memory_alignment.status field (audit #5). brief-reviewer now emits
status: verified | n_a | contradictions so a score-5 N/A (no memory) is
distinguishable from a score-5 verified-aligned brief — the score≥4 gate
passes in both, status reveals whether the wrong-premise defense ran.
3. Document pre-2.2 = zero framing enforcement (audit #4). HANDOVER-CONTRACTS
§Handover 1 now states the producer-elective hole + two remedies. Also
fixes a stale "current is 2.1" line (current is 2.2).
4. Soften flagship overselling (audit #6). CLAUDE.md Context-Engineering
principle now hedges that main-context relief is asserted-by-design, not
measured (T1 PoC found Δ≈0); README carried no false claim to fix.
TDD: 8 new tests written failing-first (5 validator, 1 trekbrief status pin,
2 doc-consistency cross-file pins). Suite 691→699 (697 pass / 2 skip / 0 fail).
No flagship prose-pin added (deliberate, per S19 anti-bloat).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
Truth-pass over the README/CLAUDE/contract docs the S14 audit flagged as
stale (findings #2/#6/#7/#8/#9). Re-grepped every count against the actual
files first — line numbers in the audit are S14 snapshots that had already
rotted. docs + tests only; lib/ runtime and all behaviour untouched.
Corrections:
- README architecture block: 23 → 24 agents; 5 → 7 hooks (add the two it
omitted: post-compact-flush, otel-export); dropped the rotting test-count
("109" — already wrong twice, 109→683→686) for "comprehensive node:test
suite" so the number can never drift again (operator choice).
- brief-reviewer five → six dimensions (+ memory alignment); plan-critic
9 → 10 dimensions (README ×2 + CLAUDE.md), matching the agent's 10 numbered
dims and the v5.5 flagship 6th brief dimension.
- phantom "v5.4" contract-freeze references → v5.5.0 (CLAUDE.md + HANDOVER-
CONTRACTS ×3). v5.2–5.4 never shipped; the formalization landed with 2.2 in
v5.5.0 (CHANGELOG:9), so line 46 got a prose tweak (one release both
established 2.1 and evolved it to 2.2). CHANGELOG history left intact — it
correctly explains the phantom.
- trekplan Phase-8 inline-sealing rationale "Opus 4.7" → 4.8.
- bonus (operator-approved): end-session helper name trekplan-end-session →
trekendsession (the actual command).
New doc-consistency pins (TDD red→green): README agent-count and hook-count
(file counts), plan-critic dim-count (computed from ### N. headers),
brief-reviewer dim-count (cross-file, excludes agent-list lines that
co-mention plan-critic's count). Updated the existing pin that guarded the
phantom "v5.4 froze 2.1" string to the corrected wording + a !/v5.4/ guard.
Version-string pins (Opus 4.8 / v5.5.0) deliberately omitted as S19 prose-bloat.
Tests 686 → 690 (688 pass / 2 skip / 0 fail). claude plugin validate passes
(1 accepted CLAUDE.md-at-root warning).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
8 sites across 3 orchestrator agents + trekbrief/trekplan/trekresearch asserted 'the harness does not expose the Agent tool to sub-agents' as present fact -- the rationale for the v2.4.0 inline migration. CC 2.1.172 (verified) lets sub-agents spawn sub-agents up to 5 levels deep, so the claim is false. Replaced each with verified history (pre-2.1.172) + current fact + forward pointer to the decision matrix (W1/CC-26). Decision-neutral: states fact without pre-empting the orchestration redesign. CHANGELOG history left untouched. Tests 578/0/2; claude plugin validate passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
Flip model: sonnet → model: opus across 20 agent files, 4 prose references
in commands (trekplan, trekresearch), trekendsession command frontmatter,
and CLAUDE.md tables. Aligns CLAUDE.md premium-profile row to actual
premium.yaml content (all-opus, which has been the case since v4.1.0 but
the doc was drift). Companion to VOYAGE_PROFILE=premium env-var (set in
~/.zshenv same day) — env-var governs orchestrator phase model; this
commit governs sub-agent models which are frontmatter-pinned and not
reachable by the profile resolver.
npm test: 516 pass, 0 fail, 2 skipped (unchanged from baseline).
Operator rationale: complete Opus coverage across all Voyage activity,
including the 20 sub-agents that the profile system does not control
(architecture-mapper, task-finder, plan-critic, scope-guardian,
brief-reviewer, code-correctness-reviewer, brief-conformance-reviewer,
review-coordinator, session-decomposer, plus the 6 researcher agents,
plus the 5 codebase-analysis agents).
Cost implication: sub-agent runs ~5x more expensive vs sonnet. Accepted.
v5.0.0 added a read-only HTML render. v5.0.1 deleted that and pointed at
/playground document-critique, which pre-generates Claude's suggestions
and asks the operator to approve/reject them. The operator asked for the
opposite — a surface where THEY drive every annotation. v5.0.2 lands it.
scripts/annotate.mjs (~430 lines, zero deps) takes any artifact .md and
writes a self-contained HTML next to it. The HTML renders the document
with line numbers, lets the operator click any line to add their own
note (inline textarea, save with Cmd+Enter or button), keeps a sidebar
of all notes (editable + deletable + persisted in localStorage per
artifact path), and exposes Copy Prompt to gather every note into one
structured prompt. Operator copies, pastes back, Claude revises the .md.
The three producing commands now run annotate.mjs at their last step and
print the file:// link with explicit "Click any line to add YOUR OWN note"
instructions. The v5.0.1 /playground document-critique line is gone.
npm test green: 516 tests, 514 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The v5.0.0 stop-gap had /trekbrief, /trekplan, and /trekreview each render
a read-only {artifact}.html (via scripts/render-artifact.mjs) AND print a
vague "run the /playground plugin" instruction. In practice the read-only
HTML was redundant with what /playground produces and the instruction
wasn't copy-paste-ready — the operator had to guess the right invocation.
v5.0.1 deletes scripts/render-artifact.mjs + its test + npm run render,
and makes each producing command end with a single boxed, literal,
copy-paste-ready line:
/playground build a document-critique playground for {artifact_path}
One paste from the operator launches the official playground skill's
document-critique template, which builds an interactive HTML — artifact
on the left, per-line Approve/Reject/Comment cards on the right, Copy
Prompt button at the bottom. Mark suggestions, click Copy Prompt, paste
back, Claude revises the .md. Doc-consistency test pins the literal
invocation so the prose cannot soften back into vagueness.
npm test green: 503 tests, 501 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The v4.2/v4.3 bespoke playground SPA (~388 KB), the /trekrevise command,
Handover 8 (annotation → revision), the supporting lib/ modules
(anchor-parser, annotation-digest, markdown-write, revision-guard), the
Playwright e2e suite, and the @playwright/test / @axe-core/playwright
devDeps are removed. A browser walkthrough found the playground borderline
unusable, and it duplicated the official /playground plugin's
document-critique / diff-review templates.
In their place: scripts/render-artifact.mjs — a small, zero-dependency
renderer that turns a brief/plan/review .md into a self-contained,
design-system-styled, zero-network .html (frontmatter folded into a
<details> block). /trekbrief, /trekplan, and /trekreview call it on their
last step and print the file:// link; to annotate, run /playground
(document-critique) on the .md and paste the generated prompt back.
Resolves the v4.3.1-deferred findings as moot (their target files are
deleted). npm test green: 509 tests, 507 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>