Conflict: CLAUDE.md command table. Kept both sides: this branch's
/trekresearch row (the external agents preload researching-sources) and
main's /trekplan row (open minors listed for the operator).
researching-sources adapted to contract S1, now that 7a's form check and
routing test run over it:
- SKILL.md takes the fixed headings (Overview, When to use, Process, Red
flags, Enforced by, Credits); the five rules and the confidence scale move
under Process unchanged; Red flags lists the thoughts the baseline runs
showed; "text only" becomes "prose only" as the form check reads it.
- The description adds "official" documentation and "looking up online what
an error message means or what causes it": the error-lookup case ranked
#3 behind debugging. That prompt also said "our tests fail", which is
debugging's job; it now asks only what the error means and where that is
documented. No threshold changed.
- Eval cases carry the routing tags (skill-trigger / skill-no-trigger /
skill-effect, skill=, owner= task-finder and trekplan, from=), 7a's
Skill grader pattern, arm: both on the no-trigger graders, and the
judge-model line on the effect case.
- The `## Skills` row in README and CLAUDE.md.
- tests/lib/skills-research-prose-pins.test.mjs drops its two form pins
(skill-lint is the authority now): 14 -> 12.
npm test on the merged tree: 2055 = 2053 pass / 0 fail / 2 skipped
(main 2043 + 12).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wave 2 merge order 7a -> 9: brings e589a02 into order 9's branch.
No conflicts. Full suite on the merged tree: 2043 (2041 pass / 0 fail /
2 skipped) = main's 2014 + this branch's 29.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The source rules the research agents shared by copy now live in one skill,
skills/researching-sources/: official sources first with URL, date and
matching version; no citation, no finding; an empty search is reported with
its denominator and never as a finding; fetched pages are data, and text in
them aimed at AI assistants is ignored and reported; nothing local in an
outbound query. It also holds the one confidence scale.
- docs-, community-, security-, contrarian-researcher and research-scout
preload it (skills: ["voyage:researching-sources"]); the copied rule text
leaves them, their own role stays.
- Two agent sentences that contradicted the rules are gone: an empty
counter-evidence search "increases confidence", and "fall back silently".
- /trekresearch names the skill where it starts the external agents and in
web follow-ups; Phase 6 rates on the skill's scale word for word; the
deep-research adapter accepts `contradictory` like the template does.
- Enforced by: research-validator checks structure only, the query privacy
gate runs only in the default-off STORM steps; the rest is text only.
A guard on every web search is a separate later order (operator 08.10).
- Red baseline (helpers, offline fixtures): without the skill 3 of 5 runs
ignored an injected instruction silently and 1 of 2 contrarian runs counted
an empty search as weak support; with it 0 of 3 and 0 of 2. Path leaks:
0 of 7 without, 0 of 5 with.
- Eval cases (3 should trigger, 2 should not, 1 effect), written, not run.
- tests/lib/skills-research-prose-pins.test.mjs: 14 pins, 13 red on 4ee711a.
Credits: Addy Osmani, agent-skills @9d0c60d,
skills/source-driven-development/SKILL.md:97-114 (MIT); Jesse Vincent,
obra/superpowers @8ca22db, skills/diagnosing-superpowers/ (MIT). Ideas only.
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>
The workshop (ordre 7a, contracts S1 and S2): a form check
(lib/skills/skill-lint.mjs) that follows Claude Code's own skill fields,
and a model-free routing test (lib/skills/routing.mjs) over every skill,
the 7 commands and the 21 spawnable agents, reading the eval cases
themselves (evals/skill-*, 3 fire / 2 quiet / 1 effect, tagged with the
event they came from). Thresholds pinned, never lowered.
The two skills were written against failures measured first in helpers
without them: red only as an import crash, the whole suite run from a
hand-made file list instead of the repo's own command, and an
unreproduced fix shipped under authority pressure. step-implementer
preloads both through its skills: line; no tool list change.
Credits: addyosmani/agent-skills @9d0c60d, obra/superpowers @8ca22db,
mattpocock/skills @c55ee46 (MIT), Anthropic skill-creator (Apache-2.0).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The pre-compact hook read only a checkpoint that started with `git commit`,
so every plan in the new `git add … && git commit` form rebuilt nothing, and
an empty match also skipped the session-state refresh. It now finds the
commit anywhere in the span and always refreshes; first test for the hook.
- A sub-bullet that carries its own command stays a criterion (folding it
left the command unrun); the shallowest bullet sets the base indent.
- Only a MINOR/SUGGESTION /code-review finding outside the range is released
from forbidding ALLOW: a MAJOR one may be a break cited at an unchanged
caller.
- `reuse` is an improvement category; the session-spec template stages too;
a negated bash 3.2 constraint, an env prefix and `bash -c` are handled.
- Stale comment, Declined-to-Judge wording and rule-key counts brought in line.
Tests fail on 7c11c2a first (9 of 24).
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 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 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 1, 5, 11:
- engine-findings: recommended_action is "Fix <file:line> so this no longer
happens: <failure scenario>", not "Resolve: <title>" (8 of 8 engine
findings were set aside as actionability:empty); the coordinator never
sets an engine finding aside for Actionability.
- findings-schema --repo-root: a cited line past the end of an existing
file is FINDING_LINE_OUT_OF_RANGE, so Phase 5's bounded re-ask fixes it
before the coordinator sees it. The reviewers' instruction said "the
actual line number from the diff"; it now says the file's own line,
never the patch's.
- fill-finding-ids.mjs: the coordinator (no shell) writes @@ID_<n>@@ and
trekreview Phase 7 computes them over (file, line, rule_key); an
unresolved placeholder or a wrong 40-hex id fails. The 4-field id with
`title` the docs named is gone; the code always used three.
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>
CLAUDE.md command table: each row from its owner (trekplan from order 3,
trekexecute from order 1, trekreview from order 5).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLAUDE.md: the review paragraph (order 5) and the guards paragraph
(order 4) are both kept (planned union line).
The launch gate went red on the merged tree: post-approval-log reads
the session's permission_mode, and its regression test feeds that value.
Both were untracked when the branch ran its suite, so the gate never saw
them there. Operator decision 2026-10-06: a counted exemption in a new
class (mode-read: 3 + 1 hits), and the binding-rule sentence in CLAUDE.md
names it. An extra hit in either file turns the gate red again (checked).
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>
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>
Wave-1 order 4 (P7, P12, the P9 test lock, the P3 plan-approval guard).
All command hooks; none runs a model.
- P12: pre-bash-executor answers permissionDecision "ask" before merge
into main, push, tag/publish and destructive git (holds in auto mode).
post-approval-log writes exactly what the person was asked to the K2
approval log: merge/push to main as `merge`, tag/publish as `release`,
with a one-hour expiry; nothing when no person was asked.
- P3: pre-plan-gate runs the K3 plan gate on a Voyage plan leaving plan
mode and sends a refused plan back; "not measured" asks, never passes.
- P9: lib/util/test-lock.mjs (K8). pre-write-executor refuses edits to
locked test files; stop-test-lock refuses "done" for the locking
session (stop_hook_active guarded).
- P7: post-edit-check runs the target repo's own formatter/linter per
edit, only during a Voyage plan run or after opt-in
(.claude/voyage-guards.json); lib/verification/step-check.mjs (K9) fails
the step on findings; no tool reads "not measured", never green.
- STORM cap matcher also names `Agent` (the tool's name since 2.1.63).
- Mod precondition stated in README, SECURITY.md and every PreToolUse stop
guard: Voyage's guards are deterministic only when no installed mod
handles `tool.check`.
K2, K3 and K5 are stubbed in tests until orders 2 and 3 are merged.
Two independent review rounds; every finding has a regression test.
Suite 1600 (1598 pass / 0 fail / 2 skipped).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Operator decision 2026-10-06. Before, a WARN that existed only because a
reviewer or engine never reported (e.g. /security-review without an origin
remote) mapped to verdict-gate exit 0, so a review nobody performed in full
was green. Now `missing-reviewer:` / `unattributable-payload` in the JSON
block's allow_blocked_by is exit 2 (could not decide, never green); a WARN
for a MAJOR or a set-aside finding still passes with its reasons. A 1.1
review must carry allow_blocked_by.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An adversarial read of d88245c reproduced 15 problems; all fixed here, each
with a test that fails on the old code.
- verdict-gate: a greener verdict must be backed by the LAST fence being a
`json` block of the right shape, with no BLOCKER in the JSON (any case),
in `## Findings (BLOCKER)`, or a differing finding-id list; two verdict
lines and more than one file argument are exit 2. ({}, null, lowercase
"blocker", a trailing ```jsonc and a later json fence all gave exit 0.)
- engine-findings: a transcribed "narrower" key can no longer lower an
engine tier; absolute paths under --repo-root match the scope; "12" lines
parse; an empty scope is an error; out-of-scope engine findings are
unverified (`engine:out-of-scope`) and forbid ALLOW.
- recurrence: the catch-all engine keys and keys normalised from unknown
ones are never proposed; the same unfixed finding in two iterations is not
a recurrence; proposals are validated before they are offered; \r/U+2028
and damaged markers are refused; writes go through a symlinked CLAUDE.md.
Prose points --repo at the session directory, not the git toplevel.
- Workflow substrate: engines are counted from what arrived, and the
verdict's floor is recomputed from the coordinator's findings; now tested
by running the script with stubbed Workflow globals. Two literal NUL bytes
written as \u0000 (git saw the file as binary).
- Trimming keeps Pass 1's "Also flagged by" provenance; `## Declined to
Judge` and remediation steps are required from review_version 1.1 only
(N-1); the zero-diff review now carries the JSON block the gate needs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The no-shim variant only shows the load error at the start point; its result run repeated the shimmed one. --red-only skips it: the test goes from 29 s to 14 s run alone.
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>
Ordre 5 (wave 1, P11 + P5), review_version 1.1.
- K7: `verdict: ALLOW | WARN | BLOCK` is required in review.md (strict
error, soft warning for 1.0 reviews). New CLI lib/review/verdict-gate.mjs:
0 = ALLOW/WARN, 1 = BLOCK, 2 = could not decide (never green); a verdict
greener than the file's own BLOCKERs or JSON block is exit 2. Realpath
main guard (the old file:// guard exits 0 under a symlink - measured).
- No finding is struck for length: succinctness trims only MINOR/SUGGESTION
text (catalogue tier), keeps BLOCKER/MAJOR whole, counts trims; the
coordinator lists what it declined to judge.
- Claude Code's /code-review and /security-review run as the engine via the
Skill tool (never --fix/--comment/--post/ultra); lib/review/engine-findings.mjs
turns their findings into a reviewer payload; two catalogue keys
(CODE_REVIEW_DEFECT, SECURITY_REVIEW_VULNERABILITY), catalogue 12 -> 14.
An engine that did not run forbids ALLOW.
- Every BLOCKER is written as a numbered `### Step R<n>` with its source
finding (strict error REVIEW_MISSING_REMEDIATION_STEP).
- P5: lib/review/recurrence.mjs - a finding class in two review.md files
(current + git history, no new store) becomes one proposal, routed by the
catalogue's memory_route; written only between Voyage markers in
.claude/rules/voyage-review-lessons.md under a size budget, CLAUDE.md gets
a pointer only; the operator approves every line (Phase 8.7).
- Workflow substrate: catalogue enum in step; a missing reviewer or engine
forbids ALLOW there too (it returned ALLOW on zero findings before).
- Fixtures review-run-A/B said WARN over a BLOCKER; now BLOCK.
Borrowed and credited in code: Superpowers (declined-to-judge), ai-native-sdlc
(cap only nits; mistake/fix/check), Spec Kit (managed block; converge steps),
Pocock (retro routing), Kiro (verdict file + gate; evidence per lesson),
Cherny (engine -> brief control order; review -> memory; budget).
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>
hooks.json wired pre-write-executor.mjs to the Write tool only, so Edit and
NotebookEdit reached .git/hooks/, .env, shell configs and the other protected
paths unguarded. The matcher is now Write|Edit|NotebookEdit.
The guard reads the target path per tool: file_path for Write and Edit (hooks
reference, PreToolUse tool_input tables), notebook_path for NotebookEdit (the
tool's input schema). When it cannot read a path (unparseable input, unknown
tool, missing field) it now blocks instead of allowing.
New tests resolve hooks.json with Claude Code's matcher semantics and run the
hooks that would fire per tool: 9 failed on the old code, all pass now. The two
fail-open pins in path-guard.test.mjs are flipped to fail closed.
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>
Operator rule (2026-10-05): standard is Opus 5.5 at reasoning effort High. Four retrieval agents (architecture-mapper, dependency-tracer, git-historian, task-finder) pinned effort: medium in frontmatter, which overrides the session level, so every /trekplan exploration ran part of its swarm below the floor. They came from fdd3ad8 on the premise that unpinned agents inherit high; e4e37f9 corrected that (unpinned inherits the session; Opus 5.5 defaults to medium), so the reason for medium was already gone. All four now pin high; the other agents keep following the session (operator's choice). docs/profiles.md (one bullet for the eight pinned agents), CLAUDE.md and README.md updated; the model-default sentence stays. Dated decision records and CHANGELOG untouched.
Red: 4 of 5 new tests fail on the pre-fix files - effort floor over all agents (offenders: the four), the four pin exactly high, no live doc says retrieval runs at medium (hits docs/profiles.md:76, CLAUDE.md:85, README.md:806), profiles.md names the four as high. Known-positive control green on arrival.
Verify 153/153 (agent-frontmatter, doc-consistency). SC9 probe: npm test green under a scratch HOME with CLAUDE_PLUGIN_DATA empty, nothing under its plugin data dir. Suite 1393 (1391/0/2).
The change is repo-true, not installed-true, until a release.
Voyage order 20261005T104513Z-1250514346, plan step 5/5.
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>
event-emit returned {written:false, reason:'CLAUDE_PLUGIN_DATA unset'} whenever the harness did not export the variable - the normal case for the Bash tool - so /trekexecute's Phase 8 events never landed. It now resolves the directory through stats-append's resolveStatsDir (one resolver; opts.path still wins, so intent-approval is unchanged). The CLI uses the realpath isMain() guard (the file:// guard was a silent no-op under a symlink or a path with a space) and exits 1 on every written:false - usage error, payload-not-json, failed write - instead of always 0. KNOWN_EVENTS gains main-merge-approved, main-merge-declined and gates_mode_flag_override, which /trekexecute emits by design. Header, intent-approval docstring (comment only), docs/operations.md and the README autonomy sentence (wrong state names, 'records each transition') updated.
Red: 10 of 20 tests fail on the pre-fix code - 7 new (CLI lands with CLAUDE_PLUGIN_DATA empty / absent, unwritable target exit 1, usage error exit 1, symlink, space path, known events) and 3 inverted contracts. Regression guards (green on arrival): never throws when unwritable; no second copy of the fallback directory name.
Inverted (the contract this changes, not deleted): emit with no CLAUDE_PLUGIN_DATA (silent skip) -> lands under a pinned HOME; never throws when unwritable -> a genuinely unwritable target (env {} now resolves to the real home); resolveStatsPath({}) === null -> the fallback path; malformed --payload exit 0 -> exit 1.
Readers checked: otel-export keys on 'event', yardstick counts only user_input, cache-analyzer and research-loop-cap name event-emit only in comments. Verify 268/268 (stats-event-emit, intent-approval, doc-consistency, otel-export-validators, yardstick). Suite 1376 (1374/0/2); non-hook lines in the real trekexecute-stats.jsonl 60 before and after.
Voyage order 20261005T104513Z-1250514346, plan step 2/5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekexecute writes run status stopped (dirty-tree stop, entry-condition stop, escalation) and step status blocked (Step 0 sandbox sentinel); the validator rejected the first and warned on the second. Both are real states lib/util/session-orders.mjs already reads (ENDED_BAD), so the validator learns them. The step-status list is exported as PROGRESS_STEP_STATUSES (was an inline literal) so tests check prose against it instead of keeping a copy. docs/HANDOVER-CONTRACTS.md Handover 5 rows updated.
Red: 3 of 4 new tests fail on the pre-fix code (stopped run status, PROGRESS_STEP_STATUSES export, blocked step status). Regression guard (green on arrival): every run status but completed stays resumable.
progress-validator 16/16. Suite 1368 (1366/0/2).
Voyage order 20261005T104513Z-1250514346, plan step 1/5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekreview of e7ac34b..3f073b7 (WARN, 1 MAJOR, finding
986c939f93808a274b5e4ecd2c5318fd422a3be4): baseDir's accepting branch
was never exercised, though every production /trekbrief record carries
project_dir. One unit test (attributeOrder from a non-git parent with
projectDir inside it) and one end-to-end landing test (the Phase 7 line
with a record carrying project_dir).
Both pass on HEAD and both fail on the always-cwd mutant (measured,
then reverted). Suite 1364 (1362/0/2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekbrief Phase 7 says the writer adds order_id / order_claimed_at /
order_reason (never typed by the model) and that the yardstick joins use on
order_id; the fixture row lists them in `fields`, EXPORT_DENYLIST names them,
and its stale line_ref (657-672) now reads 961-976; the allowlist header
names them as dropped; docs/architecture.md Stats explains them.
/trekbrief --approve now runs Phase 7 after a successful stamp, with fixed
values (mode "approve", 0 turns, brief_quality/research_topics/auto_research
from the brief's frontmatter, auto_result "manual", intent_approved true).
Valgt fordi PM 04.10 (point 3): fix the code, not the criterion - the
approval must leave the trekbrief record. Measured hole: okf-wiki v1-k has
brief-approved 04.10 17:12Z and trekplan 17:29Z, but only a 03.10 trekbrief
record with intent_approved false. CLAUDE.md, README.md and
docs/command-modes.md say so. The manual path is unchanged.
npm test 1309 -> 1362 (1360 pass / 0 fail / 2 skip).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
order_id / order_claimed_at / order_reason on the five surfaces: (1) record
format = the writer (pinned in stats-landing), (2) Phase 7 prose with "the
writer adds", (3) the field-allowlist header names them as dropped and
TREKBRIEF_ALLOWED leaves them out, (4) the trekbrief-stats fixture row's
`fields` column + EXPORT_DENYLIST, (5) docs/architecture.md Stats. Plus: the
row's line_ref must contain the Phase 7 stats-append line (it said 657-672,
the line is at 958); /trekbrief --approve reaches Phase 7 with mode "approve"
(PM 04.10, point 3) and CLAUDE.md, README.md, docs/command-modes.md say so.
Red: 7 doc pins fail. Green on arrival: the yardstick-header pin (Step 6
already rewrote the header) and the otel DROP guard (the fields were never
allowlisted).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
measureUse({ queue, runs, cutoff, countingSince }): runs come from
orderRuns(stats) - trekbrief-stats.jsonl only. YES = a trekbrief record names
the order's id under one slug that names no other order; declared NO = a
new-work order carrying <!-- arbeidsform: ordre --> on its own line; no
record or a disputed record = NOT MEASURED, never a no (PM 04.10, point 1).
countingSince null -> NOT COUNTABLE, every order not measured; the window
starts at the latest of cutoff, MARKER_SINCE and the counting start.
facts.ordersNamedByARecord is the known-positive diagnostic (SC8).
Existing use tests get countingSince = MARKER_SINCE (their window unchanged)
and records instead of slugs; their denominators now read YES + declared NO.
Replaced: "a new-work order without a slug leaves the numerator NOT
MEASURED" - the slug join it guarded is gone. New exports are read through a
namespace import, so the trust/interrupts/mutants tests still run.
Red: 24 of 43 fail (every use test, the two measureAll tests, the symlink
CLI test); 19 pass, none of them new.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
stats-landing gains a baseEnv() (process.env minus CLAUDE_COORD_DIR) at every
spawn - the real voyage mailbox holds a claimed order while the suite runs -
and runLine takes a cwd and extra env. New: Phase 7's own line, run in a temp
git repo against a temp coord dir, must land order_id / order_claimed_at /
order_reason (one claimed -> the id; zero -> keys present, null, none-claimed;
two -> several-claimed:2; model-supplied order_* keys replaced; no coord ->
coord-missing). The CLI must also write when run through a symlink or from a
path with a space.
Red on behaviour: 7 of 8 new tests fail against today's writer (no order keys;
the file:// guard is a silent no-op under a symlink and under a space -
measured in a scratch repro 04.10). Guard green on arrival: a trekplan record
gains no order keys.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
20 tests for lib/stats/claimed-order.mjs (new): exactly one claimed order is
an attribution (stem id + the .claim sidecar's claimed-at); zero, several
(an unparseable file still counts), a to: naming another repo, a missing
coord dir or no git repo is null plus a reason - never a guess. Mailboxes
mirror coord-order-claim.sh (basename of the toplevel) plus the worktree's
main repo; _* is reserved; an inherited GIT_DIR and a project_dir outside
cwd cannot steer it.
Red: the module does not exist (20 of 20 fail, each on its own - the module
is loaded per test). Against a null stub in a scratch copy, 18 fail on
behaviour; 2 are guards green on arrival (13 _-prefixed mailbox never read,
14 the recorder only reads).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured 2026-10-03: the two new-work orders on the real queue carry no `slug:`
(0 of 690 orders do), so "0 of 2" was forced by the missing join key, not by
work going around Voyage. An absence without a possible match is "not
measured", never 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The use number read `work-class` from the order frontmatter; 0 of 690 orders
carry it, so the denominator was always empty. PM rule 02.10: the order
marker `<!-- loesningsvalg: plan|prove -->` is new work, `ikke-nytt` is not,
counted from 2026-09-28 (enforced by pre-order-loesningsvalg.sh since then).
Unmarked orders and orders before the start are "not measured", never a no.
Red against today's code: MARKER_SINCE is not exported, and with it stubbed in
a scratch copy all five new use tests fail on behaviour.
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: opus -> Opus 5.5 and sonnet -> Sonnet 5.5 (both default
effort medium), fable -> Fable 5.1 (default high), and a subagent
without effort: inherits the session level. Seven tracked files still
say Opus 4.8 / Sonnet 4.6 / Fable 5. History keeps its names; a
known-positive control proves the query can find them there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lifted target (operator, 2026-09-27; PM order 44111111): Voyage + the
operator's way of working level with or ahead of related frameworks in all
14 areas, and every Voyage part a documented Claude Code primitive covers
removed or with a measured reason to stay.
scripts/comparison-gate.mjs reads both denominators from their source, never
from the table: the areas from the first column of the PM report's table,
the parts from git ls-files (one part per eval case). It fells the table on
missing evidence, never on a verdict: a cited file must exist inside its
root and hold the cited lines, a pinned clone must sit at its pin, a web
citation needs a verbatim quote, an absence needs zero hits and a
known-positive control. Green also requires an independent reader. The
table itself is local-only (docs/comparison.local.json).
Measured today on 7439dac: RED, 0 evidence problems; 2 of 14 areas against
all five references (Superpowers 11, Pocock 14, agent-skills 11, Cherny 10,
playbook 2); tidy 5 of 64 covered parts resolved.
23 tests in tests/scripts/comparison-gate.test.mjs; six mutants felled (no
evidence check, no line check, no reader check, denominator from the table,
no tidy completeness, no pin check). Suite 1278 -> 1301 (1299/0/2).
[skip-docs]: an operator measurement instrument like scripts/yardstick.mjs,
whose table is local-only - no user-facing behaviour changes, so README and
CLAUDE.md have nothing true to say about it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Bash tool runs the user's shell; on macOS that is zsh, whose NOMATCH
option fails an unmatched session-* glob with exit 1. A first run has no
worktrees yet, so Check 4 stops every first multi-session run and every
re-run after a declined main-merge gate. Red under /bin/zsh, green under
/bin/bash.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 3 of the review of the session-order flow:
- the orders dir is cleared only under the main-merge gate's confirm
(wave path, next-wave none, Step 4 passed); Step 6 keeps it, and a
declined gate keeps the merged-waves record
- the gate text is true on the wave path: the waves are already merged
on the current branch, nothing is finalized, and re-running the same
command (not --resume) returns to the gate; the single-session
--resume statement stays
- the report footer names the multi-session way to continue
- wave.json stores the branch the wave was prepared on, and Step 3's
status call (executed from the doc in a temp repo) refuses another
branch, keeping wave.json
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>
Round 2 of the review of the session-order flow. One invariant closes the
class: Phase 2.55, 2.6 and 7.6 remove worktrees only without force and
branches only with -d; a refusal keeps the work and is reported.
These tests execute the bash blocks of commands/trekexecute.md in
throwaway repos with linked worktrees:
- Check 4 and Step 5 remove a clean worktree and a merged branch, keep an
unmerged branch and a worktree with untracked files, and list them
- Step 1 stops on a branch or worktree left by an earlier attempt
- Step 3 stops on a dirty main checkout (B1) and tells a refused merge
(no MERGE_HEAD) from a real conflict; after a merged wave it records
the wave and drops only identical, untracked, archived progress copies
- Phase 2.5, Check 4 and Step 0 resolve the main checkout and refuse a
linked worktree (B2); Step 0 derives a main-relative plan path
- Check 1 does not count .claude/trekplan-sessions/ as a dirty tree
- wave.json and merged-waves.json carry the plan sha256 and refuse
another plan or version, naming the run and the clear command (B3);
Step 6, not Phase 8, clears on every wave merged + Step 4 passed
One test is a structural guard over the text (no force flag in those
phases); the executed blocks pin the behavior.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Operator decision 2026-10-02: keep the test set that a person runs
through Anthropic's plugin eval tool. Voyage starts nothing; the gate
counts that entry exactly, and the binding rule and the gate header now
say so instead of claiming historical mentions only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>