The coupling to Claude Code's built-in run skill (wave 4, order A2,
decisions 54 and 64). The plan's "run the thing" step, the executor's
End to end part 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, because run gives no exit code. The template quotes
the name instead of backticking it: every backticked span on a template
step bullet is read as a runnable example.
R2: lib/skills/routing.mjs keeps a short fixed list of Claude Code's own
skills a quiet case may name as owner (BUILTIN_OWNERS, only run, seen in
2.1.303). For such an owner only "not taken" is checked, and the report
says so; ROUTING_NEGATIVE_WON stands, and an owner on no list is still
ROUTING_UNKNOWN_OWNER. skill-writing-criteria-quiet-2 gets owner=run.
The trekplan.md paragraph is reflowed to its old line count so the stats
line_ref there does not move (order B edits the same file); the
trekexecute Phase 9 line_ref fixture moves by two lines.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- park-attempt-files: parks in the git dir (outside the work tree, so Sub-step C.2 never registers a parked file again), reads a path with a space, names a new file under a header it cannot read, parks a symlink, never overwrites a parked file, and exits 1 while a file the attempt made is still in the tree; the upward diff is saved in one form whatever the git config.
- brief-validator: BRIEF_SC_NOT_RUNNABLE only when a later backticked span is a command; a criterion that only names a flag or a path stays prose (Handover 1 says so now).
- review ids: counted over the final list (runContract), as fill-finding-ids counts review.md; trimmed_count matches rows by id; engine-findings and fidelity-diff use computeFindingIds; the --workflow dedup keeps one source's different findings apart, the decision-23 put-back stays one copy per triplet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The revert of a step sent back to the plan leaves its new files on disk, and --resume built the revised step on top of them: a stale tests/batch.sh holding the rejected line would have passed Verify, the manifest and the success criterion. lib/util/park-attempt-files.mjs moves every still-untracked file the attempt created (from step-N-upward.diff) into the report dir, never deleting it; /trekexecute runs it before the fresh build helper (voyage-lekerepo trial 5, finding 4).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decision 41's rerun is scoped to below plan_version 1.8 in the executor and Handover 4 (as the helper and the exit-2 row already say), the decision-30 sentence names the one exception, and the Fixed and Known-issues slicers share one subsection helper.
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 3 (v6.2.0..96cb977, BLOCK: 1 BLOCKER, 8 MAJOR, 2 MINOR), each fixed
behind a test that failed first.
- Every allowlisted runner, not only git, takes plain words and a short list
of options that only read: an option that writes a file or loads code
(--test-reporter-destination, --outputFile, --junitxml, --basetemp,
--import, --config, -p, -o, -exec, a reporter path) is on no list; after
`npm test --` only paths follow; `make test` takes no VAR=value. A built-in
node test reporter (tap, spec, dot, junit, lcov) stays allowed.
- /trekexecute: a restore the guard refuses (destructive git, in the mode
that shows no prompts) or the operator declines is never recorded as
reverted: simplify = "revert-refused" and the run stops before review; a
refused step revert is reported with its paths.
- stepTestsOnly: a fixture document under tests/ is a test file, "e.g." is
not a path, ./ is dropped; the plan-file sweep reads Files: with the same
reader (fieldPaths); the validator hands its parsed fields over.
- plan-validator --steps-from asks for Verify: on a 1.8 plan too.
- skill frontmatter: a value starting with # is a hazard; a quote after an
escaped backslash closes the value. Routing reads kind tags with hasOwn.
- release-check reads scope_sha_end as written (an all-digit sha keeps its
leading zero), and Voyage's own artifacts under .claude/projects/ and
.claude/voyage/ committed after the review do not count as unreviewed.
Suite 2170 (2168/0/2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 2 (v6.2.0..0d044f6, BLOCK: 2 BLOCKER, 11 MAJOR, 1 MINOR), each fixed
behind a test that failed first.
- The git runner checks only words /bin/sh passes through unchanged (no
quote, backslash, $, glob or brace) and refuses --output and its
abbreviations: round 1's --output refusal was bypassed by quoting.
- fieldPaths: backticked paths are kept as written, parentheses and all; in
plain text every path-like word counts, and a parenthesised note does not.
- plan-validator --steps-from reads the plan's ## Verification for an
appended End-to-end step, and warns instead of failing under --soft.
- regression-check prints progress_status, the value progress.json takes;
/trekexecute copies it.
- release-check: a plugin in a subdirectory is checked in its own directory,
the suite is not run when a cheaper check already makes the answer exit 2,
and a bad argument or a crash is exit 2.
- Skill routing looks a skill up among skills only, and builds the corpus
vectors once.
- /trekexecute Phase 7.2 says plainly that remediation steps in the review
template's own form stop with a re-plan; making them runnable is a later
order (operator 2026-10-10).
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>
Wave 2, order 6. /trekexecute now:
- refuses a plan whose logged approval does not cover its current sha256
(K2, approval-log verify --kind plan), before step 1;
- runs the step check (K9) and the step's optional Regression: (K10, new
lib/verification/regression-check.mjs through the criteria runner) at step
end, before the checkpoint; exit 2 is "not measured", never green;
- runs the architecture rules (K5) and the plan-file sweep (K6) after the last
step; a violation or a file outside the plan turns completed into partial;
- reviews by itself in the closing run (Phase 7.2): run the thing, /simplify,
/trekreview, verdict-gate; a BLOCK adds the review's remediation steps after
the plan validator accepts them and the operator re-approves the plan, capped
at TREKEXECUTE_MAX_REVIEW_ROUNDS (3);
- makes the main-merge gate a lock on the verdict: BLOCK or undecided keeps
the merge closed; when open, the executor merges and the guard's question is
the one question (operator decision 2026-10-08). The --gates pause before
the wave merge-back is gone for the same reason.
The guard refuses a merge into main and a push in the permission mode that
shows no prompts, since no one can be asked (operator decision 2026-10-09; two
mode-read exemptions approved by the operator).
progress.json gains optional coupling fields (Handover 5); the validator
rejects the runner's exitCode in plan_verification.failed_criteria (C15).
Pointer lines name the skills test-first and debugging (S2).
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>
The skills reading (2026-10-06) found two defects the operator decided to fix
once wave 1 was merged:
- the brief template's Success Criteria examples used a pipe and npx, which
the criteria runner refuses (and the brief validator now warns on);
- trekcontinue and trekexecute called lib/ scripts relative to the working
directory, which is the user's repo, not the plugin.
Tests fail on the old text first (tests/lib/reading-defects.test.mjs).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Independent read-only review of c56f852..2d29966 (2026-10-08), each defect
reproduced by the reviewer; each new test fails on that code.
- test-lock green ran ANY allowlisted command: `green --cmd "git status"`
marked a red step green and the stop guard let it stop. The lock now
stores the step's test command (`lock --cmd`); `green` runs only that
one (a different --cmd, or a lock without one, exits 2). trekexecute D1
calls `green` with no command, which also removes the quoting hazard.
- plan-gate --accept-open worked at round 1 and passed the gate; it now
refuses while rounds are left.
- findings-schema --repo-root swallowed a following flag, or took a root
that does not exist, and silently skipped the line check: exit 2.
- brief-review-stamp hashed only the body, so a changed `framing` or
`research_topics` stayed "current"; it now covers the reviewed
frontmatter too (only the post-review stamps are left out).
- red-proof red_kind read an assertion message naming SyntaxError as a
load error; the signatures are now specific.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voyage-lekerepo trial (2026-10-06) point 7, operator decision 2026-10-08
(«grønt merke på låsen»): the stop guard blocked Stop three times while the
executor waited for the controller, with the step's test already green.
- test-lock.mjs green --cmd "<Verify>" runs the step's test command (same
allowlist + denylist as done-line) and records green_at only on exit 0;
pending clears it; a new lock starts without it.
- stop-test-lock lets a green-marked lock stop; the write guard still
refuses the locked test files.
- trekexecute: D1 marks green after a PASS; each fix round marks pending.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voyage-lekerepo end-to-end trial (2026-10-06), report points 8, 10, 12, 15, 16:
- approval-log: «Approve (Recommended)» / «Godkjenn (anbefalt)» is the
approval it labels; the suffix never turns a hollow answer into a yes.
- trekexecute Phase 8: the state-file block imports atomic-write through
${CLAUDE_PLUGIN_ROOT}; a relative import only ran with cwd = plugin root
(the test runs the block from another directory).
- trekreview, trekresearch, trekcontinue: stats go through stats-append like
the other commands, and a failed write is reported, never skipped
silently (closes the open STATE finding for all three). The schema
fixture's stale line refs for these and trekplan are re-measured.
- annotate prints an absolute path, so file://{$ANNOT_HTML} is a live link.
- red-proof: `red_kind` = load-error | test-failure on a proven red.
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>
An independent review of abc3083 found 15 defects, the two worst verified
in scratch repos. Each fix started with a test that failed.
- Proof of red could be "proven" by the environment: a start point
unpacked with git archive had no node_modules and no .git, so any test
failed there. The start point is now a git clone --shared checked out at
start_sha, gitignored top-level entries are linked in, and a control run
(start point + the change) must pass, or the result is not-run.
- The Test first file was never committed (the template lists it apart
from Files:) and leaked into the next step's diff. The step's scope is
now Files: + test files, staged at the checkpoint.
- New files outside Files: were invisible to every check. Every untracked
file is registered with --intent-to-add; a revert unregisters them.
- The floor guard paired renames (foo.test.js -> .bak read as clean) and
missed skipIf and node's t.skip/t.todo; prose files no longer count as
stubs.
- Phase 7.5 audited from the last step's start_sha; it now uses the run's
session_start_sha.
- The done line is written after the checkpoint and checked with --commit.
- fix_rounds never passes 5; attempts are never reset; re-control keeps
the spec/quality verdicts and earlier floor-guard rulings; the closed
stop list maps every existing stop; failed vs stopped made consistent;
the controller's effort is said, not assumed.
Tests: 1470 (1468 pass, 0 fail, 2 skipped).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekexecute no longer builds steps itself. Each plan step is built by one
fresh helper (new agent step-implementer: opus, effort high, no Agent tool)
and judged by one controller (a general helper on opus) that reads the
diff from a recorded start_sha and gives two verdicts, spec and quality.
Fix rounds go up, maximum 5: three fixes by a fresh helper, then back to
the plan, then to the operator. No cheaper-model ladder.
Proof is a command, never the model's word:
- lib/verification/red-proof.mjs: the step's test must fail at the start
point and pass at the result (exit 0/1/2; 2 is never green). Reproduces
the 02243c6 red-first measurement (6 of 55) through the shim fixture.
- lib/verification/test-integrity.mjs: the floor guard on the diff
(removed asserts, skipped/deleted tests, muted checks, stubs, loosened
thresholds). Over the last 150 commits: 149 clean, 1 real finding.
- lib/verification/done-line.mjs: DONE step N only when the test command
exits 0.
Test first is required from plan_version 1.8. The test lock (K8) is used
through its CLI and reported as not-locked while it is missing. A run
stops only on a closed list of four classes; every other call goes into a
decision log with its cost if wrong. Without a passing run-the-thing
criterion the result is not verified end to end, never green.
Handover 5 gains optional per-step start_sha, report_path, red_proof,
test_lock, fix_rounds (0-5) and run-level decisions and end_to_end; old
progress files still validate and resume.
No isolation on the helper: measured, a worktree-isolated subagent
branches from the default branch (02f320f), not the executor's HEAD
(2c89a6b), so it would miss the earlier steps.
Borrowings credited in commands/trekexecute.md ## Credits (Superpowers,
ai-native-sdlc, Kiro, GitHub Spec Kit, agent-skills, Cherny).
Tests: 1411 -> 1457 (1455 pass, 0 fail, 2 skipped).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekreview of 5680591..84a0621 (verdict WARN: 0 BLOCKER, 3 MAJOR, 1 MINOR,
1 MAJOR suppressed as unverified for length only). All closed red -> green:
- Suppressed MAJOR 1d0171a7 (verified live): Phase 8 spliced {plan-path}
into a single-quoted --payload. A lone quote broke the shell parse (event
lost, no written:false to report); a quoted pair ran a command
substitution and still reported written:true. event-emit now reads
`--payload -` from stdin and the three Phase 8 blocks pass the payload
through a quoted heredoc. Checked under bash and zsh.
- 570ba19b: the SC5 set-step extractor read line by line and never saw the
wrapped Step 0 sentinel (`blocked`); it now matches across the break and
the test asserts `blocked` is read.
- c69a865a: the Phase 9 line_ref in jsonl-schemas.md was 9 lines off. Both
trekexecute rows are now pinned to the exact span by a test.
- 0004fa23 (MINOR): the gates_mode_flag_override block says what to do on
written:false (print the reason, continue).
- emit() docstring no longer says failures are swallowed silently.
- 7ffaede5: chosen to KEEP the prose-only legacy `passed` tolerance, because
a public-plugin run started under the 6.1.0 prose would otherwise re-run
every finished step on resume; recorded as an accepted deviation in the
(local-only) brief. No code change.
Suite 1400 (1398/0/2), was 1393.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The progress file /trekexecute's prose described did not pass the command's own validator: run status in-progress and no partial, no plan_version (required), step status running and passed. Measured on the 4 real progress files: 3 used passed, 2 failed on plan_version. The prose now speaks the validator's vocabulary, site by site: schema (plan_version = the value Phase 2 parsed; run status in_progress|completed|failed|stopped|partial), fresh-mode warning, both resume rules, step start in_progress, step finish completed, the escalation staging rule, the Phase 7.5 commit count (status=completed - left alone, every successful run would read as drift and be overridden to partial) and the final write (adds partial; a sandbox-blocked run writes stopped, report result blocked). Untouched on purpose: plan_verification.status, session-state / NEXT-SESSION-PROMPT status, stats and report result, the tolerant session-orders reader list, Phase 2.6's running state.
Valgt: tolerate a legacy passed on resume (one sentence after each resume rule) because Voyage is a public plugin and an in-flight run written under the old prose would otherwise re-execute finished steps. The validator gets no alias. Valgt: fresh mode also warns for stopped and partial - both are resumable, so they now get the --resume hint instead of a silent overwrite (intended behaviour change).
Red: 3 of 5 new tests fail on the pre-fix text - SC4 (documented progress file validates 0/0 per run status), SC5 (offenders at trekexecute.md 1011, 1055, 1062, 1164, 1169, 1326, 1352, 1489), the legacy-sentence count. Regression guard and known-positive control green on arrival.
Verify 125/125 (trekexecute-progress-schema, trekexecute, session-orders, criteria-runner, progress-validator). Suite 1388 (1386/0/2).
Voyage order 20261005T104513Z-1250514346, plan step 4/5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase 9 said 'append to ${CLAUDE_PLUGIN_DATA}/trekexecute-stats.jsonl; if it is not set, skip silently' - the Bash tool env never carries it. It now runs stats-append.mjs trekexecute with the record on stdin, the /trekbrief Phase 7 shape, and reports a written:false. The gates_mode_flag_override record was prose with no writer; it now has an event-emit block (fixed literal payload: --gates is a boolean flag) and a documented shape {ts, event, known_event, payload:{flag, signal_effort}}. Phase 8's three event blocks spliced ${PLAN_PATH} (set in an earlier Bash call that does not survive) and ${WAVE_COUNT} (never assigned) into a double-quoted payload, so a literal run printed payload-not-json, and the decline reason was operator free text in a shell argument. Payloads are now single-quoted with {plan-path} / {wave-count} placeholders and the literal label hold-for-review; each call runs on its own and a written:false is printed and passed. docs/architecture.md and the jsonl-schemas rows (writer, measured line_refs) follow.
Red: 7 of 7 new tests fail on the pre-fix text (Phase 9 writer + no 'skip silently', Phase 9 record lands, no bare ${CLAUDE_PLUGIN_DATA}/...jsonl target, no shell expansion in --payload, the three Phase 8 blocks land known events when run as written in a fresh shell, the written:false sentence, the override writer and shape).
Verify 198/198 (stats-landing, main-merge-gate, gates-flag-coverage, profile-stats-fields, plugin-root-resolution, doc-consistency, no-claude-code-launch). Suite 1383 (1381/0/2).
Voyage order 20261005T104513Z-1250514346, plan step 3/5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Check 4, Step 2a' and Step 5 start with
`[ -n "${ZSH_VERSION:-}" ] && setopt nonomatch`, so an unmatched
session-* glob stays literal under zsh as it does under bash and the
existing `[ -d "$wt" ] || continue` guard skips it. null_glob was not
used: it turns `ls -d .../session-*` into `ls -d`, which lists `.`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1. Step 6 cleared the orders dir before Phase 8's main-merge gate asked,
so a declined gate lost the merged-waves record and the next run
prepared wave 1 again on merged code. The clear now sits only under
the gate's "On confirm" (wave path, next-wave none, Step 4 passed);
Step 6 and a declined gate keep the record, so a re-run goes
next-wave none -> Step 4 -> back to the gate.
2. The gate's Decline row and Recovery surface now say what holds on the
wave path: the waves are already merged on the current branch,
nothing is finalized, the record is kept, and re-running the same
command (not --resume, which Phase 2.5 runs as a single session)
re-runs master verification and returns to the gate. The branch name
is trek/{slug}/session-N; the push-before-cleanup note now holds only
where the push succeeded. The single-session --resume line stays.
3. The report footer adds the multi-session way to continue.
4. wave.json stores the branch the wave was prepared on (write
--branch); Step 3's status call passes the current branch and stops,
touching nothing, when the main checkout is on another branch.
npm test: 1277 tests, 1275 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One invariant closes the data-loss class: Phase 2.55, 2.6 and 7.6 remove
worktrees only with `git worktree remove` without force and branches only
with `git branch -d`. Whatever git refuses (a worktree with changes, an
unmerged or checked-out branch) is kept, reported with what the user can
do, and never retried with force; every unmerged trek/{slug}/* branch
survives every failure path. Step 1 stops on a branch or worktree left
by an earlier attempt instead of deleting it. After a merged wave, a
progress file is dropped from its worktree only when untracked and
byte-identical to its archived copy, so the happy path still cleans up.
B1: Step 3 refuses to merge into a dirty main checkout, and tells a
refused merge (no MERGE_HEAD: stop, keep wave.json) from a real conflict
(abort, Step 5 keeps the branches).
B2: Phase 2.5, Check 4 and Step 0 take the main checkout from the first
`git worktree list` entry and refuse to run from a linked worktree.
B3: wave.json and merged-waves.json carry the plan's sha256 and refuse
another plan or version, naming the run that holds the orders dir and
the clear command; Step 0 stops on that. Step 6 clears the orders dir
when every wave is merged AND Step 4 passed, no longer keyed on the
Phase 8 label the wave path cannot reach.
Also: every session-orders.mjs call runs from the main checkout with a
main-relative plan path; Check 1 no longer counts .claude/trekplan-sessions/
as a dirty tree (it blocked every re-run after a failed wave); a stuck
wave has a documented non-force way out; Hard rule 12 states the
invariant. The test file only narrows one call-site filter that also
matched Step 0's plugin-root existence check.
npm test: 1273 tests, 1271 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude Code's positional-argument shorthand replaces $N in a command's
text; awk's $(0) is the same field without that collision.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven defects from an independent review of the 6.0 session-order flow,
all verified against the text before fixing:
1. Step 3 branched only on pending/failed/stopped/unreadable, so a session
still writing in-progress (or in_progress) next to a failed one had its
live worktree force-removed. status now classifies each session as
completed, running (no file, pending, in-progress, in_progress, or any
unknown status) or ended-bad (failed, stopped, partial, blocked,
unreadable), keeping the raw status; Step 3 stops on any running FIRST
and touches no worktree, branch or wave.json.
2. The Phase 2.5 wave-in-flight guard was cwd-relative; from a subdirectory
it missed wave.json and Check 4 force-removed the wave. The guard is now
anchored at the git toplevel, and Check 4 opens with a block that refuses
to clean while wave.json exists.
3. Step 6 read progress files from worktrees that Step 3/5 had removed. A
new archive subcommand copies each to orders/wave-W-session-N.progress.json
before any worktree goes; Step 6 and Phase 8 read the copies.
4. NO_WAVE always prepared the lowest wave, so a re-run after a wave-2
failure re-ran wave 1. record-merged writes orders/merged-waves.json
after each merged wave (Step 5 keeps it); next-wave returns the lowest
unmerged wave or none (then Step 4). Phase 8 clears the orders dir only
after a completed report; the record refuses another plan's path.
5. Phase 7.6 named a deleted worktree and promised an unwired re-run. The
order now names the main checkout and says the recovery session's own
audit is the check.
6. (test side, previous commit) progress paths are asserted literally.
7. Hard rule 12 now carries the awaiting-sessions exception.
npm test: 1262 tests, 1260 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>