voyage/CHANGELOG.md
Kjell Tore Guttormsen cf08df9d55
feat(routing): every eval case names its event; the P10 eval gate is exempted with its reason (A1)
P10's model-free part (wave 4, order A1, decision 63). The routing test now
checks every case in evals/ for from=, not only the skill-tagged ones (R1):
a case with no skill tag is not routed, only checked, and the report gives
both counts ("45 cases checked for from=, 37 routed"). The eight test-set
cases get from=proevesett-eval-suite (d311f3b) or
from=proevesett-intent-gate (3892a83), the commits that added them.

The release gate that reads the last test-set run is written into the
runbook as exempted with its reason (it waits for the fixed test set to run
again) and still says where it goes (scripts/release-check.mjs).

review-630's prototype-tag stub gets from=test: under R1 an unrouted case is
still checked for from=, and the stub tests that a prototype name is never
routed, which stands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:15:00 +02:00

230 KiB
Raw Blame History

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog.

Unreleased — The annotating skill, the run coupling and P10's model-free part

Doors

  • two-way: every case in evals/ names its event, and the routing test checks every case (P10, R1) — a revert lets a case without from= through again; the eight tags added to the fixed test set stay harmless.

Changed

  • P10's model-free part is done; the eval gate (P10) is exempted until the fixed test set runs again. Every case in evals/ now names the event it came from (from=), the eight test-set cases included (from=proevesett-eval-suite, from=proevesett-intent-gate). The routing test (lib/skills/routing.mjs) fails any case without it, routed or not, and its report gives both counts: cases checked for from= and cases routed. The release gate that would read the last test-set run is written into docs/release-runbook.md as exempted with its reason, not built: a gate that can never fire is not built.

v6.5.0 — 2026-10-18 — Three skills for brief, criteria and review, English labels, and three trial-5 fixes

Wave 3 adds three skills, each one source for a discipline that was copied or missing before: voyage:interviewing for the brief's question round, voyage:writing-criteria for criteria that can run and go red, and voyage:reviewing-adversarially for every reviewer's stance. The test repo's trial 5 ran all three end to end. The product now shows English where it showed Norwegian (decision 56), and three findings from trial 5 are fixed (decision 59), each with a test that failed on the code before it. Suite 2659 (2657 pass, 0 fail, 2 skipped), measured by npm test on main at 849b242, the tree this release review covered.

Nothing here asks anything of users. No brief, plan or review format changes.

Doors

  • two-way: skill reviewing-adversarially and its skills: lines (order 7d) — revert f906ec9; the review contract (JSON, verdict) is unchanged.
  • two-way: skill writing-criteria and its pointers (order 7c) — revert 837e925; the criteria runner and the validators are unchanged.
  • two-way: skill interviewing and the /trekbrief Phase 3 pointer (order 7e) — revert f6e18a1 restores the inline Phase 3 text; no brief format change (Handover 1 untouched).
  • two-way: English UI labels (decision 56) — the stored annotation keys are unchanged, so a revert brings back the Norwegian labels and every saved annotation loads either way.
  • two-way: the brief validator warns on a criterion whose first backticked span is not a command while a later one is (trial-5 finding 1) — a warning, never an error; a revert stops the warning.
  • two-way: a re-planned step's earlier new files are parked before the fresh build (trial-5 finding 4) — a revert leaves them in the work tree again; files already parked stay in the git directory, never deleted.
  • two-way: one reviewer's two findings on one file+line+rule keep a row each (trial-5 finding 7) — a revert merges them again; earlier review.md files are not re-read.

Added

  • Skill voyage:reviewing-adversarially (order 7d). One stance for every reviewer: no praise, a source for every finding (file:line or a quote), no downgrade without a reason, a Declined to Judge list, claims checked against the diff and not the report. Preloaded by the three /trekreview agents and scope-guardian, and named by /trekreview at spawn; it replaces the copied "Interaction Awareness" block. Each reviewer's Declined to Judge lines now reach review.md.
  • Skill voyage:writing-criteria (order 7c). One source for how a success criterion or a Verify:, Regression: or End-to-end: line is written so the criteria runner can run it and it can go red; anything more is bash tests/<name>.sh. Preloaded by brief-reviewer and plan-critic, named by /trekplan. Baseline: 24 of 27 lines refused by the runner without the skill, 0 of 27 with it.
  • Skill voyage:interviewing (order 7e). /trekbrief Phase 3 asks for the interview form by name instead of carrying it: at most four questions per call, one decision each, the recommended answer first, facts looked up and never asked, the rest written down, and a hollow answer or unasked scope never written in as the person's decision. Measured with helpers: round-1 size 10–11 → 4, questions without a recommendation 15/31 → 0/12, a hollow answer kept as a decision 2/3 → 0/3.
  • Eval cases for the three skills (evals/skill-interviewing-*, evals/skill-writing-criteria-*, evals/skill-reviewing-adversarially-*: three that should fire, two that should stay quiet, one effect case each). Written, not run.

Fixed

  • English where the product showed Norwegian (decision 56). The annotation page's intent buttons, sidebar badges and copied prompt read Fix / Change / Question; the stored keys stay fiks / endre / spørsmål, so annotations saved earlier still load. /trekreview's project-memory approval offers "Add the line" / "Not now". README, CLAUDE.md, docs/architecture.md, package.json and plugin.json describe what the product shows. The Norwegian hollow-answer list in approval-log.mjs and /trekbrief stays: it matches what a user types.
  • The brief validator sees a criterion the runner cannot run (trial-5 finding 1). When a success criterion's first backticked span is not a command but a later span is, the validator now warns BRIEF_SC_NOT_RUNNABLE, as the criteria runner already reported it unrunnable. A criterion that only names a flag or a path stays prose and unflagged (Handover 1 says so).
  • A re-planned step no longer builds on its earlier attempt's files (trial-5 finding 4). On failure: revert leaves a step's new files on disk; --resume after a new plan now runs lib/util/park-attempt-files.mjs before the fresh build helper. It moves every still-untracked file the attempt created into the git directory (voyage/parked/step-N-attempt-k), never deletes one, never overwrites a parked file, and exits 1 while a file the attempt made is still in the tree.
  • One reviewer's two findings on one triplet keep a row each (trial-5 finding 7). Pass 1 merged two different /code-review findings on the same file, line and rule key, and the second lost its row and its action. A reviewer is never merged with itself: its second finding under another title stays its own row, with the id over rule_key#2, counted over the final list — also in --workflow, engine-findings and fidelity-diff. The decision-23 put-back stays one copy per triplet.

Known issues

The findings from the test repo's trial 5 that are not fixed in 6.5.0 (decision 59), grouped by consequence.

Too lax — can let through what should be stopped

  • Core code outside the deep-review patterns is never deep-reviewed (trial-5 finding 9). /trekreview triage makes every file outside the deep-review patterns (for example bin/ and tests/) summary-only, so code-correctness-reviewer gives no verdict on a CLI's core code; brief-conformance-reviewer still reads the whole diff. Planned for the fix round before v7 (decisions 57 and 58).

Too strict — can stop what should go on

  • A controller finding on a locked test line the plan gave has no way forward in the fix ladder (finding 2). Fix rounds may not change a locked test (the one exception is a test not red at base), so rounds 1–3 repeat the same diff before the step goes up to the plan.
  • The stop guard holds the session while it waits for the fix helper (finding 3). Sub-step F sets the test lock to pending before a fix round; the green exception (operator decision 2026-10-08) covers only the wait for the controller.
  • Phase 7.5 counts a re-approval of the plan as a stray commit (finding 5). After the upward path the plan is approved again, but 7.5 lists only approvals from the review loop as process commits; read strictly, the run becomes partial and the merge into main stays closed.
  • Plan dedup misses one finding reported by both plan reviewers when they cite it differently (finding 6): an absolute and a relative path, another rule key, or overlapping line ranges, so one major is counted twice.
  • done-line.mjs --check --commit with a short sha answers "no DONE line" (finding 10), exit 1, though the line holds the full sha; Sub-step G only says --commit {hash}.

Inaccurate — wrong or unclear, nothing stopped or let through

  • Line numbers in review findings can be off (finding 8). An engine finding cited the line after the code; FINDING_LINE_OUT_OF_RANGE catches only a line past the end of the file, and a patch line number written in a reviewer's prose, or :135 with no file name, is not caught.
  • With --plugin-dir, statistics go to the installed plugin's data directory (finding 11): stats-append and event-emit write to ~/.claude/plugins/data/voyage-…, so a development copy's statistics mix with the installed version's.
  • /trekplan Phase 9 points the plan reviewers at their schema in agents/plan-critic.md and agents/scope-guardian.md (finding 12), a path in Voyage outside the repo, in the same prompt that tells them to read only inside it.
  • /trekbrief's bounded budget is unclear (finding 13): "8, the three fixed ones included" does not say whether the Phase 3.5 tier question counts, and Phase 3.5 puts the heuristic's proposal first as "(default)" even when the operator's own rule is to go up in doubt.
  • /security-review diffs against the remote's default branch, not the review's range (finding 14), so it can review more files than the review. In this release's review the opposite happened: the remote's main was ahead of v6.4.0, so the built-in diff missed the decision-56 commits, and its standard prompt was run over the whole range instead.

The release review of 6.5.0 (/trekreview over v6.4.0..main, WARN: 0 BLOCKER, 13 MAJOR, 1 MINOR) found the following. None is a BLOCKER, so none opens a fix round before this release (decision 52). "Confirmed" means the release session reproduced it; "read" means it was traced in the code and not run.

Too lax — can let through what should be stopped

  • The park step can leave the earlier attempt's files in the tree and still exit 0 (the trial-5 finding-4 fix, lib/util/park-attempt-files.mjs). Confirmed: a file still registered with git add --intent-to-add (the revert was refused by the guard or declined) is read as "tracked since the attempt" and left in place; and an upward diff written under color.ui=always has no header the tool can read, so nothing is parked. Read: from a subdirectory the diff's paths are resolved against the wrong directory, and the tool's two git calls never check their exit status.
  • On the opt-in --workflow path, the severity floor and the put-back read one row per file, line and rule key (scripts/trekreview-armB.workflow.mjs), while the trial-5 finding-7 fix can now give two. Read: a finding can then be floored against the wrong row, or take an engine row's one legal lowering, and an engine row the coordinator did not return is not put back when its sibling was; a WARN can become ALLOW. The default path is not affected.
  • Which row a finding joins can depend on the order the reviewers' payloads are read (lib/review/coordinator-contract.mjs). Read: the same findings in another order can give other rows, severities and verdict.
  • The coordinator dropped four engine findings as refuted because their line numbers lay past the end of the file. The engine had cited positions in the diff; only the citation was checked, never the claim, and two of the four were confirmed true (the intent-to-add hole above and the brief warning below). Same class as trial-5 finding 8.
  • No test holds a reviewer's Declined to Judge lines reaching review.md. The copy-through in /trekreview and the coordinator is prose only; deleting it leaves the suite green.

Too strict — can stop what should go on

  • The brief validator's new BRIEF_SC_NOT_RUNNABLE warning fires on prose (the trial-5 finding-1 fix). Confirmed: any bare word in a later backticked span counts as a command, so "--verbose prints the login field" is told to put login first. A warning, never an error.

Inaccurate — wrong or unclear, nothing stopped or let through

  • A finding's #k id depends on arrival order (lib/parsers/finding-id.mjs), so the same finding can get another id in a second review; and a kept row can take the plain id that a set-aside row on the same triplet already carries. Read, not run.
  • /trekplan tells the session to load voyage:writing-criteria by name but does not list the Skill tool in allowed-tools, as /trekbrief now does. Whether Claude Code treats that list as a limit is not verified.
  • The bake-off's arm A still merges each triplet to one row (scripts/bakeoff-armA-merge.mjs, not changed in this release), so a fidelity measurement now shows an artificial gap; the grouping rule lives in three copies.
  • A new eval scaffold has a non-ASCII character (evals/skill-writing-criteria-effect/scaffold.sh:42, an em dash).

v6.4.0 — 2026-10-17 — plan_version 1.9, the trial-4 findings, session-clean tests, the converging critic loop

A new plan version, 1.9, in which every path in a step's Files: and on its Test first: File: line stands first, in backticks, so the reader no longer guesses paths from prose (decision 16). The same delivery closes the six findings from the test repo's trial 4 and stops npm test from pointing a live session's stop guard at a temp-repo lock. Every fix began with a test that failed on the code before it. Suite 2517 (2515 pass, 0 fail, 2 skipped), measured by npm test on the third remediation's Step 2 commit (829da48), the commit before this section.

The converging critic loop came after that measurement (decisions 43 and 44). From round 2 the plan gate counts a critic round by rule A, and both reviewers state rule B. Suite 2602 (2600 pass, 0 fail, 2 skipped), measured by npm test on main at 4e28dc5, the tree this release review covered.

Nothing here asks anything of users. Older plans warn, they do not fail: a plan below 1.9 is read as in 6.3.1, apart from the fixes under Fixed, and gets one warning per step whose Files: names a path that is not backticked.

Doors

  • two-way: plan_version 1.9 — a 1.9 plan read by 6.3.1 gets PLAN_VERSION_MISMATCH as a warning and the 6.3.1 reader, so a revert rewrites no plan.
  • two-way: Files reader (three 6.3.0 answers restored) — a revert brings back 6.3.1's answers; no file format changes.
  • two-way: the test files on the Test first File line are the backticked paths right after File: (operator decision 20) — a revert reads every path-shaped span again.
  • two-way: red proof checks --tests against the plan — a revert accepts any list again.
  • two-way: brief-conflict mark on review findings — an older verdict gate ignores the field.
  • two-way: review Pass 1 ranks by catalogue tier and a dropped duplicate never lowers its group — a revert restores the asserted-severity ranking.
  • two-way: the workflow review puts back every engine finding the coordinator did not return (operator decision 23) — opt-in path only; a revert restores the old floor.
  • two-way: approval commits require a Co-Authored-By trailer — only Voyage's own commands call the CLI, and they pass it.
  • two-way: explorer prompts, stamp order, test env — prose and test-side only.
  • two-way: a 1.9 wrapped line keeps its paths only after a comma (operator decision 29), and a File: line with nothing after it takes its first wrapped line — a revert joins every wrapped line again.
  • two-way: below 1.9 a test file after a note in brackets, and, plus or + is read when it is clearly a test (operator decision 28 and operator decision 31) — a revert reads only the run right after File: again.
  • two-way: red proof reads the step's test files from the plan, prints them, and refuses a plan it cannot read (operator decision 30) — the older prose that passes --tests still runs against it.
  • two-way: original_severity names what the kept finding asserted — only tests read the field.
  • two-way: the workflow review fails closed when its coordinator returns nothing, and names every reviewer that did not run in allow_blocked_by — opt-in path only.
  • two-way: below 1.8, when the plan names no test file, the helper and the executor give red proof the files the helper wrote (operator decision 41) — a revert leaves such a step unproven and unlocked.
  • two-way: rule A in the plan gate (decision 43) — an older gate ignores the new verdict fields, and a revert counts every round fully.
  • two-way: rule B and the security key in the reviewers (decision 43) — prose only; a revert restores the old rating.
  • two-way: plan dedup passes the reviewers' marks and rule-B fields through, and its two fixes — a revert drops the fields and brings back the line-0 collapse and the crash.
  • two-way: the post-compact hook test's timeout (decision 44) — test-side only.
  • two-way: the critic-loop matcher needs overlapping texts, and a new finding never takes an old id (operator decision 48) — a revert matches by id or line alone again.
  • two-way: plan dedup keeps a lowered_from that is not a severity (operator decision 48) — a revert counts it as no lowering again.
  • two-way: plan dedup ranks a merged pair by what rule B counts (operator decision 48) — a revert brings back the order-dependent merge.

Added

  • plan_version 1.9: the file first on every line. Each entry of Files: and each Test first: File: line opens with its backticked path or paths; everything from the first other text on is description and is never read. A 1.9 plan that breaks this gets PLAN_STEP_PATH_NOT_FIRST or PLAN_STEP_PATH_NOT_A_PATH (errors under --strict, warnings without). The parser, the validator, the tests-only check, the plan-file sweep (K6) and red proof read a 1.9 plan by this grammar. 1.9 is the current target: Handover 4, the plan template, /trekplan, the planning orchestrator and CLAUDE.md say so, and the rules introduced at 1.8 say "1.8 or later".
  • A warning for older plans. Below 1.9, a path in Files: that is not backticked gets the warning PLAN_STEP_PATH_UNTICKED, under --strict too.
  • The brief-conflict mark. A /code-review finding at the MAJOR tier whose recommended action goes against a brief Non-Goal or another stated choice drops to MINOR, marked contradicts_brief and brief_lowered_from: MAJOR; any other engine finding only gets the mark, and a BLOCKER is never lowered. /trekreview passes the brief's choices to the coordinator, which writes the mark into review.md; the opt-in workflow review applies the same rule and floors an illegal lowering. On an ALLOW or WARN review the verdict gate answers exit 2 for a finding lowered or marked outside that one shape: brief_lowered_from on any other finding, a mark on a reviewer finding, a mark or an engine finding below its catalogue tier, or a mark with a missing or unknown rule key.
  • The critic loop converges by rule A, counted by the plan gate (decision 43). Round 1 is unchanged. From round 2 on, plan-gate.mjs --diff prints what changed since the text the last round reviewed. Both reviewers get it and mark each previous finding by id. Then --record counts the round: a new major that cites a plan line outside that diff counts as minor. A blocker, a security finding and a finding with no plan line count at full severity. A previous finding stays counted until it is marked resolved. The gate keeps each recorded round's text in the git directory, so a snapshot is never committed. A plan outside any git repository keeps none, and its next round counts fully. Every new verdict field is optional, and absent means round-1 behaviour, so an older verdict block gives the same exit codes. Phase 9, Handover 4, the planning orchestrator, CLAUDE.md and the README say so.
  • Rule B in both reviewers (decision 43). plan-critic and scope-guardian state it: a major that a named test, Regression: command or gate in the plan will fail on during execution is minor, never a blocker and never a security finding. The gate records each such lowering from round 1 on. Plan dedup passes the reviewers' marks and rule-B fields through. The operator answered three questions on 2026-10-15: rule B applies from round 1 and rule A from round 2; both reviewers tag a security finding with the review catalogue's security key; a lowered finding that is re-reported as major stays minor, and only a re-report as blocker counts as blocker.

Fixed

  • The suite no longer hands the session id to the lock CLI. npm test preloads a helper that removes CLAUDE_CODE_SESSION_ID for the whole run, and every test that spreads the process environment into a child uses a shared helper without it. A live session's stop guard is no longer pointed at a temp-repo lock. A test file run on its own with node --test still passes the id to a child it starts without an env (release review).
  • The three Files: regressions from 6.3.1's Known issues give 6.3.0's answer again: a source file after a described test is kept, a path that a description only mentions is not read as a file, and a backticked bare name such as LICENSE alone on a following line is read as a file.
  • The test files on the Test first: File: line are the backticked paths that stand right after File:, separated only by commas or spaces, and below plan_version 1.9 also each further path after a note in brackets ((new), *(new)*, (existing …)) or after and, plus or +, as long as it is clearly a test (operator decision 28, 13.10, and operator decision 31, 14.10; review bd2520b0). Every one of them is read, locked and copied for red proof, not only the first. A path in the description after them is no test file, at every plan_version (operator decision 20, 12.10; review 6c31212c), so a step whose File: line names its source in the description is no longer read as tests-only.
  • A 1.9 Test first: names its test only on a line that opens with File:, the way the executor, K6 and red proof read it. Below 1.9 the check reads as before.
  • Engine provenance in the review. Ingest takes engine from the payload, never from a field a reviewer wrote on its own finding, and dedup ranks by catalogue tier, so a reviewer-agent finding is kept over an engine finding, and the kept finding carries the group's highest severity, in the coordinator's Pass 1 and in the workflow dedup. A brief-conflict mark can no longer lower a reviewer's MAJOR (operator decision 2026-10-12). On the workflow path, floor (b) and the put-back of every engine finding the coordinator did not return (both below) hold the same line after the coordinator answers.
  • Explorers and reviewers stay in the repo. /trekplan tells its brief-reviewer, the eight Phase 5 explorers, the Phase 6 deep-dives, the plan-critic and the scope-guardian to read local files only inside the repo under exploration plus the paths their prompt gives, and every explorer gets the brief.
  • The brief review stamp covers only text the reviewer saw. For a small brief, the reviewer's gaps are written after the stamp, so the stamp reads stale and /trekplan reviews the brief once more.
  • Approval commits carry the caller's Co-Authored-By trailer. artifact-commit.mjs takes --trailer and refuses (exit 1, before anything is staged or committed) a missing, multi-line or malformed trailer, an unfilled {model}, and one that names a session link. /trekbrief, /trekplan and /trekexecute pass it; /trekexecute prints the reason and goes on when the approval is logged but not committed.
  • A list joiner no longer ends the read of a plain path below 1.9. In Files:, a +, &, and or or between backticked paths is no word of description, so a plain path after them is read as a file again, as 6.3.1 read it, and a step of two tests joined by + and a plain source is not tests-only (review 182ceb93).
  • A 1.9 entry keeps the paths of a line wrapped after a comma, and a numbered File: line names its test. A line that is no list item keeps its paths only after a comma, when the entry so far ends with one (operator decision 29, 14.10; reviews d21ff81e, eaeb398e), so a Files: list wrapped after a comma names every file: the step is not tests-only, and K6 plans the second file too. Otherwise that line, and every later wrapped line of the entry, is description and never read. A File: line with nothing after it takes its first wrapped line. The Test first: File: line may open with -, *, +, 1. or 1), and any list item ends it (reviews b4fa1927, 4b6460e5).
  • A 1.9 plan refuses placeholders and mixed-case bare names as files (operator decision 22, 13.10; review 33f37f53). A leading backticked span that is a placeholder (none, TBD, TODO, TBA, N/A, NA, ..., in any case) or a bare name that is neither in capitals nor a build file, such as the mixed-case Parser, is PLAN_STEP_PATH_NOT_A_PATH, and its hint says to write ./Name for such a file. LICENSE, README and Makefile stay files; below 1.9 nothing changes.
  • The engine of a payload is read from an own property. Ingest no longer gives the findings of a payload whose reviewer is named toString, constructor, __proto__ or another name Object.prototype carries an engine (it gave them a function or an object), and toReviewerPayload refuses an engine named toString with its "engine must be one of" error (review 3799ea6c).
  • Pass 1 ranks by catalogue tier, and a duplicate never lowers its group. Of findings with the same (file, line, rule_key), the coordinator's Pass 1 and dedupByTriplet keep the one with the higher catalogue tier, then a reviewer-agent finding over an engine finding, then the higher asserted severity, then the brief-conformance-reviewer finding, then the first seen, and write the kept finding at the highest severity its group asserted. Before, a marked code-review MAJOR beat a reviewer's MINOR on the same triplet and the review came out ALLOW; now it is WARN (review bc7f4e23; the coordinator's prose, operator decision 24).
  • The workflow review puts back every engine finding the coordinator did not return (operator decision 23, 13.10; reviews ab1b5d9f, bc7f4e23). On the opt-in workflow path, dedup ranks as Pass 1 does, and every engine finding with no returned finding at its exact (file, line, rule_key) is put back at its own severity, one per triplet (the higher-severity copy when two share it), so dropping, moving or relabelling an engine finding no longer lowers the verdict. Beside it, floor (b): a returned finding is never below the lower of its reviewer counterpart's severity and its catalogue tier (for a key outside the catalogue, the counterpart's severity). The workflow path is now stricter than the default path (see Known issues).
  • An approval trailer with a blank or padded name is refused. artifact-commit.mjs refuses a trailer whose name is empty or only spaces, or that holds two spaces in a row, so an empty {model} ("Claude" and two spaces) fails as the module header promises. A name with a parenthesis, such as "Claude Opus 5.5 (1M context)", is still accepted (review 8420915b).
  • The plan validator parses each step once. validatePlanContent reads a step's fields once and every check, --steps-from included, reads them from there; its errors and warnings are unchanged (review 93382464).
  • Red proof reads the step's test files from the plan and prints them, and the executor defines them once (review cf241526; operator decision 30, 14.10; reviews 793fc1aa, 09ae46d8, d01df508, 11ee78c5). With --plan and --step, red-proof.mjs reads the step's test files from the plan as decision 20 and, below 1.9, decision 31 set them, and prints the list it ran as tests (a tests: line in text mode). The helper and the executor pass no --tests, and the lock's --files is that printed list. A --tests that names another set is exit 2 with a reason that starts tests-mismatch and the plan's list in plan_tests; a plan or step it cannot read is exit 2 with a reason that starts plan-unreadable, and the executor corrects its own call; a step whose plan names no test file reads as before. commands/trekexecute.md defines the step's test files in one sentence the other places point to.
  • The /trekbrief pass branch names no ## Brief Quality, and the stats rows span their blocks (operator decision 21, 12.10). That section belongs to the exhausted and force-stopped branches only. In tests/fixtures/jsonl-schemas.md the line_ref of the trekbrief, trekplan and trekreview stats rows runs from the phase heading to the closing fence of its stats-append block, and a test pins all four command rows (trekexecute's too) by exact equality.
  • original_severity names what the kept finding asserted (review 08deae68). When Pass 1 raises a finding to its duplicate group's severity, Pass 3 writes original_severity from the finding's own severity, and only when that differs from its catalogue tier; the carrier field pass1_raised_from never leaves the contract.
  • The workflow review fails closed when its coordinator returns nothing (review edf2ec56). A coordinator that returns no verdict and findings counts as a missing reviewer: the merged findings are read at their catalogue tier or higher (never lowered), the verdict starts at WARN (a BLOCK stays BLOCK), and every reviewer, engine and coordinator that did not deliver is named in allow_blocked_by as missing-reviewer:<name>, so the verdict gate exits 2 on such a WARN.
  • K6 keeps its own normaliser and LIST_ITEM is one literal again (operator decision 27, 13.10; review 7961a700). The two /simplify edits that crossed the first remediation's fence around K6 are reverted.
  • The control-run test leaves headroom over a slow start (review 703d87e1). Under full-suite load the start-point run of red proof's control-run test was killed at its 2 s timeout. The test now gives red proof a 15 s timeout and starts every run but the control slowly on purpose, so a timeout without headroom fails on demand; the numbers live in tests/helpers/timing.mjs.
  • Below 1.8 a plan that names no test file gets the files the helper wrote (review 7b3b59ed; operator decision 41, 14.10). A File: line below 1.8 may name its test without backticks, so red proof reads no test file from the plan and answers no test files given. The helper then runs the same red proof again with --tests naming the files it wrote, and the executor gives red proof that same list, so such a step is proven and locked.
  • The post-compact hook test survives a slow start (decision 44). Its hook child had a fixed 5 s timeout and was killed under full-suite load. The timeout now comes from tests/helpers/timing.mjs, and a killed hook child reads as a failure instead of exit 0.
  • Plan dedup keeps distinct file-level findings apart, and no longer crashes on a bad field (decision 43). Findings of one rule key on line 0 or with no line no longer collapse into one. An empty file or a line that is not a whole number no longer crashes the finding id; the line becomes null and the finding stands.
  • The critic loop no longer folds a new finding into an old one by its id or line alone (reviews 4ab24b07, d03835c4; operator decision 48, 16.10).
    • What happened: an equal id or the old finding's line was enough. The new text was lost, and a new file-level major could count as an old rule-B minor.
    • Now the texts must overlap, a finding with a plan line is never matched by id, and a new finding never takes an old finding's id.
  • A lowered_from that is not a severity now counts as blocker (reviews 8782602b, ebe164e2; operator decision 48, 16.10). It was read as no lowering. A blank one is still no lowering.
  • Plan dedup no longer lets reviewer order lower a blocker (review 69c9cebd; operator decision 48, 16.10).
    • A merge keeps the copy rule B counts highest, on the merged keys.
    • This also covers a blocker claim merged into a plain major, found during this round.

Known issues

  • The session split reads a 1.9 plan as an older plan (operator answer 3).
  • Marked MINOR findings still feed recurrence / project-memory proposals.
  • The default review path's verdict gate does not compare review.md with the engine payloads, so only the opt-in workflow path puts an engine finding the coordinator did not return back (operator decision 23). The operator made that check a separate delivery later (operator decision 25, 13.10).
  • Below 1.9 the plan-file sweep (K6) keeps its own wider reader of the File: line (operator 2026-10-11): it plans every backticked path on that line, also one in the description that decision 20 no longer counts as a test file.
  • Red proof accepts a --tests that matches the plan's list and prints it in the spelling it was given, not the plan's (review 2d624b54; deferred by operator decision 42, 14.10).
  • ingest keeps a pass1_raised_from and an original_severity that a payload wrote on its own finding (reviews c06d5385, e031a480; deferred by operator decision 42, 14.10).
  • When its coordinator returns nothing, the workflow review raises the merged findings in place; this has no effect on its output today (review 6ff82e75; deferred by operator decision 42, 14.10).
  • A whitespace-only line ends a 1.9 Test first: File: entry but not a Files: entry, to be skipped in both by operator decision 40 (review 4b6460e5; deferred by operator decision 42, 14.10). The same id stands in a Fixed bullet above, which fixed the list-item case of that review; the whitespace-only case came back open.
  • A 1.9 wrapped line read as description is dropped without a warning, even when it opens with a backticked path, to be warned on by operator decision 39 (review 4e1607cb; deferred by operator decision 42, 14.10).
  • Handover 4's Files: bullet words its empty-entry rule as for a File: line (review 4f22b101; deferred by operator decision 42, 14.10).
  • Accepted deviation: the 1.9 File: selector repeats the list-marker set of LIST_ITEM (review 4dce7c74; operator decision 38, 14.10, decision 27 stands).
  • The line diff's LCS table has no size bound. A rewritten gap of tens of thousands of lines takes seconds to minutes and gigabytes, and can end outside exit 0/1/2. Real plans measure about 1,200 lines (review 8a9b5a17; deferred by operator decision 48, 16.10).
  • A previous finding re-reported on its own edited line is counted twice. Such a re-report of a lowered finding counts at its full severity (review 8004ea85; deferred by operator decision 48, 16.10).
  • A line sent as a numeric string ("42") is read as no line and counted at full severity. The agent templates give line as a number (review c257625e; deferred by operator decision 48, 16.10).
  • npm test does not run tests/e2e-critic-diff-mode.sh. It runs under ## Verification and in /trekreview's success-criteria check (review 818b1346; deferred by operator decision 48, 16.10).
  • The matcher's residual (review 4ab24b07; operator decision 50, 16.10): a previous finding marked resolved by every raiser and re-reported in other words (content overlap below 0.7) on an unchanged line is a new finding, which rule A can lower to minor. The same holds for a re-report in the same short words (fewer than 6 content words) away from the previous finding's place.
  • A short new finding at a previous finding's place is matched to it when all its content words appear in the old text: the overlap is measured against the shorter text, and the place clause has no word floor. The new text is lost, and the old finding's severity is counted, a rule-B minor included (review ea8c1752; deferred by operator decision 51, 16.10).
  • In a merge of three or more copies, a copy's rule-B claim that ties on the keys merged so far is dropped. When the security key arrives with a later copy, reviewer order still decides between minor and major (reviews 436ade33, f9ba85e1; deferred by operator decision 51, 16.10).
  • A lowered_from such as "none", "n/a", false or 0 counts as blocker, by design (fail-closed). A reviewer that writes one on a finding it did not lower turns a minor into a BLOCK (review 79d1dc97; deferred by operator decision 51, 16.10).
  • The rule that a blank lowered_from is no lowering lives only in plan dedup. A --record input that bypasses dedup with lowered_from: "" counts as blocker (review 2e7afd61; deferred by operator decision 51, 16.10).
  • When the plan has not changed since the previous round, the gate counts the round fully, and a previous finding that no reviewer reports again leaves the count without being marked resolved. This predates the critic loop's diff mode (review 4c340d4a; deferred by operator decision 51, 16.10).
  • A near-duplicate merge in plan dedup keeps only the survivor's place, so rule A can lower a new major in the changed text to minor when its partner cites an unchanged line, and the round can record PASS. 6.3.1 counted that merge major (review ef1633b6; deferred by operator decision 52, 16.10).
  • Below 1.9, regression A's restored reading also takes a plain slash path that a description only mentions after a comma (`tests/a.test.mjs` — covers the parser, lib/parse.mjs stays as is). 6.3.1 read only the test file; now the step is no longer tests-only, and the validator warns PLAN_STEP_PATH_UNTICKED on the mentioned path (review 38a8ad34; deferred by operator decision 52, 16.10).
  • The verdict gate's brief-lowering check compares severities in upper case only, so an engine finding written "severity": "major" reads as an illegal lowering and the gate exits 2 (fail-closed) (review 20b626e2; deferred by operator decision 52, 16.10).
  • The opt-in workflow review's floor raises an illegally lowered or marked reviewer finding but keeps its brief_lowered_from and contradicts_brief, so the verdict gate still exits 2 on that review (fail-closed) (review c614baad; deferred by operator decision 52, 16.10).

v6.3.1 — 2026-10-11 — Fixes from the release review of 6.3.0, and two verdict-gate holes closed

Rounds 7 to 10 of the release review of 6.3.0. Round 7 is the WARN 6.3.0 was released with, round 8 was BLOCK (1 BLOCKER), rounds 9 and 10 were WARN. Every fix began with a test that failed on the code before it. Suite 2236 (2234 pass, 0 fail, 2 skipped).

Nothing here asks anything of users. Measured against 6.3.0 over the marketplace and the test repo: the plan validator reports the same errors and warnings for all 233 plan files, the verdict gate gives the same exit for all 123 review files, and tests-only reads the same for all 1408 plan steps.

Doors

  • two-way: tests-only is decided by the plan's Files: alone, and red proof no longer reads the step's diff (operator decision 2026-10-11) — a revert brings the diff check back; plans stay valid.
  • two-way: the Files: reader keeps a plain file beside a backticked path, reads numbered entries, and keeps a description together across commas and lines — it feeds only the PLAN_STEP_TESTS_ONLY warning and red proof's tests_only; a revert restores the 6.3.0 reading.
  • two-way: a trailing # comment is dropped from a backticked check too, so such a check now runs; one whose comment holds a double quote, $, a backtick or a backslash is refused out loud — 6.3.0 refused every backticked check with a comment, so nothing that ran stops running.
  • two-way: the verdict gate reads the last fenced block once and answers exit 2 unless its info string is exactly json, or when it is never closed; a ~~~ fence is a fence — a review written by /trekreview reads as before; a revert reopens the two holes under Fixed.
  • two-way: stops and timeouts, the release check's --review, isMain in every CLI, the test lock's command comparison, one fence reader, and cleanups — fixes; a revert restores the old behaviour.

Fixed

  • Two verdict-gate holes, present in 6.3.0. A review that ended with a clean json block and then a block holding a BLOCK verdict, written as ~~~json or opened with more text after json on its line, passed with exit 0: the gate did not see the second block. Both are exit 2 now.
  • Tests-only steps. The plan's Files: alone decides, and red proof, /trekexecute, step-implementer and the handover contract say so. A change already in the tree when the step began no longer counts against it, and a plan outside .claude/ reads the same.
  • The Files: reader keeps a plain file beside a backticked path (", Dockerfile", "and Makefile"), reads a numbered entry (1. or 1)) as an entry, keeps a description together past a comma and onto the next line, and starts a description at a plain file followed by a colon. Lowercase makefile, rakefile and justfile are build files.
  • Checks with a comment. A trailing # comment is dropped in a backticked check and in a command passed as written, so the words screened are the words run. A comment with a double quote, $, a backtick or a backslash is refused instead, because the executor hands the Verify: span to red proof, the test lock and the done line inside double quotes. Every reader refuses it out loud (PLAN_VERIFICATION_NOT_RUNNABLE, BRIEF_SC_NOT_RUNNABLE). A span that is only a comment is not-a-command.
  • Stops. Red proof reports a command killed by its timeout 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 (stoppedBy) serves red proof, the criteria runner, the test lock, the done line and the release check.
  • Release check. A relative --review is read in --repo, or from the current directory when only that one exists. Two different files are exit 2, never guessed, and one file reached through a symlinked --repo is one file.
  • Every CLI uses one isMain helper. Before, some did nothing and exited 0 when run through a symlink or a path with a space.
  • Test lock. It compares --cmd by its words and without its trailing comment.
  • One fence reader for the gate and every reader of a trailing json block. A fence closes only on a run at least as long as its opener, as in Markdown, and CRLF and an indented fence read alike everywhere. A fence indented four spaces or more still counts, on purpose: Markdown's rule made a BLOCKER block inside a list item invisible.
  • Cleanups. The 15-minute timeout is defined once, the findings check reads each cited file once per validation, and the guard writes its no-one-to-ask refusal once.

Known issues

Round 11 of the release review (0f400d3..10ac9c5) is WARN: 0 BLOCKER, 10 MAJOR, 0 MINOR. All ten come from Claude Code's /code-review, which gives no category, so each enters as MAJOR. Voyage's two reviewers and /security-review found none. The operator chose to release 6.3.1 with it (2026-10-11). None of the ten lets a gate pass. The regressions below were checked by running them against 6.3.0. None of them occurs in the 1408 plan steps measured above.

  • The Files: reader still guesses paths from prose and misreads in both directions. Two misreads are regressions from 6.3.0:

    • A source file after a described test is dropped ("tests/a.test.mjs - new test, src/a.mjs - the fix"). The step that builds code then reads as tests-only and goes to the plan.
    • A path that a description only mentions is read as a file ("covers the parser in src/parse.mjs"). A step of only tests is then not caught and goes through fix rounds (at most five, then the operator).

    Red proof has no diff check behind the reader. The structural fix is to require every path in Files: to be backticked. It changes the plan contract and is left for a planned release.

  • A json block closed on the same line as its JSON is no longer read (a regression from 6.3.0). The gate answers exit 2, and a reviewer is asked again. An opener with a blank before json is not json either, as in 6.3.0.

  • A trailing comment with a double quote, $, a backtick or a backslash is refused in every backticked check. That includes checks that never reach a shell: a ## Verification bullet, Regression:, End-to-end: and a brief criterion. 6.3.0 refused these too.

  • Cleanups: a dead branch for a span that is only a comment, the comment dropped up to four times per command, a re-export of the timeout that nothing imports, and a test helper that copies a PATH lookup.

  • An engine run that was stopped and not counted in the verdict reported three more, each checked by running:

    • A backticked bare name such as LICENSE, alone on a line after a description, is no longer read as a file. 6.3.0 read it.
    • One unclosed fence earlier in a review hides the review's own json block from the review validator. 6.3.0 found the block, and the gate answers exit 2 there.
    • An indented json example after a review's own block is read as the last block, as in 6.3.0.
  • The example plan's steps 1-2 keep their tests-only warning (operator decision 2026-10-09).

v6.3.0 — 2026-10-11 — The executor is coupled to the review gate, three skills, and a drilled release runbook

Wave 2 of the practice build (five orders, merged 2026-10-09) and the fix round after it, which closes finding 1 of the test repo's third trial: a step of only tests can never be proven red. Every fix began with a test that failed on the old code. Suite 2194 (2192 pass, 0 fail, 2 skipped).

Two changes ask something of users (see Doors): /trekexecute now refuses a plan that has no logged approval for its current content, and a check in a brief or plan runs with no shell, as plain words with a runner's read-only options. Plan 1.7/1.8, brief 2.0–2.2 and review 1.0/1.1 files still validate; the new step fields are optional.

Doors

  • one-way: /trekexecute refuses a plan whose logged approval does not cover its current sha256 (K2) — a plan written before 6.2.0, written by hand, or edited after its approval stops at Phase 1; run /trekplan --project <dir> and answer "Approve" (from 6.3.0).
  • two-way: /trekexecute reviews by itself in the closing run (/simplify → /trekreview → verdict gate, K7) and keeps the main merge closed on BLOCK or an undecided verdict; step check (K9), Regression: (K10), architecture rules (K5) and plan-file sweep (K6) run at step end and after the last step — a revert restores the old executor; nothing to do for users.
  • two-way: the approval guard refuses a merge into main, a push, a tag or publish and destructive git in the permission mode that shows no prompts — a revert lets them through again; nothing to migrate.
  • two-way: progress-validator rejects the runner's exitCode in plan_verification.failed_criteria (C15) — the executor's own prose always wrote exit_code.
  • two-way: skills workshop — form check, model-free routing test, test-first and debugging preloaded into step-implementer — new files and one skills: line; a revert removes them.
  • two-way: researching-sources skill, preloaded by the five web-search agents and named by /trekresearch — the agents' copied rule text moved into the skill; a revert puts it back.
  • two-way: Regression: (K10) and On failure: action words (K11) — an optional field and a warning; plans without them validate as before.
  • two-way: trial 2's minor fixes (B8, B11, B12, C13, C14, C16, C17) — checks, prose and agent text; a revert restores the old behaviour.
  • two-way: release check and runbook — new files; a revert removes them, and nothing else reads them.
  • two-way: tests-only steps (PLAN_STEP_TESTS_ONLY, red-proof --plan/--step → tests_only, which also reads the step's own diff, executor routes them to the plan) — a warning and an optional flag; a revert removes them, plans stay valid.
  • two-way: timing tests under load (hook helper kill limit 30 s, SC #14 fastest of three against 800 ms) — test-only.
  • two-way: example plan On failure: lines open with a K11 word, and its verbose-content test moves into the step that wires the output (6 steps, progress.json follows) — text in an example.
  • two-way: /trekreview saves the reviewer's whole answer for the findings check and names FINDING_PROSE_LINE_OUT_OF_RANGE — command text.
  • two-way: the criteria runner's commands run without NODE_TEST_CONTEXT — a false green under node --test is now red; nothing to do for users.
  • two-way: the fixes from the release review of 6.3.0 (rounds 1-6) — checks and prose; progress.json may now say simplify: "revert-refused" (an optional value); a revert restores the old behaviour.
  • one-way: a check in a brief or plan (criteria, Regression:, proof of red, the done line, the test lock) runs with no shell: its words reach the runner as written, so only plain words run (no quote, backslash, $, brace, or ~/@ at a word's start; a glob only for node --test on Node 21 and later; no path that climbs out with .. or starts at /, git included; a trailing # comment in a shell fence is dropped) with a short list of read-only options per runner — git without --output or --no-index, node --test with a built-in --test-reporter only, nothing after make test, only paths after npm test --; an option that writes a file or loads code is refused — a criterion that used one (git log --grep="x", pytest -k foo, pytest tests/test_*.py, jest --coverage, go test -timeout 30s) is now NOT RUN at review and not runnable on a 1.8 plan; wrap it in bash tests/<script>.sh (from 6.3.0).
  • two-way: the phase-model resolver text says effort comes only from the brief's phase signal — prose only, no code change.

Added

  • /trekexecute is coupled to the gates (order 6).
    • Plan approval (K2): approval-log.mjs verify --kind plan before step 1; not-logged, mismatch, expired, broken and diverged halt with what to do. Exit 2 is never a pass.
    • Step end: the step check (K9; exit 2 is "not measured") and the step's Regression: command (K10, new lib/verification/regression-check.mjs through the criteria runner) run green before the checkpoint.
    • After the last step: architecture rules (K5) and the plan-file sweep (K6); a violation or a file no step names turns completed into partial.
    • The closing run reviews by itself (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, at most TREKEXECUTE_MAX_REVIEW_ROUNDS (3) times.
    • The main-merge gate is a lock on the verdict, and where the guard asks, the executor does not ask again (one question per merge).
    • progress.json gains optional coupling fields (Handover 5).
  • Skills (orders 7a and 7b), the first three: voyage:test-first and voyage:debugging, preloaded by step-implementer, and voyage:researching-sources, preloaded by the five web-search agents and named by /trekresearch at spawn. lib/skills/skill-lint.mjs checks the form; lib/skills/routing.mjs is a model-free routing test over the skills, the 7 commands and the 21 spawnable agents (collision at 0.75 fails; thresholds pinned). Eval cases evals/skill-* are written, not run. Authoring method: docs/skills-authoring.md.
  • Release and rollback (order 8). docs/release-runbook.md (before, the release, both rollback paths drilled in a sandbox) and scripts/release-check.mjs: clean tree, npm test at HEAD, review verdict not BLOCK and covering HEAD, a ### Doors list. 0 ready, 1 not ready, 2 could not run.
  • Plan step rules (order 9). Regression: — one allowlisted command, unpiped (PLAN_STEP_REGRESSION_NOT_RUNNABLE); On failure: opens with revert | retry | skip | escalate, or PLAN_STEP_ON_FAILURE_UNKNOWN warns. Minors open after the last critic round are listed for the operator, and --extra-round records the round they pick.
  • Tests-only steps (order 10). PLAN_STEP_TESTS_ONLY warns on a step whose files are all tests; red-proof --plan/--step reports tests_only, and /trekexecute sends such a step to the plan instead of into fix rounds that cannot succeed. /trekplan, the plan template and plan-critic say the test belongs in the step that builds the behaviour.

Fixed

  • The approval guard refused only a merge into main and a push in the permission mode that shows no prompts; a tag, a publish and destructive git went through unattended. Now every call it would ask about is refused there.
  • Plan-review dedup merges two findings on the same file:line with the same content; the Jaccard threshold for every other pair is unchanged.
  • /trekbrief Step 4c says the brief reviewer runs in the background and is waited for.
  • The Phase 4 size count includes .mjs, .cjs, .mts, .cts.
  • criteria-runner --evidence shows the first output line on PASS rows.
  • The findings schema checks path:line citations in finding prose against the file; /trekreview checks the reviewer's whole answer and names FINDING_PROSE_LINE_OUT_OF_RANGE.
  • git-historian never proposes changing a file the brief froze, and names the remote from git remote -v.
  • The criteria runner's commands run without NODE_TEST_CONTEXT, so a test run inside node --test can no longer pass falsely.
  • Timing tests tolerate load (fastest of three; hook helper kill limit 30 s), and the K2 hook tests use unique session ids per run.
  • The example plan's On failure: lines use the K11 words, and its verbose-content test moves into the step that wires the output. Steps 1-2 (golden capture, stability harness) keep their tests-only warning; a step type for them is a later question, and step 2's heading no longer says it must fail.
  • The resolver text in four commands says effort comes only from the brief's phase signal.
  • Release review of 6.3.0 (seven rounds; rounds 1-3 BLOCK, rounds 4-7 WARN; every finding of rounds 1-6 fixed with a test that failed first, round 7's under Known issues): the guard refuses where no one can be asked also when its rules will not load; review steps appended by /trekexecute are held to the step rules on any plan version and need a Verify: (plan-validator --steps-from); a restore the guard refuses is recorded as revert-refused and stops the run before review, never as reverted; every check Voyage runs runs with no shell (round 5, the operator's structural fix after the patching of the shell screen did not converge), as plain words and each runner's read-only options; the release check compares version files without their version, lets the README change only in the badge's version, reads scope_sha_end as a commit sha, sees a file moved after the review, ignores Voyage's own artifacts committed after the review, runs the cheap checks first, stops a suite that never ends, works for a plugin in a subdirectory and never reports a crash as "not ready"; the plan-file sweep reads Files: as v6.2.0 did, and the tests-only check has its own reader, and red proof also reads the step's diff (see Known issues); skill frontmatter and routing read YAML values, comments and tags as YAML does; regression-check prints the progress.json status and runs through the criteria runner itself. /trekexecute says plainly that review steps in the template's own form stop with a re-plan.

Known issues — for 6.3.1

The seventh round of the release review is WARN: 0 BLOCKER, 12 MAJOR, 0 MINOR. The operator chose to release 6.3.0 with it (2026-10-11); the findings go into 6.3.1.

  • Tests-only steps: when red proof decides, the step's diff in the documented flow holds only the test, so it cannot overrule the plan's Files: reading; a change already in the working tree when the step started counts against tests-only; an unbackticked file next to a backticked path in Files: is not read.
  • Red proof reports a command killed by its timeout as "could not start". The release check calls a suite killed for too much output a timeout, and reads --review from the current directory instead of --repo.
  • A trailing # comment is dropped in a fenced check but not in a backticked one.
  • The example plan's steps 1-2 keep their tests-only warning (operator decision 2026-10-09; a step type for them is a later question).
  • Four cleanups: the 15-minute timeout defined in three places, a line count read once per citation, isMain copied into five more CLIs, and a roundabout condition in the guard.
  • Found while writing the review, and present in 6.2.0 too: the findings check ends a reviewer's json block at the first triple backtick, even one inside a JSON string.

v6.2.0 — 2026-10-08 — Intent, plan gate, step helpers, guards and a review that is a gate

Wave 1 of the practice build (five parallel orders, merged 2026-10-06), the fixes from two end-to-end trials in a separate test repo, and the defects an independent reader found in those fixes. Every fix began with a test that failed on the old code. Suite 1972 (1970 pass, 0 fail, 2 skipped).

Nothing that was valid becomes invalid: plan 1.7, brief 2.0–2.2 and review 1.0 files still validate. The new fields are optional, and the new rules apply only from plan 1.8 and review 1.1.

Added

  • Intent (/trekbrief). A size class (ceremony: small|bounded|architectural; absent = architectural) sets the question budget, and the brief asks one round of questions with the recommendation first. "høres bra ut", "gjør som du vil" and an empty answer are not approval. lib/util/approval-log.mjs keeps an append-only, hash-chained approval log in the target repo, bound to the approved content's sha256. lib/util/artifact-commit.mjs commits it. /trekplan Phase 1 halts on a broken, missing or mismatched entry.
  • Plan 1.8 and the plan gate (/trekplan).
    • Plan 1.8 requires Test first: on every step and one End-to-end: step. New optional fields: Interface in:, Interface out:, Review focus:.
    • An architectural plan gets a ## Design part.
    • The critic loop has at most 3 rounds, and the plan records them. lib/validators/plan-gate.mjs decides: 0 go, 1 stop, 2 could not run. An open MAJOR stops the plan, and after the last round the operator decides.
    • plan-critic now checks 12 dimensions.
    • New lib/verification/arch-rules.mjs runs the target repo's own dependency-cruiser or import-linter.
    • New lib/verification/plan-scope-sweep.mjs lists changed files that no step names.
  • Step helpers and proof by command (/trekexecute).
    • One fresh step-implementer helper per plan step (new agent: opus, effort high, no Agent tool).
    • One controller reads the diff and gives two verdicts: does the step meet the plan, and does it hold the quality.
    • Fix rounds go up, at most 5: helper, then plan, then operator.
    • New lib/verification/red-proof.mjs: the step's test must fail at the start point and pass at the result.
    • New lib/verification/test-integrity.mjs (the floor guard) catches removed asserts, skipped tests, stubs and loosened thresholds.
    • New lib/verification/done-line.mjs writes the done line only when the test command exits 0.
    • A closed stop list and a decision log appear in the final report.
  • Guards (command hooks only, none runs a model).
    • pre-bash-executor answers "ask" before a merge into main, a push, a tag or publish, and destructive git. post-approval-log records the answer.
    • pre-plan-gate runs the plan gate when a Voyage plan leaves plan mode.
    • The test lock (lib/util/test-lock.mjs, pre-write-executor, stop-test-lock) refuses edits to a locked test file, and refuses "done" until the step's own test command is seen green.
    • post-edit-check runs the target repo's own formatter or linter. It runs only during a Voyage plan run or after opt-in.
    • New lib/verification/step-check.mjs checks each step when it ends.
  • The review is a gate (/trekreview, review 1.1).
    • verdict: ALLOW | WARN | BLOCK is required. lib/review/verdict-gate.mjs reads it: 0 ALLOW/WARN, 1 BLOCK, 2 could not decide (never green). A control that did not run gives exit 2.
    • Claude Code's /code-review and /security-review run as the engine. Their findings enter through lib/review/engine-findings.mjs under three rule keys. CODE_REVIEW_IMPROVEMENT (MINOR) covers simplification, efficiency, reuse, style and readability. The rule catalogue now has 15 keys.
    • No finding is struck for length. Only MINOR and SUGGESTION text is trimmed, and the trims are counted.
    • The coordinator lists what it declined to judge.
    • Every BLOCKER becomes a numbered remediation step.
    • A finding class seen in two reviews is proposed as a project-memory line (lib/review/recurrence.mjs). The operator approves each line.
  • Checks when a brief or plan is written. A success criterion or Verify line that the criteria runner could never run is caught when the brief or plan is written, not when the review runs. The brief validator warns (BRIEF_SC_NOT_RUNNABLE, BRIEF_SC_SUBPOINTS, BRIEF_SC_BASH_NOT_PINNED). For a 1.8 plan, the plan validator reports PLAN_VERIFICATION_NOT_RUNNABLE, PLAN_STEP_VERIFY_NOT_RUNNABLE, PLAN_END_TO_END_NOT_RUNNABLE and PLAN_END_TO_END_NOT_VERIFIED: as errors under --strict, otherwise as warnings.

Fixed

  • The write guard covers Edit and NotebookEdit, not only Write, and fails closed.
  • The review keeps findings that are right:
    • an engine finding is never set aside for Actionability;
    • recommended_action is the engine's own fix, or otherwise a test-first step, never the failure scenario;
    • a cited line past the end of a file is caught;
    • finding ids are computed, not typed by a model.
  • A MINOR /code-review finding outside the reviewed range no longer holds ALLOW back. A MAJOR one still does.
  • The plan template's checkpoint stages the step's files (git add … && git commit). The pre-compact hook reads that form.
  • The brief template's examples are commands the runner accepts. /trekcontinue and /trekexecute call lib/ through the plugin root.
  • Manifest must_contain uses grep -E -e … --, so a pattern such as --sep is not read as an option.
  • /trekreview, /trekresearch and /trekcontinue write stats through stats-append and report a failed write.
  • annotate prints an absolute path.
  • A test lock marked green may stop while it waits for its controller.
  • /trekplan runs every exploration agent, and reviews the brief again only when it has changed since /trekbrief reviewed it.

v6.1.1 — 2026-10-05 — /trekexecute writes what it promises

A patch release. /trekexecute no longer loses its telemetry when the harness does not export CLAUDE_PLUGIN_DATA, its progress-file prose now matches its own validator, and no agent is pinned below reasoning effort high.

Fixed

  • lib/stats/event-emit.mjs falls back to the same data directory as stats-append and the yardstick when CLAUDE_PLUGIN_DATA is unset, instead of skipping silently. Every written:false (failed write, usage error, payload-not-json) exits 1 with a reason. The CLI also runs when it is invoked through a symlink or a path with a space.
  • main-merge-approved, main-merge-declined and gates_mode_flag_override are known events.
  • /trekexecute Phase 8, Phase 9 and the gates_mode_flag_override record all write through a writer that resolves the directory. A failed write is printed in one line and the run continues.
  • Phase 8 passes each event payload on stdin through a quoted heredoc (event-emit.mjs --payload -), so the shell expands nothing in it. Before, the plan path went into a single-quoted argument: a path with a quote character broke the shell parse, and a quoted pair could run a command substitution.
  • The progress-file schema and status rules in /trekexecute use the validator's vocabulary (in_progress, completed, plan_version). progress-validator now accepts the run status stopped and the step status blocked, both of which the command writes. A legacy passed step is still treated as completed on resume.
  • architecture-mapper, dependency-tracer, git-historian and task-finder pin effort: high (was medium). No agent is pinned below high; the rest follow the session.

v6.1.0 — 2026-10-05 — The yardstick's use counter gets a source

The use row in scripts/yardstick.mjs now counts an order as used only when a Voyage record names the order's id. Counting itself stays off (USE_COUNTING_SINCE = null) until the operator declares the work done; the tool ships first, the measurement comes after.

Added

  • lib/stats/claimed-order.mjs finds the one coord-queue order the session has claimed (repo-mailbox's claim contract, read-only). Exactly one claimed order is an attribution; zero or several is null plus a reason, never a guess.
  • /trekbrief stats records carry order_id, order_claimed_at and order_reason, added by the writer (stats-append), never typed by the model. The fields are on all five stats surfaces and are not exported.
  • facts.ordersNamedByARecord in the yardstick output: a known-positive diagnostic for the use row.

Changed

  • Yardstick use: the slug join is replaced by an order-id join. YES = a trekbrief record names the order's id; declared NO = the order's own arbeidsform: ordre line; no record = not measured, never a no.
  • /trekbrief --approve now runs Phase 7 after a successful stamp, so the approval leaves a trekbrief record (mode: "approve").

Fixed

  • The CLI main-guard in stats-append and yardstick compares real paths, so it no longer silently does nothing under a symlink or a space in the path.

v6.0.0 — 2026-10-02 — Voyage never starts Claude Code

Operator decision 2026-09-27: nothing Voyage ships starts a Claude Code session. Work that needs another session becomes an order plus a starter line that the user runs in a session they open themselves; parallel work inside one session uses subagents. This is a breaking change for anyone who relied on Voyage launching sessions.

Changed (breaking)

  • /trekexecute multi-session path (Phase 2.6) no longer launches child sessions and no longer finishes in one call. It prepares one wave at a time: a worktree per session, one session order per session (.claude/trekplan-sessions/{slug}/orders/, written by the new lib/util/session-orders.mjs) with a /trekexecute --session N <plan> starter, and stops. Running the same command again reads each session's progress file, merges the wave sequentially and prepares the next one. A plan with W waves takes W + 1 parent runs plus one session per order. New Hard rule 21: never start Claude Code.
  • Sessions now run under the user's own permission mode and tool set: the per-session tool allowlist and the permission-bypass mode are gone, and brief.md / architecture/overview.md are no longer injected as an appended system prompt.
  • Phase 7.6 recovery writes a bounded recovery order for a session you open, and the run stops as partial; nothing dispatches it automatically.
  • /trekplan --decompose (and its alias --export headless): the session-decomposer writes orders.md instead of a launch.sh, and the "launch" reply is gone.
  • /trekresearch --engine deep-research: the pre-gate no longer runs the Claude Code binary to read its version; the post-hoc check decides. The version-below-floor reason token is gone (that case now reports no-cited-report).
  • No {session-dir}/logs/session-N.log is written any more; progress files are the source of truth, and each wave's progress files are archived to orders/wave-W-session-N.progress.json before its worktrees are removed.
  • --dry-run no longer prints a billing line.

Removed

  • The ANTHROPIC_API_KEY billing check, the hooks-fire version precheck, the headless safety preamble and the per-child tool, turn and budget flags — they existed only for launched children. The TREKEXECUTE_MAX_TURNS and TREKEXECUTE_MAX_BUDGET_USD environment variables are ignored.
  • templates/headless-launch-template.md and scripts/q3-cache-prefix-experiment.mjs (a finished experiment that started the binary; its results stay in docs/).
  • README: the billing-safety and headless MCP-tuning sections, and the fourth security layer (scoped per-child tool access), which went with the launched children.

Fixed

  • Every VOYAGE_ROOT resolution in /trekexecute (multi-session Step 0 and plan verification), /trekreview and /trekresearch now finds the installed plugin: the literal ${CLAUDE_PLUGIN_ROOT} that Claude Code substitutes, else the highest installed version in the plugin cache. Before, these blocks always exited 2.
  • The multi-session path never force-deletes. Worktrees are removed only when git agrees they are clean and session branches are deleted only once merged; anything git refuses is kept and listed in the report with what to do. Before, a failed session, a merge conflict or a refused merge deleted every trek/{slug}/* branch of the wave, finished work included.
  • Collecting a wave never tears down a session that is still running (an unknown status counts as running); it stops when the main checkout has uncommitted changes or has switched branch, and tells a refused merge from a real conflict. The parent run must start in the main checkout, never in a session's worktree or a subdirectory's view of it.
  • A merged-waves record, bound to the plan's path and content hash, keeps a re-run from preparing an already merged wave again; a different plan or an edited plan is refused with the way out named. The record is cleared only when the final merge is confirmed.

Added

  • tests/lib/no-claude-code-launch.test.mjs: fails when any tracked file outside a reasoned, exact-count exemption list carries a way to start Claude Code; proven on a known-positive fixture for every pattern. The one operator-run exception is the fixed test set (docs/proevesett.md).
  • tests/lib/session-orders.test.mjs: runs the order writer on a fixture plan and proves the orders land, statuses classify, progress is archived, merged waves are remembered, and nothing is started.
  • tests/lib/plugin-root-resolution.test.mjs: runs every VOYAGE_ROOT block, substituted and unsubstituted.

v5.11.1 — 2026-09-23 — dead references to a retired repository removed

Changed

  • The annotation surface's provenance is described as the pattern it follows (pencil toggle, intent buttons, popover form, structured export) instead of by naming a repository that no longer exists: .claude-plugin/plugin.json and package.json descriptions, README.md, docs/architecture.md, the v5.0.3 entry below, and two comments in scripts/annotate.mjs and tests/scripts/annotate.test.mjs. No behavior change.

Added

  • tests/lib/retired-references.test.mjs fails when any tracked text file or path contains a term from the gitignored local list tests/.excluded-terms.local.txt. The scanner is validated against a planted known-positive, an empty scan fails closed, and the named exemption list is empty and rot-checked. Without the local list the scan is skipped with an explicit message.

v5.11.0 — 2026-09-23 — /trekplan plans only against an approved intent

Added

  • Intent approval gate. /trekplan (both --brief and --project, also --quick, no override flag) runs lib/validators/intent-approval.mjs --check before it reads the brief. It halts on BRIEF_INTENT_NOT_APPROVED, BRIEF_INTENT_APPROVAL_STALE or BRIEF_INTENT_APPROVAL_INVALID, and an approval check that cannot run halts too. The marker is intent_approved_hash (sha256 over the normalized ## Intent + ## Goal) plus intent_approved_at. Editing either section after approval makes it stale. /trekbrief Phase 4h shows Intent and Goal verbatim and stamps only on "Approve". /trekbrief --approve <project-dir | brief-file> does that step alone for a brief from any producer. A ## line inside a code block or HTML comment is not a heading, and each section must appear exactly once. The marker is a trace that the step ran against this text, not a signature: any session on the same machine can stamp.
  • scripts/yardstick.mjs prints Voyage's three numbers (use, trust, interrupts) with the denominator and the source each one was read from. It exits non-zero while any number cannot be counted, and today it is RED.
  • scripts/end-state-gate.mjs counts the distance to "Voyage is finished" (defects, experiments, dormant agents, open decisions). It is fail-closed: an entry whose check cannot run counts as open.
  • Plugin eval suite (evals/, docs/proevesett.md): eight cases run as real claude -p children with only Voyage loaded, deterministic graders, and each expectation committed before its first run. Measured stability: every case 5 of 5 over three full runs, and the sequencing-gate case 15 of 15.
  • lib/stats/stats-append.mjs: /trekbrief and /trekplan stats records land in the data dir the yardstick reads when CLAUDE_PLUGIN_DATA is empty, and a failed write is reported, not skipped silently. intent_approved reaches the OTel field allowlist.

Changed

  • Handover 1 (PUBLIC CONTRACT): a brief from any producer now stops at /trekplan until its intent is approved. The schema change is additive (two optional fields, no brief_version bump). The requirement sits in the consumer. See docs/HANDOVER-CONTRACTS.md §Handover 1.
  • The arg parser has a CLI. /trekreview runs it with $ARGUMENTS and relays Error: --project <dir> is required. from code (it passed "$@", which the Bash tool never has, so the parser never ran).

Fixed

  • /trekexecute runs the plan's ## Verification on the single-session path too (D-03), and /trekreview runs the brief's success-criteria commands and gives the reviewer the result (D-04), through lib/verification/criteria-runner.mjs.
  • The criteria runner screens with an allowlist of test runners, not a denylist, and refuses writes a brief may not perform. A backticked span runs only when it is a command, and the runner reads the repo's own plan format.
  • The end-state gate can no longer be turned green by editing its own ledger, and a behaviour probe must fell a stub, not just name a test.
  • The review gold-scorer key separator is written as an escape, not a raw NUL byte. The /trekresearch swarm engine points only at the External agents block.
  • Docs no longer claim an opus orchestrator: the commands follow the session model.

Removed

  • /trekplan's "execute with team" path: Claude Code 2.1.178 removed TeamCreate/TeamDelete, so it always fell back to sequential execution.
  • TaskCreate/TaskUpdate from /trekplan's tool lists. Claude Code 2.1.233 stopped offering them on current models, and no prose called them.

v5.10.1 — 2026-09-03 — gemini-bridge dropped; fail-closed review verdicts

Removed

  • gemini-bridge is dropped from the pipeline (operator directive). The agent file is deleted and every live surface that could still steer a run toward it is cleared: commands/trekresearch.md (the Bridge-agent launch block, the --local help text, the high-effort always-on pair, the stats record, the graceful-degradation list), commands/trekplan.md, commands/trekbrief.md, agents/research-orchestrator.md (mode table, agent table, prompting block, summary line), README.md (feature prose, mode table, agent prose, the mermaid EXTERNAL node, the * = conditional legend, the optional-MCP requirement, the --local section), CLAUDE.md, settings.json (the whole trekresearch.geminiBridge block), templates/research-brief-template.md (the Gemini Second Opinion section and the sources-table gemini type), templates/trekbrief-template.md, docs/architecture.md, docs/command-modes.md.
  • /trekplan high-effort Adversarial Pass 2 degrades explicitly. It now emits a ## Adversarial Pass 2 (v5.1.1 high-effort) section whose status reads "unavailable, skipped", rather than failing or vanishing: a high-effort plan carrying no Pass 2 marker is indistinguishable from one whose Pass 2 crashed. /trekresearch high effort forces only contrarian-researcher always-on, which remains the complete adversarial coverage.
  • Not removed: gemini_used survives as a vestigial /trekresearch stats field pinned to false. Dropping it would break the observability export schema for existing consumers, and no consumer asked for that.
  • Agent inventory: 24 → 23 files (20 spawnable + 3 orchestrator reference docs; synthesis-agent still dormant). Counts reconciled in README.md and CLAUDE.md; the <example>-block floor in tests/lib/agent-frontmatter.test.mjs moves 34 → 32 because an agent legitimately left the inventory — not because examples went missing from a surviving one.
  • Pinned by 5 new tests in tests/lib/doc-consistency.test.mjs, 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. CHANGELOG entries and measurement/decision docs keep their references deliberately: they record what a past version did.

Fixed

  • /trekreview verdicts are fail-closed. A finding removed by Pass 2 or Pass 3, and a reviewer whose payload was thrown away or never arrived, were arithmetically identical to a finding that never existed — all three pushed the verdict toward ALLOW. Measured before the fix: a BLOCKER with a 101-character title → ALLOW; a payload carrying one ad-hoc rule_key was skipped whole at ingest, taking a valid BLOCKER sibling with it → ALLOW. lib/review/coordinator-contract.mjs now splits every removal two ways — dropped when the test refuted the finding as a claim about this codebase, unverified otherwise — and a non-empty unverified bucket, or a reviewer in expectedReviewers that did not report, forbids ALLOW (verdict WARN, with allow_blocked_by naming why). The rule never raises a verdict: the severity catalogue and the BLOCKER/MAJOR thresholds are untouched. New exports: classifySuppression, REFUTING_REASONS, UNVERIFIED_REASONS; runContract gains unverified, missing_reviewers, unattributable_payloads and allow_blocked_by (suppressed stays the union, so existing consumers keep their meaning). A payload that fails schema without carrying a reviewer name is counted as unattributable rather than reported as a reviewer called "unnamed reviewer" — naming one would invent an agent nobody launched and double-count with expectedReviewers. Mirrored in agents/review-coordinator.md (Pass 2/3 fate columns, the new §Suppression is two-valued, Pass 4 threshold table) and commands/trekreview.md (Phase 5 reviewer accounting → STOP; Phase 6). Driven test-first: 11 new tests in tests/lib/coordinator-contract.test.mjs, incl. a known-positive control proving ALLOW is still reachable.

Docs

  • T1 §6 PoC status corrected — it was already run and declined. docs/T1-cc26-delegated-orchestration.md §8 item 3 still claimed both the §6 synthesis-agent PoC and the §5 full 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 (docs/T1-synthesis-poc-results.md; reproduce with node scripts/synthesis-measure.mjs). The stale wording 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 an explicit RUN AND DECLINED status block. The finding is structural, not stochastic: /trekplan Phase 5 spawns the exploration swarm foreground (commands/trekplan.md:158,338-341), so the 6–10 outputs are already resident in main before Phase 7 begins — delegating only the Phase-7 digest returns on top of them and evicts nothing. A saving needs the Phase-5 delivery moved off-main, which is §5.

  • §5's environment premise updated (measured 2026-09-03, CC 2.1.259). S12 recorded the live bake-off as blocked for want of an ANTHROPIC_API_KEY; claude -p --output-format stream-json in fact runs on subscription auth with no API key and now emits a subagent_stats block (spawned / max_depth / refused) that did not exist in June — a ready-made classifier-interference counter for §5's feasibility guard. S12's other blocker (the installed plugin is the cache copy, so a repo-local agent is invisible to claude -p) stands unmeasured. This changes nothing about the §6 verdict; it lowers the cost of §5.

  • /trekresearch --engine deep-research: document the real version window. Claude Code 2.1.218 changed /deep-research to start only when the operator invokes it; from there the Skill tool refuses a model invocation outright with disable-model-invocation (measured in a real --engine deep-research run on 2026-09-01 — the SC3 fallback to swarm held). The engine was built against 2.1.196 and the prose still promised a path Claude Code has removed ("requires Claude Code 2.1.154+"). commands/trekresearch.md (flag bullet + pre-gate + fallback reason tokens), docs/command-modes.md and README.md now state the closed window 2.1.154 <= CC < 2.1.218 and name disable-model-invocation as the expected fallback reason on any current CC. The pre-gate gained an upper ceiling (still a numeric comparison, not a string one). The flag is kept as an additive opt-in that never hard-fails; no lib/ change, no adapter-contract change, no default change, no version bump. Pinned by tests/lib/doc-consistency.test.mjs.

v5.10.0 — 2026-08-18 — STORM bounded research loop (default-off) + the Agent-tool name spawn defect

Additive. Every new research mechanism ships inert: VOYAGE_STORM_ENABLED is unset by default, and with it unset both new /trekresearch phases are no-ops. The one change that affects consumers regardless of flags is the spawn rule under Fixed — it changes how any repo should call the Agent tool.

STORM bounded loop — shipped, default-off, behind a pre-registered adoption gate

  • /trekresearch Phase 4.5 (dimension discovery, under the existing maxDimensions: 8 ceiling) and Phase 5 (bounded multi-turn follow-up, replacing the single follow-up pass) run only at effort: high and only when VOYAGE_STORM_ENABLED=1. Unset, Phase 5 is inert because lib/util/research-loop-cap.mjs grants a budget of 0, and Phase 4.5 is inert because its skip-guard reads the flag directly (it never calls the cap) — two independent off-switches, so a bug in one does not silently activate the other.
  • TREKRESEARCH_MAX_CONV_TURNS (default 3; invalid values fall back to 3) sets turns per dimension. The total budget is that value × maxDimensions.
  • New lib/util/research-loop-cap.mjs: an append-only ledger the cap counts its own turns from. Each turn slot is claimed with O_EXCL, so the bound survives concurrent turns; an unreadable ledger fails closed in both modules; and the enforcement boundary is a denial tombstone rather than the turn count, so a crash mid-turn cannot hand back a free turn.
  • New hooks/scripts/pre-agent-cap.mjs, registered as a PreToolUse hook on WebSearch|WebFetch|Task: the budget is enforced by the harness, not by prose in a command file. VOYAGE_DISABLE_CAP_HOOK=1 switches it off. docs/spike-pretooluse-subagent-reach.md records the measured reach of PreToolUse into sub-agent tool calls — including where the gap is.
  • Five measurement fields (unique_sources, dimensions_baseline, conv_turns, empty_turns, dimensions_baseline_preserved) are emitted to trekresearch-stats.jsonl and allowlisted in lib/exporters/field-allowlist.mjs. All five are counters or booleans — none carry prose or paths.
  • scripts/storm-measure.mjs + docs/storm-measurement.md: the adoption gate, with thresholds registered before the first measurement by design. ≥ 30 % improvement on either metric → adopt; < 15 % → decline; an empty arm is insufficient-data, not a decline. Decline is a no-op — the mechanism simply stays default-off; adopt is one constant. No measurement has been run yet.

Added — outbound query privacy gate

  • lib/validators/query-privacy-gate.mjs inspects a research query before it leaves the machine, in the same two-tier shape as the existing SSRF gate: a WARN tier (absolute filesystem paths, repo-internal identifiers) that --soft / VOYAGE_QUERY_PRIVACY_ALLOW=1 can override, and a HARD-BLOCK tier (secret-shaped tokens) that nothing overrides. Called only from the two new high-effort steps; the existing single-pass path is unchanged.

Fixed — the Agent tool's name parameter silently breaks a subagent's return channel

  • Consumers of this pipeline should read docs/agent-return-channel-defect.md. Passing name to the Agent tool does not label a subagent — it changes what is spawned: taskKind: "in_process_teammate" / spawnDepth: 0 instead of a real subagent (spawnDepth: 1). A teammate's final text is not a return value; it reaches the parent only if the teammate itself calls SendMessage(to: "main"). Voyage's reviewer agents carry tools: [Read, Glob, Grep] — no SendMessage — so when named they are structurally unable to answer. No error, no warning. Measured numerators (66-line target): named without explicit SendMessage 0/5 returned · named + explicit SendMessage 1/1 · unnamed 3/3 · work actually performed while named 5/5 — only delivery fails, and the output is recoverable from ~/.claude/projects/<project>/<session>/subagents/agent-*.jsonl. Independently confirmed at 3730 lines / 277 KB by akashic-intelligence (4/4 correct final text on disk); the returning arm above 66 lines remains inferred rather than observed, and the doc says so.
  • The four spawning commands (trekbrief, trekplan, trekresearch, trekreview) now state the rule at their spawn sites and name the mechanism. trekexecute spawns nothing and is excluded. The doc-consistency test derives the spawning set from the command files, so the pin cannot go vacuous when a command starts or stops spawning.

Fixed — hook and validator hardening

  • The destructive-command rule anchored on command position rather than any substring (a path containing a blocked word no longer trips it), and the bypasses that anchoring itself opened are closed.
  • The secret-detection validator hard-blocks token formats the run-length patterns missed.
  • The exporter allowlist covers /trekresearch's engine field, with the JSONL schema fixture pinned to agree — a new stats field is otherwise dropped silently at export.

Docs

  • README: first screen aligned with the org repo standard, complete AI disclosure, and the Gemini MCP tool contract described inline instead of via a dead cookbook link. Governance keeps one canonical file, not a local copy.
  • /trekresearch: STORM mechanisms documented across four surfaces; the Independence crossing's two risks split, each naming its own control.
  • docs/*.pdf is gitignored — origin is a public mirror and must never carry operator PDFs.

Tests

  • Suite baseline 832 (830 pass / 0 fail / 2 skip) → 1013 (1011 / 0 / 2). New coverage: research-loop-cap (including the concurrency and fail-closed paths), the cap hook's crash-time marker branches, the query privacy gate, the measurement harness's decision rule, and the spawn-rule doc pin.

v5.9.1 — 2026-07-03 — Fix /trekendsession load-time crash (eager-exec placeholders)

Patch, no functional additions.

Fixed

  • /trekendsession was unusable in every invocation: two of its three !`...` eager-exec blocks (Phase 3 atomic-write, Phase 4 validator call) contained unresolved runtime placeholders (<project-dir> etc.). The harness executes eager-exec blocks at command LOAD time, so zsh parsed <project-dir> as input redirection and the command aborted before the model saw a single instruction. Both blocks are now plain runtime Bash fences with the {curly} placeholder convention (shell-inert), matching trekplan.md/trekresearch.md. The Phase 1 discovery block (self-contained) keeps its legitimate eager-exec prefix; trekcontinue.md's discovery block was runtime-verified unaffected.
  • Latent secondary bug in the same blocks: cwd-relative plugin paths (lib/validators/..., ./lib/util/atomic-write.mjs) would have failed with ERR_MODULE_NOT_FOUND even after substitution, since the Bash cwd is the user's repo. Both now use absolute ${CLAUDE_PLUGIN_ROOT} paths per the existing command convention (Node ESM accepts absolute-path import specifiers — verified on Node 18+).

Added

  • Regression guard tests/commands/trekendsession.test.mjs: scans every !`-block in commands/*.md for unresolved <angle>/{curly} placeholders (this bug class is silent until first invocation), plus structure tests pinning Phase 3/4 as runtime Bash with ${CLAUDE_PLUGIN_ROOT} paths and exactly one surviving eager block. Suite baseline 828 → 832 (830 pass / 0 fail / 2 skip).

v5.9.0 — 2026-07-02 — Fable model tier + deep-research engine

Additive, plus one behavior alignment: profile phase_models now reach sub-agent spawn sites (previously documented but never wired), and the seven command orchestrators no longer pin model: opus — frontmatter omits model:, so the orchestrator follows the session model.

Fable model tier

  • fable (→ Claude Fable 5, Mythos-class, positioned above Opus) is an accepted model value throughout the validation chain: BASE_ALLOWED_MODELS widened to ['sonnet', 'opus', 'fable'] in lib/validators/profile-validator.mjs — the single source imported by brief-validator and phase-signal-resolver (two-layer gate preserved; accept-fable AND reject-unknown-model covered at both layers). No env gate — haiku's VOYAGE_ALLOW_HAIKU opt-in stays as-is.
  • /trekbrief Phase 3.5 tier loop offers a 4th option: fable → {effort: high, model: fable}. AskUserQuestion's 4-option maximum is now fully used — a 5th tier requires a loop redesign. The fable tier reuses effort: high orchestration semantics; EFFORT_LEVELS is unchanged.
  • New built-in profile lib/profiles/fable.yaml (all six phases on fable, modeled on premium; registered in BUILTIN_NAMES with a loadProfile('fable') canary test so a registry regression fails loudly instead of silently resolving premium). Premium stays the default.
  • Reasoning effort is inherited from the session: Fable 5's default effort is high, NOT xhigh, and switching model resets effort — set xhigh at session level (/effort xhigh, the effortLevel setting, or CLAUDE_CODE_EFFORT_LEVEL). Documented canonically in docs/profiles.md §Model & effort axes.
  • claude-fable-5 added to the cost PRICE_TABLE ($10/MTok input, $50/MTok output; cache write 5m $12.50 / 1h $20; cache read $1 — verified 2026-07-02 against the official platform pricing docs). PRICE_TABLE_VERSION bumped to 2026-07-02. Without the entry, every fable run would report cost_usd: null in the observability export.
  • Profile tables + allowlist prose updated across README, docs/profiles.md, docs/operations.md, docs/HANDOVER-CONTRACTS.md, docs/architecture.md, docs/command-modes.md, templates, and CLAUDE.md; the S15 doc pins now machine-check the fable row cell-for-cell against fable.yaml. The ^(opus|sonnet)… regex claim in two docs was corrected — validation is an exact string match against BASE_ALLOWED_MODELS; the regex never existed in code.

Behavior alignment: profile phase_models now reach sub-agent spawns

  • Pre-existing wiring gap (found in exploration): all four pipeline commands invoked only the brief-only phase-signal-resolver.mjs, so the ?? profile.phase_models[<phase>] half of the documented composition rule never executed — --profile <x> never reached sub-agent spawns.
  • Fixed with a single composed resolver: resolver.mjs --resolve-phase-model now returns {effort, model, source} (brief > profile > default, with effort passed through atomically) and is the one CLI the four pipeline commands invoke. A doc-consistency pin requires the composed invocation and forbids the brief-only CLI in command Bash blocks.
  • Behavior change (contract alignment): --profile economy/balanced now genuinely reaches sub-agent spawn sites for the first time — behavior aligns with what the docs have long claimed. The premium default is unaffected in practice (premium resolves opus, which equals the frontmatter fallback).
  • Command frontmatter: the model: opus line is DELETED from all seven commands — omission (not the disputed inherit literal) is the spelling both official surfaces document as session-inheritance, guarded by a frontmatter-absence doc pin. Accepted tradeoff: in a sonnet session the orchestrator runs on sonnet; re-add a frontmatter pin for deterministic orchestrator choice. The 24 agents/*.md model: opus pins are untouched (spawn-time injection wins; frontmatter is the fallback). /trekcontinue//trekendsession spawn no exploration swarm and get no spawn-site injection; the continue phase is covered at resolver level and follows the session model.

Bundled unreleased work (since v5.8.0)

  • /trekresearch --engine {swarm|deep-research} (581489a..9374820): opt-in delegation of the external research phase to Claude Code's built-in /deep-research workflow, with in-context adapter + self-check, availability fallback to swarm (never hard-fails), and doc-consistency pins across surfaces.
  • brief-validator CLI no-flag invocation fix (926b768).
  • Deep-research engine research notes + docs (60e9e7a, 9d8e043).

Operator + consume-side notes

  • The operator-global CLAUDE.md policy "Opus 4.8 default for all subagents" predates the fable tier; updating it is an operator action outside this repo.
  • /plugin update compares against a stale local marketplace clone and can report "already at the latest version" after this release (Claude Code issues #35752 / #38271, both closed-not-planned). Reliable refresh: remove + re-add the marketplace, or git pull --ff-only in the marketplace clone. Cross-version skew consequence: a stale cached v5.8 brief-validator REJECTS fable-bearing briefs with BRIEF_INVALID_MODEL — enum widening is safe for new readers of old data, not old readers of new data.
  • Org availableModels with enforceAvailableModels: true can make an inheriting orchestrator silently fall back to the first allowed model.

Release hygiene

  • Suite (measured with bare npm test at release): 828 (826 pass / 0 fail / 2 skipped) — +17 over the pre-release ground-truth baseline of 811 measured 2026-07-02 (allowlist/gate coverage, fable profile pins, composed-resolver + frontmatter-absence doc pins, PRICE_TABLE case).
  • Version sync: plugin.json, package.json, package-lock.json, README badge, CHANGELOG top entry all at 5.9.0, guarded by doc-consistency.test.mjs.

v5.8.0 — 2026-06-30 — offline gold-scored output eval (SKAL-1·4b)

Additive — no behavior change, no breaking change. Internal eval infrastructure only (lib/ + tests/ + docs); no command, agent, profile, or Handover contract touched.

Gold-scored output eval (SKAL-1·4b)

  • The review-coordinator self-eval gains its scoring run, building on the deterministic coordinator contract + golden corpus shipped as the 4a foundation in v5.7.0.
  • lib/review/gold-scorer.mjs: scoreFindings(runFindings, goldFindings) matches at (file, rule_key) granularity (line + severity deliberately ignored) → { tp, fp, fn, precision, recall, f1, matched, missed, spurious }; scoreVerdict checks exact verdict match. Pure — no I/O, no LLM, no network. Vacuous-set conventions (empty run → recall 0; empty gold → precision 0; f1 collapses to 0) are documented in the module header.
  • tests/fixtures/bakeoff-rich/runs/run-perfect.json: the first committed run — reviewer payloads that, fed through runContract, reproduce all 5 seeded gold findings. The regression guard: any future contract change that silently suppresses or skips a seeded finding breaks the eval.
  • tests/lib/gold-eval.test.mjs: the scoring run, wired into node --test. Asserts run-perfect scores precision/recall/f1 = 1.0 and verdict == expected_verdict (BLOCK). Offline: committed payloads, no live agent spawn (the LLM-in-the-loop grading is the separate 4c tier).
  • Third test-census category. lib/util/test-census.mjs now reports a goldEval bucket (matched by GOLD_EVAL_FILE_RE) separately from behavior and docPins — a scoring run is neither behavior coverage nor a prose pin, so the honest-count invariant is a 3-way sum.
  • docs/eval-corpus/README.md: SKAL-1·4b moved from "Future hardening" to an implemented section documenting the scorer, run format, and census category.
  • Suite: 822 (820 pass / 0 fail / 2 skip), up from 809 (+10 scorer behavior tests, +3 eval scoring-run tests). The scorer test covers the discriminating paths (false negatives + false positives) and the degenerate empty-run / empty-gold cases, not merely the all-match case.
  • Version sync: plugin.json, package.json, package-lock.json, README badge, CHANGELOG top entry all at 5.8.0, guarded by doc-consistency.test.mjs.

v5.7.1 — 2026-06-29 — relocate agent <example> blocks to body (always-loaded token trim)

Performance/packaging change — no behavior change, no breaking change. (M4)

Always-loaded token trim

  • The 17 example-bearing agents each carried two <example> blocks (34 total) inside their description: frontmatter. voyage launches its agents by name from the orchestrator commands, so those auto-selection examples were paying a per-turn token tax for a path the pipeline never uses. They are now relocated verbatim into each agent's body under a ## When to use — examples section — preserved, not deleted.
  • Frontmatter description chars across all 24 agents: 17,672 → 4,945 — roughly 3,180 fewer always-loaded tokens per turn for every session with voyage enabled. The 7 zero-example agents are untouched; no system prompt, tools, model, or name changed.
  • New invariant test in tests/lib/agent-frontmatter.test.mjs: no <example> in any frontmatter description, and ≥ 34 <example> retained across agent bodies (relocation moves, never deletes). Suite: 807 pass / 0 fail / 2 skip.
  • The saving only reaches a machine after /plugin marketplace update + reload — the delta is not instant on the machine that ships the release.
  • Version sync: plugin.json, package.json, package-lock.json, README badge, CHANGELOG top entry all at 5.7.1, guarded by doc-consistency.test.mjs.

v5.7.0 — 2026-06-26 — opt-in token/cost metering (SKAL-2) + eval foundation (SKAL-1·4a)

Additive — no breaking change. Two unreleased work-streams land together.

Opt-in token/cost metering (SKAL-2) — the headline

  • Pure token-usage parser + cache-aware USD cost (lib/stats/token-usage.mjs): parses MAIN-CONTEXT usage from the transcript, dedups by requestId (last-wins, streaming-placeholder mitigation), excludes sidechain records, and REFUSES to estimate (cost_usd:null, is_estimate:true) for models absent from the frozen PRICE_TABLE.
  • CWE-212 export boundary: token-usage schema allowlist in the OTLP exporter; session_id/transcript_path/cwd stripped at export, asserted both ways.
  • Cross-session aggregation in cache-analyzer (total tokens + cost).
  • Capture folded into the EXISTING otel-export.mjs Stop hook, gated behind the VOYAGE_TOKEN_METER env var (default off), fail-open. v1 scope = main-context only; sub-agent turns are a documented v2 follow-on.

Eval foundation (SKAL-1·4a)

  • gold.json golden corpus + loader/validator; review-coordinator contract reference impl + deterministic test; two-sided gate coverage for the BRIEF_* BLOCKERs; eval-corpus frozen-failure home.

Release hygiene

  • Version sync: plugin.json, package.json, package-lock.json, README badge, CHANGELOG top entry all at 5.7.0, guarded by doc-consistency.test.mjs.
  • Canonical node --test: 807 (805 pass / 0 fail / 2 skipped).

v5.6.1 — 2026-06-24 — leaner always-loaded agent listing (reference/dormant agent descriptions trimmed)

Additive — no breaking change, no runtime behavior change. Trims the always-loaded token cost of the agent listing that Claude Code injects into every session.

Reference/dormant agents now carry one-line descriptions

  • The 3 *-orchestrator reference docs (planning-/research-/review-orchestrator) and the dormant synthesis-agent carried multi-paragraph description: frontmatter (full rationale + CC-2.1.172 history + a usage example) that Claude Code injects into every session — despite none of them being spawnable from the live /trek* pipeline. Their description: is now a single line; the full rationale already lives, and remains, in each file's body. ~700 tokens trimmed from the always-loaded agent listing, no capability change.
  • The three orchestrators retain the self-declaration "reference document, not a spawnable capability" (pinned by doc-consistency.test.mjs); synthesis-agent retains its DORMANT / not-wired flag and the docs/T1-synthesis-poc-results.md pointer.
  • Surfaced via dogfooding with config-audit's always-loaded token audit. Canonical node --test: 754 pass, 0 fail (756 total, 2 skipped); the agent-inventory + frontmatter pins stay green.

Version sync

  • plugin.json, package.json, package-lock.json, the README badge, and the CHANGELOG top entry all at 5.6.1, guarded by the version-consistency test in tests/lib/doc-consistency.test.mjs.

v5.6.0 — 2026-06-20 — /trekexecute loop hardening: machine-verifiable completion + bounded recovery

Additive — no breaking change. Hardens the /trekexecute execution loop so termination is machine-verifiable and recovery is bounded by an explicit budget, closing the "runs forever" and "declares done without proof" failure modes. Five focused changes; canonical node --test 744 → 756 (0 fail).

Machine-verifiable completion gate (the headline)

  • Stop-signal contract — /trekexecute reports completed only when a machine-checkable contract holds: the Phase 7.5 manifest audit PASSes, the stop signal exits 0, and the success criteria are green. Hard Rule 18 is promoted from prose guidance to an enforced gate, anchored in the Phase 7.5 audit rather than the model's self-assessment.

Bounded recovery — cap hierarchy + global budget

  • TREKEXECUTE_MAX_RECOVERY_ITERATIONS — a global recovery-iteration budget (default 25, env-overridable) sits above the per-step caps as a three-axis cap hierarchy (recovery depth · per-step retry · global budget), codified as Hard Rule 20. Stops an unbounded recover→retry→recover spiral that the per-step caps alone could not bound.
  • iterations_remaining signal — surfaced in the progress schema and the summary JSON, with a deterministic gate cross-check (iterations_remaining == cap − (recovery_depth + Σ attempts-beyond-first)) that catches a never-decremented counter. Shape-validated in lib/.../progress-validator.mjs (PROGRESS_ITERATIONS_REMAINING_INVALID: non-negative integer, additive-optional — never required at top level).

Doc consistency

  • Fan-out hedge harmonized — the CLAUDE.md design-principle line is aligned to the measured claim (parallel wall-clock + structured artifact handoffs as the load-bearing benefit; main-context relief stays explicitly not demonstrated), with a banned-phrase forward-guard in tests/lib/doc-consistency.test.mjs so the over-claim cannot reappear.

Release hygiene

  • Version sync — plugin.json, package.json, package-lock.json, the README badge, and the CHANGELOG top entry all at 5.6.0, guarded by the version-consistency test in tests/lib/doc-consistency.test.mjs.

v5.5.0 — 2026-06-18 — Coordinated release: brief framing enforcement (2.2) + W1–W3 narrow wins

The coordinated release held since the framing work. Supersedes the unreleased internal milestones v5.2–v5.4 (W2 model/effort alignment, W3 guardrail hardening, the Handover-1 public-contract formalization), landing them together with the brief_version 2.2 schema badge and the W1 narrow wins. Additive — no breaking change for existing consumers: every 2.0/2.1 brief still validates; the new requirements gate only on briefs that declare brief_version: "2.2".

Brief framing enforcement — brief_version 2.2 (the headline)

Three version-gated layers ship at brief_version ≥ 2.2, implementing the CLAUDE.md cross-cutting invariant "brief framing must match operator intent":

  • framing enum (preserve | refine | replace | new-direction) — required in frontmatter, collected in /trekbrief Phase 2.5 before any prose is written, non-skippable even in --quick. Enum-checked on any version (BRIEF_INVALID_FRAMING); missing at ≥ 2.2 → BRIEF_MISSING_FRAMING.
  • Memory-alignment dimension — new brief-reviewer dimension 6 compares brief Intent/Goal + framing against operator memory, flagging explicit contradictions only (scores N/A when no memory is supplied); wired to the Phase 4e gate (memory_alignment.score ≥ 4). Emits a status field (verified | n_a | contradictions) so a score-5 N/A (no memory available) is distinguishable from a score-5 verified-aligned brief — the gate passes in both cases, and status is what tells the operator whether the wrong-premise defense actually ran.
  • Obligatory ## TL;DR — ≤ 5 content lines at the top of every 2.2 brief (soft cap → BRIEF_TLDR_TOO_LONG).
  • Opt-in version floor — --min-brief-version <ver> on /trekplan + /trekresearch (forwarded to the validator as --min-version) raises a BRIEF_VERSION_BELOW_MINIMUM warning — never a block — when a brief declares a version below the floor. Closes the producer-elective hole where a 2.0/2.1 brief silently sidesteps framing enforcement; docs/HANDOVER-CONTRACTS.md §Handover 1 now documents pre-2.2 = zero framing enforcement and the two remedies (require 2.2 upstream, or pass the floor flag).

Existing 2.0/2.1 briefs stay valid (forward + backward compatible), mirroring the phase_signals ≥ 2.1 precedent. trekreview briefs are exempt.

Public contract formalization (Handover 1)

docs/HANDOVER-CONTRACTS.md §Handover 1 (brief.md → research) is now labeled PUBLIC CONTRACT — the only public integration boundary of the pipeline. Froze brief_version 2.1 as the baseline, then evolved it to 2.2 under the breaking-change protocol. Any conforming producer (not just /trekbrief) may feed Voyage; brief-schema changes are breaking for every downstream consumer.

Model & effort alignment (W2)

  • Opus 4.8 baseline — the opus alias resolves to Opus 4.8 (default reasoning effort high).
  • Native effort: frontmatter (additive, static) on 8 agents: retrieval (task-finder, git-historian, dependency-tracer, architecture-mapper) → medium; adversarial-reasoning (plan-critic, risk-assessor, contrarian-researcher, review-coordinator) → high. The other 15 agents inherit the Opus-4.8 default.
  • Resolver model-gate fix — lib/profiles/phase-signal-resolver.mjs now gates model against BASE_ALLOWED_MODELS (mirrors the existing effort gate); out-of-allowlist models are dropped rather than handed to a spawn.
  • Axis distinction documented — docs/profiles.md §Model & effort axes separates orchestration phase_signals.effort (which agents/passes run) from native reasoning effort: (per-spawn budget) — different axes that happen to share the name effort.

Guardrails & hooks hardening (W3)

  • Exec-form hooks (CC-14) — all 7 hooks in hooks/hooks.json migrated to {command:"node", args:["${CLAUDE_PLUGIN_ROOT}/…"]}, removing a class of path-quoting bugs for consumers who install Voyage under a path containing spaces.
  • disallowed-tools enforcement (CC-11) — disallowed-tools: Agent, TeamCreate added to /trekexecute, promoting its documented no-delegation rule from prose to enforcement (allowed-tools grants auto-approval but does not remove a tool from the pool; disallowed-tools does).
  • Universal safety executors (CC-15) — pre-bash-executor.mjs / pre-write-executor.mjs confirmed universal by design (session-agnostic safety; narrowing to execute-only sessions would only weaken protection).

Narrow wins (W1 — NW1–NW3)

  • NW1 — reviewer-output schema contract (ungated, shipped). lib/review/findings-schema.mjs validates each /trekreview Phase 5 reviewer's JSON against a schema; on schema failure main re-asks for conforming JSON (bounded N=2), retiring the fragile "collect trailing JSON / re-ask on parse error" contract.
  • NW2 — trekreview Workflow port as opt-in --workflow flag. Phase 5–6 (parallel([conformance, correctness]) → plain-JS dedup-by-(file,line,rule_key) → agent(coordinator)) ported to a Workflow script, reachable via --workflow (default stays prose, preserving the 2.1.154+ portability floor). Bake-off verdict opt-in-defensible (POSITIVE on the measured axes — fidelity-equivalent review.md, zero classifier interference at 9-agent concurrency, ≈ +4.4% tokens — but on a single un-archived run: the raw per-run data was never committed, so the numbers cannot be re-derived; see docs/T2-bakeoff-results.md §Reproducibility caveat).
  • NW3 — synthesis-agent shipped dormant (declined per measurement). Built + measured deterministically: Δ main-context = 0% at all realistic BASE — delegating only trekplan Phase 7 evicts nothing, since the Phase-5 foreground reads make the outputs resident first. Not wired; re-measurement is cheap via scripts/synthesis-measure.mjs. See docs/T1-synthesis-poc-results.md.

CC 2.1.130→181 verification dispositions

  • Verified clean (no regression): CC-29 (subagent_type matching now case/separator-insensitive; no Voyage agent declares multiple Agent(...) types), CC-31 (the tightened background worktree-isolation guard aligns with Voyage's intent — /trekplan TeamCreate isolation:"worktree" with sequential fallback, /trekexecute Phase 2.6 worktree waves).
  • CC-08 — GH #36071 (hooks in headless claude -p) closed as NOT PLANNED, not fixed. The in-prompt safety preamble is retained as the headless defense.
  • Deferred (recorded, no code): CC-07 (fallbackModel), CC-12 (Stop/SubagentStop additionalContext), CC-13 (background_tasks/session_crons in hook input). Triggers noted in docs/cc-upgrade-2.1.181-decision-matrix.md §S13.

Release hygiene

  • Version sync — plugin.json, package.json, README badge, and the CHANGELOG top entry all at 5.5.0, guarded by a new version-consistency test in tests/lib/doc-consistency.test.mjs.
  • Honest test count (S19) — lib/util/test-census.mjs + tests/lib/test-census.test.mjs report the behavior-test count separately from the doc-consistency prose-pin count, so the cited total no longer oversells behavior coverage. Pruned 3 redundant/tautological prose-pins from doc-consistency.test.mjs (each provably subsumed by a structural invariant or behavior test). Devil's-advocate audit §Top changes #8.
  • claude plugin validate passes. The single advisory warning (root CLAUDE.md not loaded as consumer project context) is accepted by design: it is universal across all marketplace plugins, validation still passes, and the root CLAUDE.md is repo/maintainer context — consumer context ships via README + command/agent frontmatter.

v5.1.1 — 2026-05-14 — Remediation patch (11/12 review findings closed)

Additive. No breaking changes against v5.1.0. Closes 11 of 12 BLOCKER/MAJOR/MINOR findings from the v5.1.0 review (sesjon 5, review.md SHA range 8cbb33e..8f4b79c). SC8 dogfood gate (#5) is scheduled for sesjon 8 as a fresh-CC-session operator action — its closure cannot happen inside the v5.1.1 execute session.

Bug fixes (load-bearing)

  • #8 YAML-number bypass closed. lib/validators/brief-validator.mjs now coerces brief_version to string before comparison; both brief_version: 2.1 (parsed as Number) and brief_version: "2.1" (parsed as String) trigger the v5.1+ sequencing gate. Previously the unquoted form silently bypassed the gate. Three regression tests added in tests/validators/brief-validator.test.mjs.
  • #11 Doc-consistency pin lock-in. tests/lib/doc-consistency.test.mjs pins templates/trekbrief-template.md to emit brief_version: "2.1" (quoted) so future template edits can't reintroduce the bypass.

Wiring (closes #9 + #12)

  • lib/profiles/phase-signal-resolver.mjs helper (new). Reads brief.phase_signals (or phase_signals_partial) and the active profile's phase_models, returns the resolved {effort, model, source} per phase. Composition rule: brief signal wins per-phase, profile fills gaps. The resolver controls only the orchestrator and the model parameter at Agent-spawn sites — sub-agents otherwise read model: from their own agents/*.md frontmatter (still pinned to opus).
  • 4 downstream commands wired. /trekplan, /trekresearch, /trekreview, /trekexecute each invoke the resolver in their Phase 1 (or equivalent first-phase block), capture the result as phase_signal_result, and pass it to Agent tool calls explicitly. Per-command low-effort code-paths reuse existing --quick-equivalent logic.
  • resolvePhaseModel orchestrator-override added (#9 part A). Profile-tier model picks are overridden when brief.phase_signals[<phase>].model is set. Non-interference verified by new test tests/lib/profile-resolver.test.mjs (Step 7 TDD pair, Red→Green).
  • brief-validator --soft gate required uniformly in /trekresearch + /trekexecute (previously only /trekplan + /trekreview). BRIEF_V51_MISSING_SIGNALS halts all 4 commands with a clear hint pointing back to /trekbrief.

Test refactor (closes #1 #2 #3 #4 #6 #7 #10)

  • Runtime SC1 walk for tests/commands/trekbrief.test.mjs (#1). Replaces prose-grep with resolvePhaseSignal invariant: returns non-null for all 4 entries in PHASE_SIGNAL_PHASES when applied to a fixture brief with a committed phase_signals block; returns gate-fire when applied to a v2.1 brief missing the block.
  • Per-tier resolver-output + missing-signals falsification (#2 #3 #6 #10). tests/commands/trekplan.test.mjs, trekresearch.test.mjs, trekreview.test.mjs, trekexecute.test.mjs each refactored from doc-pin pattern to runtime assertion against 4 new fixture briefs (tests/fixtures/briefs/{low,standard,high,partial}.md).
  • Dedicated SC5 profile-resolver non-interference test (#7). tests/lib/profile-resolver.test.mjs asserts that brief-emitted signals are not overridden by VOYAGE_PROFILE, and that --profile does not silently override brief-emitted answers.
  • #4 SC5 invariant locked at resolver level rather than test-strategy level (no scope expansion — see source_findings audit trail in plan.md frontmatter).
  • Total test delta: +12 tests (539 baseline + 12 + 4 doc-pins from Step 10 = 555 expected; actual 578 because the existing tests grew underneath us during the v5.1.0→v5.1.1 cycle). 0 fail, 2 skipped.

Documentation (closes #5 scheduling + Decision B high-effort)

  • #5 SC8 dogfood scheduling. REMEMBER.md (gitignored) gains a ## v5.1.1 sesjon 8 — DOGFOOD GATE OBSERVATIONS reserved placeholder with concrete procedure: fresh CC-session → real v5.1-eligible task → Phase 3.5 observation → 5 specific questions to answer. The actual observation is a sesjon 8 manual operator action; sesjon 7 produces scaffolding only.
  • Decision B high-effort behavior locked per command (operator-confirmed, decisions.local.json):
    • /trekplan high: gemini-bridge plan-review Pass 2 on the post-revision plan (replaces fragile plan-critic doubling per risk-assessor finding — line numbers shift after revisions, breaking dedup triplets).
    • /trekresearch high: full swarm + contrarian-researcher AND gemini-bridge always-on regardless of normal triggering rules.
    • /trekreview high: skip Pass 3 reasonableness filter; coordinator applies PLAN_EXECUTE_DRIFT normalization for unknown rule_keys (preserves original in original_rule_key).
    • /trekexecute high: gates_mode = 'closed' automatically; explicit --gates flag still wins.
  • Brief Non-Goal amendment (.claude/projects/2026-05-13-trekflow-solo-lane/brief.md, gitignored): low/high effort tiers now locked in v5.1.1; standard remains fallthrough default. Continue + brief phases remain effort-less.
  • Brief SC1 amendment (same file, gitignored): SC1 "4 AskUserQuestion calls" interpreted as the resolver-invariant resolvePhaseSignal returns non-null for all 4 entries in PHASE_SIGNAL_PHASES. The literal AskUserQuestion mocking interpretation would require a state-machine harness module (significant scope expansion); the resolver-invariant interpretation is authorized as equivalent. Operator-confirmed via Pre-Step-10 autonomy gate.

Known scheduling

SC8 (#5) dogfood-gate closure happens in sesjon 8 (fresh CC-session, manual /trekbrief walk-through). v5.1.1 push to Forgejo gated on sesjon 9 /trekreview returning ALLOW. If sesjon 9 returns BLOCK, loop back to sesjon 6 (new remediation plan).

Source findings audit trail

Plan-frontmatter source_findings: lists the 12 review-finding IDs each step closes. Audit trail traces review.md → /trekplan --brief review.md (Handover 6) → plan.md → /trekexecute → individual commits.

v5.1.0 — 2026-05-13 — Per-phase effort + model dialog

Additive. No breaking changes. Forward-compat with all v5.0.x briefs.

Why

The voyage pipeline runs a single profile-tier setting for every task. For typo fixes and small bugfixes the full brief → research → plan → execute → review ceremony is over-engineered; for risky migrations the same profile-tier is too thin. v5.1 hands ceremony-level back to the operator per phase in the same dialog that produces the brief — without removing the disciplined defaults that protect high-stakes work. Independent of v4.1's profile system: composition happens at the command level (brief signal wins per-phase, profile fills gaps). No /trekflow, no helper module, no per-command effort dictionary — composition is documented prose in each downstream command.

Added

  • /trekbrief Phase 3.5 — between Phase 3 completeness exit and Phase 4 draft, 4 tier-coupled AskUserQuestion calls commit an effort level (low | standard | high) and an optional model (sonnet | opus) per downstream phase (research, plan, execute, review). Tier mapping: low → {effort: low, model: sonnet}, standard → {effort: standard} (model omitted; composition falls through to profile), high → {effort: high, model: opus}. Force-stop pattern (Phase 4f verbatim) records phase_signals_partial: true instead. --quick skips Phase 3.5 entirely and auto-writes phase_signals_partial: true.
  • brief-validator extension — 6 new issue codes: BRIEF_INVALID_PHASE_SIGNALS, BRIEF_INVALID_PHASE_SIGNAL_PHASE, BRIEF_INVALID_EFFORT, BRIEF_INVALID_MODEL, BRIEF_SIGNALS_MUTUALLY_EXCLUSIVE, BRIEF_V51_MISSING_SIGNALS + exported PHASE_SIGNAL_PHASES + EFFORT_LEVELS constants. The BASE_ALLOWED_MODELS const in lib/validators/profile-validator.mjs was promoted to export const so the brief validator can re-use it.
  • HANDOVER-CONTRACTS amendments — Handover 1 gets 5 inserts: versioning row → 2.1, two new schema-table rows (phase_signals, phase_signals_partial), v5.1 sequencing-gate validation row, versioning-paragraph expansion explaining the version-conditional gate, 6 new failure-mode bullets.
  • Template bump — templates/trekbrief-template.md → brief_version 2.1 with a default phase_signals: block (4 phases × effort: standard, model omitted) and a commented phase_signals_partial: true line showing the force-stop alternative.
  • Composition rule (v5.1) — new ## Composition rule (v5.1) sub-section in each of commands/{trekplan,trekresearch,trekexecute, trekreview}.md. Documents effort_for_phase = brief.phase_signals[ <phase>]?.effort ?? 'standard' and model_for_phase = brief.phase_signals[<phase>]?.model ?? profile.phase_models[<phase>]. Per command: effort == low activates that command's existing --quick-equivalent code-path (/trekplan skips Phase 5 agent swarm, /trekresearch inline research, /trekreview correctness-only, /trekexecute --gates open + sequential-only).
  • Sequencing-gate surface in 4 downstream commands — when brief-validator.mjs returns BRIEF_V51_MISSING_SIGNALS in errors, halt with a one-line user-readable message pointing back to /trekbrief. Enforcement is validator-only.
  • 5 new minimal command test files under tests/commands/ — trekbrief.test.mjs (3 cases), trekplan.test.mjs / trekresearch.test.mjs / trekreview.test.mjs (2 cases each), trekexecute.test.mjs (2 cases). Pattern D (read .md, assert prose patterns). Verifies sequencing-gate surface + low-effort prose.
  • 5 new doc-consistency pins — template brief_version 2.1 + phase_signals: block, HANDOVER schema rows, voyage CLAUDE.md + README.md mention phase_signals.
  • 2 new fixtures — tests/fixtures/brief-with-phase-signals.md + brief-without-phase-signals.md (backward-compat).

Changed

  • brief_version bumped 2.0 → 2.1. The bump exists because v2.1 activates the version-conditional sequencing gate — the only check in the brief validator that triggers on brief_version rather than field-presence. The forward-compat policy still applies to the field itself (unknown frontmatter keys flow through).

Notes

  • Test count grows by ≥ 17 new cases minimum: 6 brief-validator + 11 command-test minimums. Realistic delta is ~25 new cases (Step 6 adds 5 doc-consistency pins on top). Target ≥ 533 pass at Step 10 verify.
  • MIGRATION.md was deliberately NOT created — v5.1 is an additive minor (brief_version 2.0 → 2.1, not major). v5.4 may promote phase_signals from optional to required (breaking change → 3.0).
  • High-effort behaviors for /trekplan / /trekresearch / /trekreview are deferred to v5.1.1 per brief Non-Goal ("No complete per-phase effort dictionary"). v5.1 locks only the low-effort floor.
  • phase_signals_present stats emission is also deferred to v5.1.1 (opt-in observability per Research 03 Q5).

v5.0.3 — 2026-05-13 — Annotation UX matches the operator's reference

No new breaking changes beyond v5.0.0. Forks consuming v5.0.2's annotation HTML keep working — the file path and entry point are unchanged. The internal localStorage key bumps from voyage-annotate: to voyage-annotate:v2: to avoid mixing the v5.0.2 shape (line-click, freeform notes) with the v5.0.3 shape (intent-tagged annotations).

Why

v5.0.2 shipped a too-simple annotation surface: click a line, write a freeform note, save. The operator pointed at an existing annotation surface in another project as the actual reference — pencil-toggle mode, text-selection capture, three intent categories (Fiks / Endre / Spørsmål), a popover form at the cursor, structured markdown export with intent labels. v5.0.3 brings scripts/annotate.mjs up to that pattern.

This reference had been mentioned by the operator early in the conversation; the iteration through v5.0.0 / v5.0.1 / v5.0.2 reflects me reading past it and trying alternatives instead of just matching it. The loss is real and is documented here in plain terms so future maintainers don't repeat it.

Changed

  • scripts/annotate.mjs — rewritten to match the reference annotation UX:
    • Article rendering — markdown is rendered to proper HTML elements (<h1>/<p>/<ul>/<li>/<table>/<blockquote>/<pre>), not as line-numbered raw lines. Document reads as a normal article.
    • Annotatable elements — every heading, paragraph, list item, table cell, blockquote, and code block gets a stable data-anchor-id.
    • Pencil-toggle button in the topbar — annotation mode default ON. Toggle OFF to read normally and follow links.
    • Click any annotatable element (in mode) → opens a form popover at the cursor with: section context (auto-detected from nearest h1/h2), anchored snippet (the exact selected substring via window.getSelection() if any text is highlighted, else the element's text content up to 200 chars), three intent buttons (Fiks / Endre / Spørsmål), comment textarea, Cancel + Save. Save is disabled until an intent is picked.
    • Sidebar panel — collapsed by default; "Show annotations" button in the topbar opens it. Annotations grouped by section, sorted by document order. Each card shows the intent badge (colored by category), the anchored snippet, the operator comment, and a delete button. Click a card to scroll the article to that element + flash highlight.
    • Copy Prompt — structured markdown: ### N. [Intent] Section: <section> + Quote: «<snippet>» + Comment: <text>. Copies to clipboard.
    • Clear all — wipes every annotation for the current artifact (after confirm).
    • Persistence — localStorage key voyage-annotate:v2:<abs path>. Refresh/close/reopen the same HTML keeps every annotation.
    • Toast feedback for save / copy / clear.
  • tests/scripts/annotate.test.mjs — refreshed for the v5.0.3 shape: pins the three intent buttons (data-intent="fiks" / "endre" / "spørsmål"), form popover, selection capture, section auto-detect, voyage-annotate:v2: storage key prefix, data-anchor-id coverage, Copy Prompt + Clear all affordances, and the markdown renderer's heading / list / table / blockquote / code-fence output. 12 tests (up from 10), all passing.

Notes

  • The producing commands (/trekbrief Step 4g, /trekplan Phase 10, /trekreview Phase 8) call scripts/annotate.mjs the same way as in v5.0.2 — no change to their wiring beyond the build-output now being the v5.0.3 interactive surface.
  • npm test: 518 tests, 516 pass, 0 fail, 2 skipped (up from 516 — 2 new annotate tests for hostile-content escape + renderMarkdown table/ blockquote coverage).
  • Reference: the annotation UI section of the existing surface the operator pointed at.
  • Version bump 5.0.2 → 5.0.3 in .claude-plugin/plugin.json, package.json, package-lock.json, plugin README.md badge.

v5.0.2 — 2026-05-13 — Operator-driven annotation HTML (the actual fix)

No new breaking changes beyond v5.0.0. Forks that consumed the v5.0.1 /playground document-critique invocation from the producing commands' final report should switch to opening the .html that scripts/annotate.mjs now produces directly.

Why

v5.0.0 added a read-only scripts/render-artifact.mjs HTML render that didn't afford annotation. v5.0.1 deleted that and pointed operators at /playground document-critique instead — but the document-critique template pre-generates Claude's suggestions and asks the operator to approve/reject them. The operator asked for the opposite: a surface where they select content and write their own notes, then ship those notes back to Claude. v5.0.1 still missed the actual ask.

v5.0.2 ships scripts/annotate.mjs — a small, focused, zero-dependency Node script that 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 attach their own note, keeps a sidebar of all notes (editable + deletable, persisted in localStorage per artifact path so refresh doesn't lose work), and exposes a "Copy Prompt" button that gathers every note into one structured prompt. The operator copies that prompt and pastes it back into Claude; Claude revises the .md freehand from the notes. One file → one HTML → click + write notes → copy prompt → paste back. No Claude-generated suggestions in the loop. The operator drives every annotation.

This is the v4.2/v4.3 concept (operator-driven annotation) without the broken v4.2/v4.3 UX, without the 388 KB SPA, without /trekrevise, without anchor parsers + Handover 8 + the JSON batch round-trip. ~430 lines of self-contained .mjs. Zero npm deps. Deterministic.

Added

  • scripts/annotate.mjs — operator-annotation HTML generator. Takes <artifact.md>, writes <artifact>.html (or --out <file>). Self-contained, design-system-aligned (light + dark + print), zero external network, deterministic. CLI: node scripts/annotate.mjs <artifact.md> [--out <file.html>]. Also npm run annotate -- <artifact.md>.
  • tests/scripts/annotate.test.mjs (10 tests) — self-contained HTML shape, no external <link>/<script src>, inline script parses, source content + path embedded, HTML escaping in title + body (XSS surface), determinism, default output path, arg parsing, and the operator-driven affordances (Click any line, Your annotations sidebar, Copy Prompt, Clear all, localStorage).
  • npm run annotate convenience script.

Changed

  • commands/trekbrief.md Step 4g, commands/trekplan.md Phase 10, commands/trekreview.md Phase 8 — each now runs scripts/annotate.mjs after the artifact is final and prints the resulting file://<abs path> link with explicit "Click any line to add YOUR OWN note" instructions. The v5.0.1 /playground build a document-critique playground for … line is removed from all three.
  • tests/lib/doc-consistency.test.mjs — replaced the v5.0.1 /playground pins with v5.0.2 pins: scripts/annotate.mjs exists; producing commands invoke it; producing commands no longer print the v5.0.1 /playground document-critique line; producing commands signal operator-driven annotation in their prose; CHANGELOG has a v5.0.2 entry.
  • Plugin CLAUDE.md + README.md + root CLAUDE.md + root README.md + .claude-plugin/marketplace.json — voyage description updated from "v5.0.1 /playground invocation" to "v5.0.2 operator-annotation HTML (scripts/annotate.mjs)".

Notes

  • /playground is unchanged — the official claude-plugins-official playground skill is great for the Claude-leads, operator-reacts flow; it just wasn't the right tool for operator-leads, Claude-reacts.
  • npm test: 516 tests, 514 pass, 0 fail, 2 skipped (up from 503 — 10 new annotate.test.mjs tests + 3 net new doc-consistency pins).
  • Version bump 5.0.1 → 5.0.2 in .claude-plugin/plugin.json, package.json, package-lock.json, plugin README.md badge.

v5.0.1 — 2026-05-13 — Drop the standalone HTML render; print a literal /playground invocation

No new breaking changes beyond v5.0.0. Forks that consumed scripts/render-artifact.mjs directly (or invoked npm run render) must remove that integration. Nothing else moves.

Why

v5.0.0 had /trekbrief, /trekplan, and /trekreview each finish by both rendering a read-only {artifact}.html view (via the new scripts/render-artifact.mjs) and printing a vague instruction to "run the /playground plugin (document-critique template) on the .md and paste the prompt back". In practice the operator saw two HTMLs in their project dir, no annotation UI on the rendered .html, and had to guess the right /playground invocation. The read-only .html added confusion without affording annotation — it duplicated work the /playground HTML already does (formatted document on the left, annotations on the right, Copy Prompt button at the bottom).

v5.0.1 deletes the redundant render and makes the printed /playground invocation literal and copy-paste-ready. One paste from the operator launches the playground skill, which loads its document-critique template, reads the .md, builds the interactive HTML, opens it. Mark suggestions, click Copy Prompt, paste back. Done.

Removed

  • scripts/render-artifact.mjs — the v5.0.0 standalone Markdown→HTML renderer (~280 lines, zero deps). Redundant with /playground's HTML.
  • tests/scripts/render-artifact.test.mjs (and the now-empty tests/scripts/ dir).
  • npm run render script alias in package.json.
  • All references to render-artifact.mjs, brief.html, plan.html, review.html in CLAUDE.md (plugin + root), README.md (plugin + root), .claude-plugin/marketplace.json, and the three command files' final-output blocks.

Changed

  • commands/trekbrief.md Step 4g (Finalize), commands/trekplan.md Phase 10 (Present and refine), commands/trekreview.md Phase 9 (Present summary) — each now ends by printing a single boxed block with the literal text /playground build a document-critique playground for {abs_path} and a one-paragraph explanation of the paste-mark-copy-paste loop. The literal string is pinned by tests/lib/doc-consistency.test.mjs so it cannot soften back into "run the /playground plugin" without a test failure.
  • tests/lib/doc-consistency.test.mjs — replaced the v5.0.0 render-artifact.mjs exists + producing commands reference render-artifact.mjs pins with v5.0.1 pins: render-artifact.mjs no longer exists; producing commands include the literal /playground build a document-critique playground for invocation; producing commands no longer reference render-artifact.mjs; package.json scripts.render is gone; CHANGELOG has both v5.0.0 and v5.0.1 entries.
  • Plugin CLAUDE.md — "Render-and-link (v5.0.0)" paragraph rewritten to "Post-command annotation invocation (v5.0.1)" explaining the literal-paste contract; project-directory contract no longer lists .html siblings; "State" section's project-root inventory no longer lists .html files.
  • Plugin README.md — "Rendered artifacts & annotation (v5.0.0)" section rewritten to "Reviewing and annotating artifacts (v5.0.1)" with a worked example of the printed output and a "What v5.0.1 changed from v5.0.0" sub-note. Top-of-README one-liner + bottom "Known limitations" note updated.
  • Root CLAUDE.md + root README.md + .claude-plugin/marketplace.json — voyage description updated to v5.0.1 + the one-paste invocation model.

Notes

  • /playground is the playground skill from claude-plugins-official. It must be installed in the operator's environment for the printed command to work. If it isn't, the same effect is achievable by pasting the .md content into Claude with "review this and suggest changes" — manual freehand revision.
  • npm test: 503 tests, 501 pass, 0 fail, 2 skipped (down from 509 — 8 render-artifact.test.mjs tests removed; the doc-consistency pins were updated to v5.0.1 contracts, net +2 tests).
  • Version bump 5.0.0 → 5.0.1 in .claude-plugin/plugin.json, package.json, package-lock.json, plugin README.md badge.

Breaking. /trekrevise is removed. The playground/ directory, Handover 8 (annotation → revision), and all of its supporting lib/ modules and tests are gone. Forks that depended on /trekrevise, the playground HTML, lib/parsers/anchor-parser.mjs, lib/parsers/annotation-digest.mjs, lib/util/markdown-write.mjs, or lib/util/revision-guard.mjs must migrate to the official /playground plugin (document-critique / diff-review templates).

Why

v4.2/v4.3 built a ~388 KB bespoke playground SPA — vendored markdown-it + highlight.js + DOMPurify, a design-system copy, a dashboard, drill-down, custom annotation gestures, an anchor parser, and a Playwright e2e suite — to let operators annotate brief/plan/review artifacts in a browser and fold those annotations back via /trekrevise (Handover 8). A 2026-05-12 browser walkthrough found it borderline unusable (annotation broken in the drill-down, dashboard didn't take over, no in-context anchor markers, wrong anchor derivation, broken guide-panel chrome). And it duplicated work the official /playground plugin already does well: document-critique and diff-review templates produce clean, self-contained single-file HTML for exactly this. The NIH cost was real; the lasting value of v4.2/v4.3 is this cautionary record. Lesson: reach for existing capabilities before building bespoke ones, and walk the UI in a browser before shipping it.

Removed

  • plugins/voyage/playground/ — the whole directory: voyage-playground.html, its README.md, vendored lib/ (markdown-it / highlight.js / DOMPurify / manifests), and the vendored playground-design-system/ copy (the canonical shared/playground-design-system/ is untouched — other plugins still use it).
  • /trekrevise — commands/trekrevise.md and the trekrevise block in settings.json.
  • Handover 8 (annotation → revision) — deleted from docs/HANDOVER-CONTRACTS.md; back to seven handovers.
  • lib/parsers/anchor-parser.mjs, lib/parsers/annotation-digest.mjs, lib/util/markdown-write.mjs (readAndUpdate), lib/util/revision-guard.mjs.
  • scripts/vendor-playground-libs.mjs, playwright.config.mjs, tests/e2e/ (a11y + network specs + snapshots), tests/playground/, tests/fixtures/playground/, tests/fixtures/screenshot-project/, tests/fixtures/annotation/.
  • Tests for the removed modules — tests/parsers/anchor-parser.test.mjs, tests/parsers/annotation-digest.test.mjs, tests/integration/annotation-roundtrip.test.mjs, tests/integration/annotation-block-boundary.test.mjs, tests/integration/annotation-export-schema.test.mjs, tests/integration/schema-rollback.test.mjs, tests/lib/revision-guard.test.mjs, tests/lib/markdown-write.test.mjs, tests/lib/source-annotations.test.mjs, tests/validators/{brief,plan,review}-validator-annotation-fields.test.mjs, and the old tests/scripts/render-artifact.test.mjs (a fresh one ships in this release).
  • docs/annotation-quickstart.md, docs/sc1-checklist-verification.md, docs/screenshots/.
  • commands/trekplan.md Phase 9 plan_critic-injection block (and its agents/planning-orchestrator.md mirror) — it imported the now-deleted lib/util/markdown-write.mjs. The plan_critic frontmatter field is no longer written.
  • devDependencies (@axe-core/playwright, @playwright/test) and the test:e2e script in package.json; package-lock.json synced (no runtime deps — it's near-empty).
  • The annotation-frontmatter HTML-comment preambles in templates/{trekbrief,plan,trekreview}-template.md (the validators still tolerate unknown frontmatter keys; nothing emits revision: / source_annotations: / annotation_digest: anymore).

Added

  • scripts/render-artifact.mjs — a small (~280 lines), zero-dependency Node renderer. Reads a .md artifact, folds frontmatter into a <details> block, renders a hand-rolled markdown subset (ATX headings, ordered/unordered/nested lists, fenced code blocks, inline code, bold/italic, links, blockquotes, GitHub-style tables, horizontal rules), and emits a self-contained HTML file with an inlined, design-system-aligned stylesheet (light + dark + print). Zero external network, zero build step, deterministic (byte-identical on re-run). CLI: node scripts/render-artifact.mjs <artifact.md> [--out <file.html>]; also npm run render.
  • Render-and-link step at the end of /trekbrief, /trekplan, and /trekreview — each renders its just-written .md to {project_dir}/{artifact}.html and prints the file:// link plus a one-liner: to annotate, run the /playground plugin (document-critique) on the .md and paste the generated prompt back; Claude revises the artifact freehand.
  • tests/scripts/render-artifact.test.mjs (fresh, 8 tests) — self-contained-document shape, frontmatter <details> folding, title derivation, headings/code-fences/lists/tables/blockquotes rendering, HTML escaping, determinism, default output path, arg parsing.
  • tests/lib/doc-consistency.test.mjs v5.0.0 pins — playground/ gone, commands/trekrevise.md gone, Handover 8 gone, render-artifact.mjs exists, producing commands reference render-artifact.mjs and /playground, CHANGELOG has a v5.0.0 entry and retains the v4.2.0 entry, and no source file (outside CHANGELOG) references trekrevise.

Notes

  • Resolves the three v4.3.1-deferred findings as moot: 87069b35 and c6c64a58 targeted playground/voyage-playground.html (deleted); 4cc3bfc9 targeted the Phase 9 readAndUpdate block in commands/trekplan.md (deleted).
  • Command count: seven → six (/trekbrief, /trekresearch, /trekplan, /trekexecute, /trekreview, /trekcontinue; plus the /trekendsession helper).
  • npm test is the fork-readiness gate; npm run test:e2e is gone (no Playwright).

v4.3.0 — 2026-05-10 — Playground rebuild: dashboard-centric + visual parity + anchor-rendering matures

Additive. No breaking changes. Forward-compat with every brief / plan / review / playground export written before v4.3.

The v4.2 playground proved the annotation loop. v4.3 rebuilds it from the ground up against the design-system reference (plugins/llm-security/playground/llm-security-playground.html) and brings anchor-rendering to maturity. Dashboard-centric layout, file://-loader (webkitdirectory + drag-drop + URL-parameter), block-boundary anchor placement, screenshots-spor convention, and a hardened test pyramid (Groups A-D).

Added

  • Dashboard-centric layout — fleet-grid of fleet-tile per artifact (brief / plan / research / review) with status badges; click drills into artifact-detail surface. Two-overflate-modell matches voyage's domain (one plugin, no onboarding) — alternative 4-overflate-router rejected per Alternatives Considered.
  • File://-loader with three entry points — webkitdirectory directory-picker (Chromium primary, Firefox 150+ secondary with Windows-bug guard), drag-drop with webkitGetAsEntry recursive walk, and URL-parameter ?project=/abs/path ergonomic shortcut. Path-traversal + symlink/dotfile filter (isProjectPathSafe) blocks .. / node_modules/ / dist/ / build/ / hidden-paths with aria-live announces.
  • Anchor-rendering matures — block-boundary placement with code-fence/table/list-item fallback (Prettier #18066 workaround); browser-side parseAnchor mirrors Node-side lib/parsers/anchor-parser.mjs regex; numbered-badge gutter + yellow-tint highlight replaces v4.2's pencil-icon; hidden-by-default sidebar-rail with ordered list, filter, and jumplist count; J/K keyboard navigation + Esc dismiss + aria-live announces; two-opacity pattern (active 100% / inactive 40% / resolved 30% strikethrough).
  • A11Y panel built from DS-primitives (Wave 5 Step 22) — guide-panel--info container with key-stats severity-grid + findings__items ordered list; wireA11yToggle couples topbar-button to panel; window.__voyage.scheduleRender({ a11yViolations }) hook lets Playwright spec populate severities.
  • Screenshots-spor convention (Wave 5 Step 23) — window.__voyage namespace with navigate(target), scheduleRender({ a11yViolations }), and getProjectArtifacts() methods; docs/screenshots/README.md documents manual + Playwright-driven screenshot procedure (defers inline gallery to v4.4).
  • DOMPurify ≥ 3.1.1 vendored (Wave 5 Step 24) — playground/lib/dompurify.min.js (22 KB UMD bundle); sanitizeAnnotation wraps user-comment markdown rendering; total bundle 388 KB / 460 KB HALT-gate (72 KB margin). HTML-comment indirect prompt-injection mitigation (Wave 5 Step 25) gates stripUnsafeComments via parseAnchor allowlist before md.render.
  • Voyage-scope DS-tokens (Wave 0 Step 1) — --color-scope-voyage + badge--scope-voyage added additively to shared/playground-design-system/dist/base.css and re-synced into the playground vendor copy. Other plugins (architect / okr / llm-security / config-audit) re-sync on next playground touch (additive-only change).
  • Test pyramid Groups A-D (Wave 7) — Group A 17 static-HTML grep tests (SC1 10-element checklist + SC3 webkitdirectory/drag-drop + SC6 export markers + SC7 tag-level no-CDN), Group B 9 structure tests (DS-tokens + theme-toggle + sidebar-tab + keyboard pattern), Group C 7 export-bundle schema + annotation_digest SHA-256 validity tests (SC-GAP-3), Group D 4 Playwright e2e tests (light/dark axe-core + pixel-diff baseline + zero-external-network authoritative gate).
  • Playwright + @axe-core/playwright devDeps + playwright.config.mjs — testDir: 'tests/e2e', snapshotPathTemplate: '{testDir}/snapshots/{arg}{ext}', npm run test:e2e script. Chromium browser binary installed locally.
  • tests/fixtures/playground/ — v43-export-bundle.json (canonical export shape) + v43-plan-pre-annotate.md (revision: 0 seed with ANN-0001/ANN-0002 anchors).
  • tests/e2e/snapshots/a11y-baseline.json — WCAG-violations delta-baseline (aria-hidden-focus, color-contrast per .key-stat--critical__label); a11y spec compares current against baseline, fails only on NEW or GROWN violations. Actual fix deferred to v4.4 (HTML FROZEN in Sesjon 6).
  • docs/sc1-checklist-verification.md — per-element pass/fail with evidence (Group A test references + manual side-by-side); 8/10 PASS literal + 2/10 PASS-redef (Element 4 onboarding-grid → fleet-grid, Element 6 screenshots-spor → hooks + docs convention) per scope-guardian Assumptions 21+22.
  • playground/README.md — v4.3 architecture, three entry-point usage, .claude/projects/ discoverability, annotation flow, window.__voyage hooks, known limitations (FF150-Win, no FSA, baseline'd WCAG), bundle-size breakdown, test-suite overview.

Changed

  • Test count: 672 → 711 pass / 0 fail / 2 skipped (713 total — Groups A/B/C node-test additions from the rebuild and the Sesjon 13–18 re-review remediation; +5 Playwright e2e specs run via npm run test:e2e).
  • Theme bootstrap IIFE (Wave 2 Step 6) sets data-theme="dark" as default; respects localStorage('voyage-theme') → prefers-color-scheme: dark matchMedia → fallback dark. Theme-toggle button in topbar (Wave 2 Step 7) persists user choice.
  • Page-shell pattern (Wave 2 Step 9) — page__eyebrow + page__title + page__lede + page__meta matches DS reference.
  • Annotation export filename — annotated-{target}.md where target = brief|plan|review|artifact (derived from frontmatter).

Fixed

  • Browser-side anchor regex synced with Node-side allowlist (Wave 4 Step 16) — VOYAGE_ANCHOR_RE / VOYAGE_ANCHOR_ID_RE mirror lib/parsers/anchor-parser.mjs:20-25; parseAnchor validates ID + intent + line-number per attribute regex.
  • Hard-coded WIP token strings (Wave 1 Step 4) — voyage tokens normalized to canonical --color-scope-voyage + --ds-color-* tokens; literal pixel font-sizes replaced with DS scale.
  • Plan-determinism test reference path (Wave 0 Step 3) — tests/synthetic/plan-determinism.test.mjs:115 updated to plan-run-C.md (alphabetic convention matching A/B).

Re-review remediation (Sesjon 13–18)

After the rebuild, an independent /trekreview (Sesjon 13) flagged 11 findings (5 BLOCKER + 5 MAJOR + 1 MINOR). Waves 1–3 of remediation closed all 11 with delivered code + tests — notably reinstating an inline screenshots gallery (renderScreenshotGallery, finding 31d28f65; supersedes the original "deferred to v4.4" item below), wrapping renderArtifact's bodyHtml in DOMPurify.sanitize (1d3591d4), converting the SC2 a11y spec to absolute zero-violation mode and removing a11y-baseline.json (09132940), documenting the Phase 9 plan_critic frontmatter injection (906f155d), and asserting the .fleet-grid 4-column CSS parity (99707f51). A Sesjon 18 re-review then found 3 new findings introduced by the remediation code itself — deferred to v4.3.1 (see Known issues below).

Deferred to v4.4

  • WCAG-violations fix (HTML FROZEN in Sesjon 6 per Wave 7 verification-only scope; superseded for the a11y-spec by the absolute zero-violation conversion in the Sesjon 13–18 remediation).
  • File System Access API (FSA) write-back (currently Blob-download only).
  • <project>/design/-folder traversal.
  • IndexedDB primary persistence (localStorage stays primary for v4.3).
  • Hybrid claude-design-skill → canvas → frontend-design workflow (research/02 deferred to v4.4+).

Known issues — deferred to v4.3.1 → all resolved in v5.0.0 (moot)

The Sesjon 18 re-review surfaced 3 findings in code the Sesjon 13–18 remediation introduced. They were deferred to a planned v4.3.1 patch; v5.0.0 makes all three moot by removing the playground entirely:

  • 87069b35 (SECURITY_INJECTION, defense-in-depth) — renderScreenshotGallery() interpolated screenshots[].dataUrl raw into an <img src>. Moot in v5.0.0 — playground/voyage-playground.html is deleted.
  • 4cc3bfc9 (PLAN_EXECUTE_DRIFT) — commands/trekplan.md Phase 9 used a backtick template literal as an ES import specifier (SyntaxError). Moot in v5.0.0 — the Phase 9 plan_critic-injection-via-readAndUpdate block is deleted.
  • c6c64a58 (MISSING_TEST) — no test covered the gallery dataUrl injection path. Moot in v5.0.0 — the gallery and its host file are deleted.

Notes

  • Brief, research (4 briefs), plan, and execute (6 sessions) all produced from the v4.3 pipeline itself. SC11 pipeline-self-eat gate continues to hold.
  • Path A/B/C decision (cache-first / sequential --no-ff waves / hybrid identical-tool) unchanged from v3.4.0 — Path B remains in production.
  • Plan quality score 86/100 Grade A APPROVE_WITH_NOTES (adversarial review Phase 9, 22 revisions documented in plan.md Revisions table). Sesjon 13–18 remediation plans reviewed independently; Sesjon 18 re-review verdict BLOCK with 3 findings (now v4.3.1).

v4.2.0 — 2026-05-09 — Annotation pipeline + first voyage playground

Additive. No breaking changes. Forward-compat with every brief / plan / review written before v4.2.

Voyage's first interactive playground. The /trekrevise command and the annotation pipeline (Handover 8) close the operator-feedback loop: render an artifact in the browser, anchor comments at block boundaries, export a batch, paste back as /trekrevise --apply for in-place revision with audit trail.

Added

  • /trekrevise command (commands/trekrevise.md) — seventh pipeline command. Phase 1 parse/validate, Phase 2 read source + rollback hygiene, Phase 3 parse anchors + validate placement, Phase 4 compute revision diff + digest, Phase 5 atomic apply, Phase 6 post-write integrity check, Phase 7 optional review-gate, Phase 8 stats + report. Accepts --profile, --gates, --reason, --from-file, --target.
  • Handover 8 (annotation → revision) documented in docs/HANDOVER-CONTRACTS.md (~100 lines). Producer/consumer contract, schema for the four additive frontmatter fields (revision, source_annotations, annotation_digest, revision_reason), block-level anchor format, lifecycle, single-iteration MVP rationale.
  • playground/voyage-playground.html — single self-contained HTML file with vendored markdown-it v14.1+ + highlight.js (no marked per Issue #3515). Three annotation creation gestures (drag-select, hover-anchor, click-anchor), modal form with intent taxonomy (change/add/remove/ clarify/risk), sidebar with critique-card-list, export flow with one-click clipboard copy, A11Y baseline (keyboard nav, ARIA roles, focus traps).
  • playground/lib/ vendored markdown-it + highlight.js + front-matter plugin, with VENDOR-MANIFEST.json recording version + license + sha. Locked at minimum versions per research-03.
  • scripts/render-artifact.mjs server-side render CLI — emits the same HTML the playground produces. Used by the SC11 pipeline-self-eat gate (rendering .claude/projects/*/brief.md + plan.md exits 0 with non-empty output).
  • scripts/vendor-playground-libs.mjs vendor-refresh helper — fetches pinned versions and updates the manifest.
  • lib/parsers/anchor-parser.mjs — pure-function anchor parser: parseAnchors, addAnchors, stripAnchors, validateAnchorPlacement. Block-boundary discipline (no in-list, no mid-paragraph, no line-start collisions). Round-trip tested with byte-identical fixture (tests/fixtures/annotation/annotation-example.md).
  • lib/parsers/annotation-digest.mjs — pure-function deterministic SHA-256 over canonical-sorted source_annotations. First 16 hex chars. Idempotent: same batch → same digest.
  • lib/util/markdown-write.mjs — serializeFrontmatter + atomicWriteMarkdown (tmp-file + rename, same crash-safety as atomic-write.mjs).
  • lib/util/revision-guard.mjs — atomic-write rollback guard for /trekrevise Phase 6 round-trip integrity check (plan-critic M4). Restores byte-identical pre-write file from *.local.bak on failure.
  • docs/annotation-quickstart.md — operator-facing 7-step walkthrough, references tests/fixtures/annotation/annotation-example.md for hands-on verification.
  • tests/fixtures/annotation/ — 5 fixtures covering brief, plan, plan-large, review, and the canonical annotation-example.md.
  • 9 new test files + extension to tests/lib/doc-consistency.test.mjs:
    • tests/lib/markdown-write.test.mjs (round-trip)
    • tests/parsers/anchor-parser.test.mjs (parse/add/strip/validate)
    • tests/parsers/annotation-digest.test.mjs (determinism)
    • tests/validators/{brief,plan,review}-validator-annotation-fields.test.mjs (forward-compat: validators tolerate the four optional fields)
    • tests/integration/annotation-roundtrip.test.mjs (SC2/SC3/SC7 byte-identical + scale)
    • tests/integration/schema-rollback.test.mjs (SC5b validator-FAIL rollback)
    • tests/integration/source-annotations.test.mjs (frontmatter audit trail)

Changed

  • Forward-compat policy documented in lib/validators/{brief,plan, review}-validator.mjs headers — validators silently accept the four optional annotation fields without bumping *_version.
  • tests/lib/doc-consistency.test.mjs extended with ~16 new pins: Handover 8 section, templates' annotation-field comment blocks, playground/ directory, marked-ban, scripts/render-artifact.mjs, lib/util/revision-guard.mjs, parseAnchors round-trip on the example fixture, /trekrevise in CLAUDE.md / plugin README / marketplace root README, ## v4.2.0 in CHANGELOG, docs/annotation-quickstart.md existence + ≤7 numbered steps + annotation-example.md literal reference.
  • PIPELINE_COMMANDS constant in doc-consistency tests — was 6 (brief/research/plan/execute/review/continue), now 7 (+ revise). Pin test renamed from "all six pipeline commands" to "all seven pipeline commands".
  • settings.json known-scopes allowlist — 'trekrevise' added to the recognized top-level scope list (was added in Wave 2 Step 6 to keep tests green pre-Step 12).
  • Templates (templates/{plan,trekbrief,trekreview}-template.md) prefixed with comment-only documentation block of the four optional annotation fields. No *_version change; existing templates still parse and validate identically.

Notes

  • marked is banned from playground/* (risk-assessor H1 + doc-consistency pin). Issue #3515 corrupts content silently after HTML comments in lists — voyage anchors after step-list would be invisible. markdown-it v14.1+ is the locked renderer.
  • Single-iteration MVP per research-05. Each operator batch produces one revision: increment. Multi-iteration loops (revise → re-review → revise again) are deferred indefinitely; the brief's SC4 wording is single-revision.
  • No *_version bump for v4.2 — the four new fields are additive. Brief/plan/review artifacts written before v4.2 validate as revision: 0 without migration.
  • Atomic-write contract for /trekrevise — single writeFileSync+renameSync (research-05 Option B). Option C (atomicWriteJson + Edit-tool split-write) was inadmissible per risk-assessor C2: no crash-safe window between frontmatter patch and body Edit.
  • 608 tests pass (606 → 0 fail → 2 skipped Docker) — baseline before v4.2 was 490; this release adds ~118 tests.

v4.1.0 — 2026-05-09

Additive. No breaking changes. Forward-compat with all v4.0.0 plans.

Two new feature surfaces: model profiles (--profile <name>) and opt-in OpenTelemetry / Prometheus export at session-end.

Added

  • Model profile system (lib/profiles/{economy,balanced,premium}.yaml, lib/profiles/resolver.mjs, lib/validators/profile-validator.mjs). Three built-in tiers + custom-yaml support. Lookup order: explicit --profile flag → plan frontmatter profile: → VOYAGE_PROFILE env-var → balanced default. See docs/profiles.md for the decision tree, custom authoring, and cost estimation disclaimer.
  • --profile <name> flag documented in all 6 pipeline commands (commands/trek{brief,research,plan,execute,review,continue}.md).
  • 5 additive profile fields in JSONL stats (profile, profile_source, phase_models, model_used, phase_models_resolved) for cost-attribution and drift detection.
  • OpenTelemetry / Prometheus export at session-end via new Stop hook (hooks/scripts/otel-export.mjs, wired in hooks/hooks.json). Strict opt-in via VOYAGE_EXPORT_MODE:
    • textfile — Prometheus exposition format → node-exporter textfile
    • otlp — OTLP/JSON POST → otel-collector
    • off (default) — no work done
  • Local Docker Compose stack at examples/observability/ (Prometheus 3.0.1 + node-exporter 1.10.2 + Grafana 11.4.0 + OTel Collector 0.115.0, all version-pinned per research/01).
  • Operator documentation at docs/observability.md (151 lines: env-var matrix, security mitigations, limitations, CVE-pinned minimum versions).
  • Cross-tier Jaccard smoke test (tests/integration/profile-jaccard-smoke.test.mjs) with parked- synthetic fixtures and 0.55 conservative starting threshold per research/02. Empirical recalibration deferred to v4.2.
  • MANIFEST_PROFILE_DRIFT warning in plan-validator --strict when plan frontmatter profile: differs from any step manifest's profile_used. Plan remains valid (warning, not error).

Changed

  • lib/parsers/arg-parser.mjs FLAG_SCHEMA — additively adds --profile <name> to all 6 commands. Existing flags unchanged.
  • lib/parsers/manifest-yaml.mjs schema — additively adds new OPTIONAL_STRING_KEYS collection with profile_used as the first member. Forward-compat: legacy plans without profile_used parse unchanged; new plans with it round-trip cleanly.

Fixed

  • Doc-consistency coverage now spans all 6 pipeline commands (was 5 — /trekcontinue was missing per HIGH risk-assessor).
  • Plan-validator strict mode detects profile-drift between plan- level frontmatter and step-level manifests (brief Assumptions block 7).

Notes

  • Forward-compat: every v4.0.0 plan validates valid: true under v4.1.0's plan-validator --strict. No migration needed.
  • Tests: 361 baseline → 484 pass + 2 skipped (Docker-dependent).
  • Path A/B/C decision (v3.4.0) is unchanged. Path C remains closed.
  • v4.2 deferred items: ROUGE-L scoring, char-4gram MinHash, empirical Jaccard re-calibration, balanced.external_research_enabled operator-override.

v4.0.0 — 2026-05-05

Breaking. Rebrand. No migration path.

The ultraplan-local plugin is renamed to Voyage. All seven commands are renamed from /ultra*-local to /trek*:

  • /ultrabrief-local → /trekbrief
  • /ultraresearch-local → /trekresearch
  • /ultraplan-local → /trekplan
  • /ultraexecute-local → /trekexecute
  • /ultrareview-local → /trekreview
  • /ultracontinue-local → /trekcontinue
  • /ultraplan-end-session-local → /trekendsession

Internal renames: FLAG_SCHEMA keys, stats filenames, env vars, branch namespace, type discriminators, hook stderr prefixes, settings.json scope keys all updated to trek* form. Plugin identity is now voyage.

No backward compatibility. Old artifacts on user disks are orphaned. Fork-and-own users re-fork from main if they want to follow upstream; there is no migration helper.

See TRADEMARKS.md for the new trademark hygiene notice clarifying independence from Anthropic.

Out-of-scope handoff (operator follow-up): plugin directory rename plugins/ultraplan-local/ → plugins/voyage/, marketplace-root coordination across ../../README.md, ../../CLAUDE.md, and ../../.claude-plugin/marketplace.json.

[3.4.1] - 2026-05-04 — /ultracontinue-local hot-fix + ultra-cc-architect doc-rydding

Forward-patch on top of v3.4.0. Fixes four bugs in the multi-session resumption path discovered post-3.3.0 ship, plus a doc-rydding sweep that generalizes references to the ultra-cc-architect plugin (no longer publicly distributed). Non-breaking: the architecture/overview.md filesystem contract (Handover 3) is preserved for any compatible producer.

Fixed

  • Bug 1 — /ultracontinue-local Phase 0 + auto-discovery. commands/ultracontinue-local.md no longer prints a usage block on bare invocation; it enters auto-discovery (sorts active state files numerically by Date.parse(updated_at), not lexicographically — fixes cross-timezone wrong-order). --help / -h is the only flag that surfaces the usage block. (Steps 1–3)
  • Bug 2 — Phase 2 placeholder leakage. {state-file-path}, {project-dir}, {path-a} and similar template tokens are gone from commands/ultracontinue-local.md Phase 2 prose. The command now reads the resolved path inline rather than asking the model to substitute. (Steps 4–5)
  • Bug 3 — frontmatter consistency for NEXT-SESSION-PROMPT.local.md. Producers (/ultraexecute-local Phase 8, /ultraplan-end-session-local) now write produced_by: + produced_at: (ISO-8601) frontmatter on the prompt file. /ultracontinue-local Phase 1.5 cross-checks produced_at against the sibling state file's updated_at and refuses to proceed on inconsistency (NEXT_SESSION_PROMPT_INCONSISTENT). Files without frontmatter remain tolerated (warning, not error) for backwards compatibility. State-anchored staleness check is the primary signal; 24h wall-clock is a soft warning only. (Steps 6–8)
  • Bug 4 — --cleanup for completed projects. /ultracontinue-local --cleanup <project-dir> (dry-run by default) and /ultracontinue-local --cleanup --confirm <project-dir> (deletes the state file + sibling prompt file). Refuses non-completed status with no force flag. Idempotent — safe to re-run after partial cleanup. (Steps 9–10)
  • ESM/CJS regression in commands/ultraplan-end-session-local.md. Phase 3 now invokes atomicWriteJson via node --input-type=module rather than the broken require() call. State writes from the helper command are no longer silently lost on Node 18+. (Collateral in Step 7)
  • plugin.json description drift. "Five-command" → "Six-command"; trailing ultra-cc-architect sentence removed. (Step 13)

Added

  • lib/util/cleanup.mjs — refuse-unless-completed gate + dry-run + confirm-aware deleter for state file and sibling prompt file.
  • lib/validators/next-session-prompt-validator.mjs — frontmatter validator + state-anchored staleness check + CLI shim.
  • tests/commands/ultracontinue.test.mjs — new test directory; covers SC-1 (auto-discovery sort + usage block), SC-2 (.md diagnostic), SC-3 (path-guard ALLOW + no placeholder), SC-4 (consistency), SC-5 (cleanup wiring).
  • tests/validators/next-session-prompt-validator.test.mjs — unit coverage for frontmatter consistency: matching, mismatch, wall-clock, no-frontmatter, missing-field.
  • tests/lib/cleanup.test.mjs — cleanup util tests.
  • --cleanup + --confirm flags on /ultracontinue-local.

Changed

  • docs/HANDOVER-CONTRACTS.md Handover 7 gains a § Lifecycle subsection documenting producer/consumer arbeidsdeling, the stale-file principle (operator-invoked --cleanup, no auto-cleanup, no force flag), the produced_by: + produced_at: frontmatter contract, and idempotency.
  • CLAUDE.md, README.md, SECURITY.md — generalize references to ultra-cc-architect plugin to "opt-in upstream architect plugin (not bundled)". CHANGELOG.md historical references are preserved with a 2026-05-04 banner stating the plugin is no longer publicly distributed.

Tests

  • 322 (v3.3.0 baseline) → 358 (post-Wave 4) → 361 (Step 11 doc-pins) → ~363 at release. New tests: arg-parser FLAG_SCHEMA extensions, ultracontinue auto-discovery + diagnostic + path-guard + consistency + cleanup wiring, next-session-prompt-validator frontmatter checks, cleanup util, and 3 new doc-consistency pins for Handover 7 § Lifecycle + next-session-prompt-validator CLI shim.

[3.4.0] - 2026-05-04 — Ultra-pipeline speedup

Hardenings + scaffolding to support an autonomy chain from brief approval through main-merge with parallel-wave execution. Non-breaking: all existing flags continue to work; --gates is opt-in autonomy control. Plan-step delivery covered by 18 plan-v2 steps split across three Waves.

Added — autonomy + parallelism

  • lib/util/autonomy-gate.mjs — autonomy-gate state machine (idle → approved → executing → merge-pending → main-merged) for the brief-to-merge chain (Step 4)
  • lib/review/plan-review-dedup.mjs — deterministic plan-review dedup helpers reused by Phase 9 inline dedup (Step 5)
  • lib/stats/event-emit.mjs — single-source stats event emitter for autonomy-gate transitions and main-merge-gate (Step 6 + 12)
  • --gates {open|closed|adaptive} flag on all four pipeline commands (Step 11). Controls how many autonomy checkpoints surface to the operator. Default adaptive.
  • hooks/scripts/post-compact-flush.mjs — PostCompact hook re-injects session-state after context compaction so multi-session work survives a compaction boundary (Step 13)

Added — hardenings + defense-in-depth

  • commands/ultraplan-local.md Phase 8 schema-drift defense — post-generation plan-validator --strict run blocks plans containing narrative Fase/Phase headers or missing Manifest YAML; addresses the documented Opus-4.7 plan/list-emission drift (Step 7, builds on v1.8.0 fix in commit 9ecd669)
  • commands/ultraplan-local.md Phase 9 parallelization with inline dedup — single-message multi-Agent dispatch + plan-review-dedup helper (Step 8)
  • commands/ultraexecute-local.md Phase 2.6 wave-executor — 11 sub-hardenings for plugin-in-monorepo + gitignored-state topology: GIT_OPTIONAL_LOCKS, --max-turns, --max-budget-usd, scoped --allowedTools, --append-system-prompt-file, SHARED_CONTEXT_FILE, SAFETY_PREAMBLE, deferred git push origin, push-before-cleanup ordering, GH #36071 awareness (Step 9)
  • templates/headless-launch-template.md — mirrors Phase 2.6 hardenings so the headless launcher is consistent with Phase 2.6 prose (Step 10)
  • commands/ultraplan-local.md + agents/planning-orchestrator.md Phase 8 main-merge gate — emit stats event for main-merge gate decisions (Step 12)

Added — quality infrastructure

  • tests/lib/agent-frontmatter.test.mjs — pins agent frontmatter invariants (Step 1-test)
  • tests/synthetic/plan-run-A.md + plan-run-B.md + plan-determinism.test.mjs — SC7 plan-determinism floor (Jaccard ≥ 0.833) (Step 15)
  • tests/synthetic/review-run-A.md + review-run-B.md + review-determinism.test.mjs — SC7 review-determinism floor (Jaccard ≥ 0.833) (Step 15)
  • tests/hooks/path-guard.test.mjs — pins pre-write-executor BLOCK rules; regression detection if BLOCK_RULES are silently weakened (Step 18)
  • tests/hooks/bash-guard.test.mjs — pins pre-bash-executor BLOCK rules (Step 18)
  • examples/01-add-verbose-flag/perf-measure.local.sh (gitignored) — operator-driven SC1 wall-time measurement harness (Step 16)
  • examples/01-add-verbose-flag/perf-baseline.local.md (gitignored) — SC1 gate template + measurement protocol (Step 16)

Changed

  • lib/parsers/manifest-yaml.mjs — schema extended additively to recognize skip_commit_check and memory_write flags (forward-compat: unknown keys ignored). Used by Step 14 and other steps that legitimately don't produce a git commit (Step 4)
  • .gitignore — generalized *.local.md + *.local.json rules into a single *.local.* glob, covering .local.sh and any future .local.<ext> (Step 16)
  • package.json — version 3.3.0 → 3.4.0
  • .claude-plugin/plugin.json — version 3.3.0 → 3.4.0
  • README.md + CLAUDE.md — version refs + --gates flag docs + Wave 1+2+3 architecture notes
  • Marketplace root README.md — ultraplan-local version line bumped 3.3.0 → 3.4.0

Memory updates (Step 14)

  • ~/.claude/projects/-Users-ktg--claude-plugins-marketplaces-ktg-plugin-marketplace/memory/project_ultraplan_opus47_gap.md — rewritten per Path B (memory truth gate). New body: (a) historical context referencing commit 9ecd669 (v1.8.0 fix, 2026-04-17), (b) empirical evidence (5 organic plans 2026-04-18 → 2026-05-01 all clean per research/04 D1), (c) defense-in-depth added in Step 7 (commands/ultraplan-local.md Phase 8), (d) residual risk surface for plugins NOT using ultraplan-local prompt arch.
  • ~/.claude/projects/.../memory/MEMORY.md — one-liner updated to flag mitigation status. The drift mechanism stays a known model-level risk; the plugin-level mitigation is documented.

These memory edits are recorded here because the files live outside the repo and have no git checkpoint of their own.

Architecture decision (Path B not Path C)

Brief offered three architectural options for the speedup work:

  • Path A — cache-first (drop --allowedTools per child) — REJECTED. Inverts security model; plugin hooks don't fire reliably in claude -p (research/06 GH #36071).
  • Path B — sequential --no-ff parallel waves with manifest-driven failure recovery — CHOSEN. v3.4.0 ships this.
  • Path C — hybrid (cache-warm sentinel + identical-tool parallel) — DEFERRED to v3.5.0 contingent on cache-telemetry data harvested by Step 6's stats events. Requires unverified Q3 (CLAUDE_CODE_FORK_SUBAGENT cache-prefix preservation at 150-250K context).

Tests

  • 265 baseline (post-Wave-2) → ~290+ green after Wave 3 (Steps 15 + 18 add ~25 tests; doc-consistency may add a couple more pin tests)

Open Questions for v1.1

  • Real-LLM determinism measurement — synthetic floor (0.833) is anchored; the foreign-repo run against examples/01-add-verbose-flag/ for SC1+SC4+SC5 measurement is a separate post-ship session.
  • Cache-telemetry harvest — Step 6 stats events emit shapes useful for Path C decision; harvesting + analysis is v1.1 work.
  • Marketplace-level autonomy-gate — currently per-plugin scope. Marketplace-wide policy + dashboards are out of scope for this solo project.

[3.3.0] - 2026-05-01

Adds /ultracontinue-local — a zero-friction multi-session resumption command — plus the contracted Handover 7 (.session-state.local.json) that any session-end mechanism may write. Non-breaking: existing brief / research / plan / execute / review pipelines are untouched. The state file is the contract; /ultracontinue only reads.

Added

  • /ultracontinue-local command — read .session-state.local.json and immediately resume the next session in a multi-session ultraplan project (model: opus)
  • /ultraplan-end-session-local helper — informal multi-session flows write the state file via this command (model: sonnet)
  • lib/validators/session-state-validator.mjs — schema-v1 validator + CLI shim for .session-state.local.json (forward-compat: unknown top-level keys ignored)
  • lib/util/atomic-write.mjs — atomicWriteJson(path, obj) extracted from pre-compact-flush.mjs for reuse
  • tests/fixtures/session-state/{valid-in-progress,malformed}.json — synthetic fixtures
  • Handover 7 (.session-state.local.json) — full schema documented in HANDOVER-CONTRACTS.md
  • Doc-consistency pins: Handover 7, session-state-validator CLI shim, /ultracontinue-local in CLAUDE.md commands table
  • ~22 new tests (163 baseline → 185 green; atomic-write + session-state-validator + doc-consistency pin extensions)

Changed

  • commands/ultraexecute-local.md — Phase 8 (canonical end-of-session), Phase 2.55 (pre-flight stop), Phase 4 (entry-condition stop) now write .session-state.local.json as a sibling to progress.json (Handover 7 producer)
  • hooks/scripts/pre-compact-flush.mjs — also refreshes .session-state.local.json before context compaction (monotonic; never advances state to a non-resumable status)
  • .gitignore — covers *.local.json (state files never enter git)

Tests

  • 163 baseline → 185 green (+22 new)

Open Questions for v1.1

  • graceful-handoff convergence: graceful-handoff v2.2 may dual-write .session-state.local.json so a single chat-end mechanism feeds /ultracontinue. v3.3.0 ships the contract; convergence is additive.
  • /continue builtin Claude Code collision (unverified) — /ultracontinue prefix mitigates risk; monitor release notes.

[3.2.0] - 2026-05-01

Adds /ultrareview-local as the fifth and final command in the ultra-suite — independent post-hoc review of delivered code against the brief — and the contracted Handover 6 (review → plan) feedback loop. Non-breaking: existing brief/research/plan/execute pipelines are untouched.

Added

  • /ultrareview-local command — fifth and final command in ultra-suite (independent post-hoc review of delivered code against brief)
  • lib/validators/review-validator.mjs — schema validator for new type: ultrareview artifact
  • lib/review/rule-catalogue.mjs — 12 canonical rule keys (version-pinned)
  • lib/parsers/finding-id.mjs — stable SHA1 finding-ID computation
  • lib/parsers/jaccard.mjs — Jaccard similarity for determinism testing
  • 4 new agents: review-orchestrator (opus inline ref), brief-conformance-reviewer, code-correctness-reviewer, review-coordinator (Judge Agent pattern)
  • Handover 6 (review → plan) — contracted feedback loop documented in HANDOVER-CONTRACTS.md
  • ~43 new tests (109 → ~152 baseline; rule-catalogue + finding-id + jaccard + review-validator + brief-validator extension + arg-parser extension + project-discovery extension + 4 doc-consistency pins + 3 review-determinism integration + 3 source-findings SC3(b) integration)

Changed

  • brief-validator.mjs accepts type: ultrareview in addition to ultrabrief (Handover 6 enabler)
  • /ultraplan-local consumes type: ultrareview brief — extracts findings as plan goals + populates source_findings array in plan frontmatter
  • lib/parsers/project-discovery.mjs discovers review.md and supports 'review' phase
  • lib/parsers/arg-parser.mjs adds ultrareview command to FLAG_SCHEMA
  • hooks/scripts/session-title.mjs adds /ultrareview-local to COMMANDS map
  • Severity vocabulary aligned with llm-security: Critical | High | Medium | Low | Info (rule-catalogue retains the 4-tier brief vocabulary; 5-tier migration is a v1.1 candidate)

Tests

  • 109 baseline → ~152 green (+43 new)

Open Questions for v1.1

  • Migrate 4-tier severity (BLOCKER/MAJOR/MINOR/SUGGESTION) → llm-security 5-tier (Critical/High/Medium/Low/Info) — research/02 advised but deferred to keep brief contract intact.
  • Real-LLM determinism measurement (current SC4 test uses synthetic fixtures).
  • SC2 end-to-end false-positive integration test (currently agent-prompt-level only).

[3.1.0] - 2026-05-01

Quality program: pure quality lift, no scope creep. Built around the fork-er onramp — anyone cloning this plugin should get value out of the box. 109 zero-dep tests gate readiness.

Added — testing & validation infrastructure (Spor 0+1)

  • package.json with node:test runner and zero npm dependencies (engines.node>=18)
  • lib/util/{result,frontmatter}.mjs — Result-shape helpers and a hand-rolled YAML subset parser supporting list-of-dicts (the form used by must_contain in real plans)
  • lib/parsers/{plan-schema,manifest-yaml,project-discovery,arg-parser,bash-normalize}.mjs — primitive parsers
  • lib/validators/{brief,research,plan,progress}-validator.mjs and lib/validators/architecture-discovery.mjs — wrappers over parsers, each with a CLI shim (if (import.meta.url === ...)) so they can be invoked from Bash via node ${CLAUDE_PLUGIN_ROOT}/lib/validators/X.mjs
  • tests/lib/* + tests/validators/* — 109 tests
  • tests/lib/doc-consistency.test.mjs — pins agent-table count, command-table coverage, plan_version invariant, and settings.json scope cleanliness; first-red surfaces drift between docs and code

Changed — wiring (Spor 1)

Site Was Is
/ultrabrief-local Phase 4g implicit trust node lib/validators/brief-validator.mjs --json
/ultraplan-local Phase 1 inline frontmatter parse + test -f brief-validator --soft + research-validator --dir + architecture-discovery
agents/planning-orchestrator.md Phase 5.5 three grep -cE calls single node lib/validators/plan-validator.mjs --strict --json
/ultraexecute-local Phase 2.3 (--validate) inline regex plan-validator --strict + progress-validator

Validators default to strict: false. Only --validate mode and Phase 5.5 use --strict. Existing in-flight projects under .claude/projects/ continue to work.

Added — handover contracts (Spor 2)

  • docs/HANDOVER-CONTRACTS.md (~310 lines) — single source of truth for the 5 pipeline handovers (brief→research, research→plan, architecture→plan EXTERNAL, plan→execute, progress.json resume). Per-handover sections: Producer / Consumer / Path conventions / Frontmatter schema / Body invariants / Validation strategy / Versioning / Failure modes. Architecture handover is explicitly an external contract — drift-WARN never drift-FAIL.

Added — PreCompact resume integrity (Spor 2, P0 fix)

  • hooks/scripts/pre-compact-flush.mjs — PreCompact-event hook (CC v2.1.105+) that reconciles progress.json with git history before context compaction. Atomic write (tmp + rename), monotonic only (current_step never decreases), fail-open (always exit 0). Closes the documented progress.json drift bug from docs/ultraexecute-v2-observations-from-config-audit-v4.md — --resume now works after long conversations.
  • hooks/hooks.json registers the PreCompact entry.

Added — examples (Spor 3)

  • examples/01-add-verbose-flag/ — calibrated end-to-end pipeline demo for a small realistic task (add --verbose to a CLI parser). Includes brief.md, research/01-cli-parser-conventions.md, plan.md (7 steps with full manifest YAML), and progress.json. All four artifacts pass their respective validators. Hand-calibrated, not LLM-generated, so the example stays reviewable.
  • examples/REGENERATED.md per example documents calibration date and regeneration triggers.
  • examples/README.md walks fork-ers through what to study first.

Changed — plan-critic semantic rubric (Spor 3, P0 fix)

agents/plan-critic.md rule #7 split into two parts:

  1. Literal blockers (exact-string): TBD, TODO, FIXME, XXX always fire.
  2. Semantic rubric (instruction-shaped): 8 deferred-decision tests covering vague modifiers, imperatives without targets, forward references without expansion, volume/quality without spec, edge-cases delegated, production-readiness delegated, path mismatch, and over-stuffed steps.

Calibrated against 5-phrase corpus the v3.0 exact-string blacklist missed: "implement as needed", "wire it up", "make it production-ready", "add tests where appropriate", "handle edge cases" — all five now flagged with rule citations.

Added — CC v2.1.x feature adoption (Spor 3)

  • F8 — MCP_CONNECTION_NONBLOCKING=true documented under "Headless multi-session tuning" in README (CC v2.1.89+) for parallel claude -p sessions
  • F9 — hooks/scripts/session-title.mjs (UserPromptSubmit, CC v2.1.94+) sets ultra:<command>:<slug> titles for ultra invocations
  • F3 — hooks/scripts/post-bash-stats.mjs (PostToolUse, CC v2.1.97+) appends duration_ms per Bash call to ${CLAUDE_PLUGIN_DATA}/ultraexecute-stats.jsonl
  • F12 — disableSkillShellExecution: true recommended in README "Security hardening" + SECURITY.md (CC v2.1.91+) for fork-ers handling untrusted plans

Deferred: F2 (hook if-field scoping). The plan called for scoping pre-bash-executor / pre-write-executor to ultraexecute sessions to "reduce false-positives in brief/plan" — but brief/plan don't issue Bash commands that match the destructive denylist, so the rationale doesn't hold. Universal protection wins.

Added — security & extension docs (Spor 3)

  • SECURITY.md — Forgejo private-issue reporting, supported = current minor only, scope (4 hooks + denylist), hardening recommendations
  • docs/architect-bridge-test.md — manual smoke checklist for the ultraplan ↔ ultra-cc-architect bridge (1 paragraph, intentionally not CI)
  • README.md — new "Extending the plugin" section: how to add an agent, switch the planning model, disable external research, find the data contract, disable the architect bridge

Removed — vestigial config (Spor 0)

  • settings.json exploration and agentTeam blocks (read by zero code; verified via grep before deletion)
  • docs/ultra-suite-brief_2.md archived as _archive- (was paste from another plugin's work)

Tests

109 tests, all green. npm test is the fork-readiness gate.

Hook table (after v3.1.0)

Hook Event CC version Purpose
pre-bash-executor.mjs PreToolUse(Bash) 2.0+ Block destructive shell commands
pre-write-executor.mjs PreToolUse(Write) 2.0+ Block writes to sensitive paths
session-title.mjs UserPromptSubmit 2.1.94+ Set ultra:<cmd>:<slug> titles
post-bash-stats.mjs PostToolUse(Bash) 2.1.97+ Log Bash duration_ms to JSONL
pre-compact-flush.mjs PreCompact 2.1.105+ Reconcile progress.json with git history

Files changed

This release is plugin-internal — no breaking changes to artifact formats or CLI surface. Forkers should npm test after pulling to confirm readiness.

[3.0.0] - 2026-04-30

Note (2026-05-04): the ultra-cc-architect plugin is no longer publicly distributed. The architecture/overview.md filesystem contract remains supported but no public producer ships.

Architect extracted to its own plugin

The /ultra-cc-architect-local and /ultra-skill-author-local commands, all seven of their agents, the cc-architect-catalog skill, the ngram-overlap.mjs script, and the skill-factory test fixtures moved out of ultraplan-local and into the new ultra-cc-architect plugin (v0.1.0).

Why

ultraplan-local had drifted into containing two distinct domains:

  1. A universal planning pipeline (brief → research → plan → execute) that is technology-agnostic and works for any implementation task.
  2. A Claude-Code-specific architecture phase that only makes sense when building features for Claude Code itself.

Keeping them in one plugin caused three problems:

  • Users who wanted only the planning pipeline had to clone an unfinished CC-feature catalog and seven architect/skill-author agents they would never invoke.
  • The architect catalog (~11 seed skills) and the planning pipeline lived on different release cadences. Architect work blocked pipeline development and vice-versa.
  • New users saw six commands when only four belonged to the core flow.

The architect was already marked optional, v2.2 and was fully decoupled at the code level — only one filesystem touchpoint remained: /ultraplan-local auto-discovers architecture/overview.md if present, and gracefully handles its absence. The split is therefore non-breaking for the planning flow.

What moved to ultra-cc-architect

  • Commands: /ultra-cc-architect-local, /ultra-skill-author-local
  • Agents: architect-orchestrator, feature-matcher, gap-identifier, architecture-critic, skill-author-orchestrator, concept-extractor, skill-drafter, ip-hygiene-checker
  • Skills: skills/cc-architect-catalog/ (13 files)
  • Scripts: scripts/ngram-overlap.mjs, scripts/ngram-overlap.test.mjs
  • Test fixtures: tests/fixtures/skill-factory/, tests/fixtures/skill-drafter/

All moves used git mv, so history follows the files into the new plugin.

What stayed unchanged in ultraplan-local

  • /ultraplan-local Phase 1 still auto-discovers architecture/overview.md. The discovery is filesystem-based, not plugin-based — installing both plugins gives you the full pipeline (brief → research → architect → plan → execute).
  • agents/planning-orchestrator.md retains its architecture-note cross-reference.
  • All other commands (/ultrabrief-local, /ultraresearch-local, /ultraexecute-local) are untouched.

Migration

If you only used /ultrabrief-local, /ultraresearch-local, /ultraplan-local, and /ultraexecute-local: no action needed. Update the plugin and continue.

If you used /ultra-cc-architect-local or /ultra-skill-author-local: install the new plugin alongside this one. In ~/.claude/settings.json:

{
  "enabledPlugins": {
    "ultraplan-local@ktg-plugin-marketplace": true,
    "ultra-cc-architect@ktg-plugin-marketplace": true
  }
}

Custom seed skills you added to cc-architect-catalog/ follow with the catalog. Use git log --follow if you need to track them in the new location.

plugin.json changes

  • version: 2.4.0 → 3.0.0
  • description: now describes a four-command pipeline; CC-feature matching is described as living in the separate ultra-cc-architect plugin
  • keywords: removed cc-architecture

[2.4.0] - 2026-04-19

Breaking change — background mode removed

Default mode for /ultraplan-local, /ultraresearch-local, /ultra-cc-architect-local, and auto-mode in /ultrabrief-local is now foreground. The command blocks the session until the brief/plan is ready.

Why

Background mode promised a swarm of specialized agents (docs-researcher, community-researcher, architecture-mapper, plan-critic, feature-matcher, gap-identifier, …) spawned by a background orchestrator. It did not work: the Claude Code harness does not expose the Agent tool to sub-agents (including ones run with run_in_background: true). The orchestrator silently degraded to inline reasoning in a single Opus context, without WebSearch, Tavily, WebFetch, or Gemini. Briefs were tagged "high confidence" but were built on guesses from training data.

Source: github.com/anthropics/claude-code/issues/19077

Empirically confirmed in a plugin investigation on 2026-04-19: a probe sub-agent reported its exposed tools as Bash, Edit, Glob, Grep, Read, Skill, ToolSearch, Write. The Agent tool was not present, active or deferred. Foreground execution from the main context spawns sub-agents correctly (docs-researcher with Tavily intact).

What changes

  • Default execution: foreground for all four commands.
  • --fg flag is preserved as a no-op alias (backward compatibility).
  • Orchestrator agent files (agents/research-orchestrator.md, agents/planning-orchestrator.md, agents/architect-orchestrator.md) are redefined from "background executor" to "inline reference" — the command markdown itself runs the phases in the main context where the Agent tool is available.
  • ultrabrief-local auto-mode now runs research sequentially inline instead of parallel background. The ANTHROPIC_API_KEY billing check is removed (irrelevant for foreground runs on subscription).
  • skills/cc-architect-catalog/background-agents-reference.md has been corrected: Shape A (orchestrator handoff) is now documented as an anti-pattern, nested spawn from a sub-agent is NOT SUPPORTED.

For headless/long-running runs

Use claude -p in a separate terminal window. Each headless session has its own main context with the Agent tool, so the swarm works correctly.

Migration

No code changes required for users. Scripts or documentation that assume background execution must be updated — the commands now block until done.

[2.3.2] - 2026-04-18

Fixed — skill-drafter slug-collision hint

skill-drafter now checks for an existing file at {catalog_root}/<slug>.md before writing its draft to .drafts/. When a collision is detected, the agent prepends a warning block to its confirmation output showing the overwrite risk and a suggested qualified slug derived from the concept handle. The draft is still written to .drafts/<slug>.md — the check is a hint, not a block.

Why. v2.3.0 dogfood surfaced the risk (logged as post_dogfood_findings[0] in that run's progress.json): when the drafter produced .drafts/hooks-pattern.md with an existing approved hooks-pattern.md seed present at the catalog root, the pipeline gave no signal that manual mv during promotion would silently overwrite the seed. The v2.3.1 qualified-slug convention gave us the mechanism to resolve collisions, but skill-drafter still didn't surface them at the right moment — before promotion, not after.

Changes.

  • agents/skill-drafter.md — new Step 2 "Check for slug collision at the catalog root" between slug computation (Step 1) and reading the source (Step 3). Subsequent workflow steps renumbered 3→7. New "Suggesting a qualifier" guidance derives a kebab-case qualifier from the concept field (or source basename as fallback). Output format gains a Collision: field (none | approved | pending | auto-merged | soft) and an optional warning block when the collision is non-none. New Hard Rule "Slug-collision pre-write check".
  • tests/fixtures/skill-drafter/slug-collision-expected.md — new reference fixture documenting the expected confirmation-output shape across four scenarios (no collision, approved collision, soft pending collision, collision with no good qualifier). Skill-drafter is prompt-driven and not auto-tested; the fixture anchors the shape for human verification and downstream parsers.

Non-breaking. No changes to .drafts/ layout, frontmatter contract, tool scope, or filename regex. Existing pipelines see an extra field (Collision:) and an optional warning block — both purely additive. No version-gated changes in skill-author-orchestrator or ip-hygiene-checker.

[2.3.1] - 2026-04-18

Added — Qualified slug convention for cc-architect-catalog

Catalog files now follow <cc_feature>[-<qualifier>]-<layer>.md. The unqualified slug (e.g., hooks-pattern.md) remains the canonical baseline for a (feature, layer) pair. Qualified slugs (e.g., hooks-observability-pattern.md) cover specific sub-patterns without displacing the baseline.

Why. v2.3.0 dogfood surfaced a design gap: the skill-factory produced a draft hooks-pattern.md from a specialized source (progressive- alert observability) that collided with the existing generic hooks-pattern.md seed. Promoting would have replaced the general pattern with a narrow one; discarding would have lost real catalog growth. Qualified slugs resolve this by letting one feature host multiple named patterns at different abstraction levels.

Changes.

  • skills/cc-architect-catalog/SKILL.md — slug convention section added; coverage table gains "qualified patterns" column; matcher logic documented for N patterns per feature; modification rules cover qualified-vs-canonical choice and slug-collision handling.
  • agents/feature-matcher.md — catalog map is now cc_feature → {layer → [skills]}; new "Selecting among multiple patterns per feature" section (baseline by default, qualified when justified, multiple when non-overlapping, never purely cosmetic); supporting_skill accepts one-or-more skill names.
  • agents/gap-identifier.md — adds pattern_count[cc_feature] signal to the catalog coverage audit.
  • agents/architecture-critic.md — adds supporting-skill verification: every cited skill name must exist in the catalog; blocker severity.
  • First qualified skill: hooks-observability-pattern.md (promoted from .drafts/, sourced from ai-psychosis/README.md, ngram-overlap 0.01, review_status approved).

Non-breaking. Existing unqualified slugs keep working. No changes to cc_feature taxonomy. Hallucination gate unchanged (still validates against cc_feature values, not slugs).

[2.3.0] - 2026-04-18

Added — Skill-factory Fase 1 MVP (/ultra-skill-author-local)

Manual one-skill-at-a-time generator for the cc-architect-catalog. Channel 2 of the skill-factory strategy: a curated local source enters, one draft skill exits in skills/cc-architect-catalog/.drafts/, with n-gram containment scored against the source and stamped into the draft frontmatter (or the draft is deleted when overlap is too high).

Why now. /ultra-cc-architect-local (v2.2.0) enforces a hallucination gate that only permits feature proposals backed by the catalog. With 10 seed skills covering 8 features × 2 layers, the feature-matcher rarely finds a match and silently produces empty proposals. Fase 1 unblocks catalog growth without spinning up automation: one source, one draft, manual review, manual mv for promotion.

Pipeline. Sequential, no retry, no parallelism:

/ultra-skill-author-local <source>
  → concept-extractor (sonnet, JSON output, gap-class C/D + cc_feature gate)
  → skill-drafter (sonnet, .drafts/<slug>.md with 9-field frontmatter)
  → ip-hygiene-checker (sonnet, runs scripts/ngram-overlap.mjs)
      verdict accepted/needs-review → stamp ngram_overlap_score
      verdict rejected               → rm draft (no preservation)

IP-hygiene utility. Pure Node stdlib. Word-5-gram containment similarity (asymmetric draft⊆source) plus longest-consecutive-shingle- run secondary signal. Verdict bands: accepted (<0.15 AND <8), needs-review (mid), rejected (≥0.35 OR ≥15). Short-text fallback to n=4 when min(words) <500. CLI emits JSON.

Calibration fixtures. Three source/draft pairs in tests/fixtures/skill-factory/ pin the verdict bands against representative prose: accepted (containment 0.014), needs-review (0.211), rejected (0.676). Re-verify any threshold change against these fixtures.

New files:

  • commands/ultra-skill-author-local.md
  • agents/skill-author-orchestrator.md (opus)
  • agents/concept-extractor.md (sonnet)
  • agents/skill-drafter.md (sonnet)
  • agents/ip-hygiene-checker.md (sonnet)
  • scripts/ngram-overlap.mjs + scripts/ngram-overlap.test.mjs
  • skills/cc-architect-catalog/.drafts/.gitkeep
  • tests/fixtures/skill-factory/{source,draft}-{accepted,needs-review,rejected}.md
  • tests/fixtures/skill-factory/README.md

Non-goals (explicit, Fase 1):

  • No automation, cron, or watcher
  • No CC changelog diffing or auto-research
  • No batch processing or review command
  • No decision-layer skills (cross-feature comparison is Fase 2+)
  • No URL or remote sources — local files only
  • Manual mv from .drafts/ to catalog root is the promotion mechanism

New stats file: ${CLAUDE_PLUGIN_DATA}/ultra-skill-author-local-stats.jsonl.

[2.2.0] - 2026-04-18

Added — /ultra-cc-architect-local optional pipeline step

New optional command that sits between /ultraresearch-local and /ultraplan-local. Reads the task brief plus any research briefs, matches the task against available Claude Code features (Hooks, Subagents, Skills, Output Styles, MCP, Plan Mode, Worktrees, Background Agents), and produces an architecture note with brief-anchored rationale and an explicit coverage- gap section.

Pipeline position (5-steg):

/ultrabrief-local → /ultraresearch-local → /ultra-cc-architect-local (optional)
                                         → /ultraplan-local → /ultraexecute-local

The architecture note is designed as priors for planning, not mandates — /ultraplan-local still runs its own exploration and may override proposals with evidence.

New files:

  • commands/ultra-cc-architect-local.md — command entry point (7 faser: parse → background → read inputs → feature matching → synthesize → review → present).
  • agents/architect-orchestrator.md (opus) — background orchestrator.
  • agents/feature-matcher.md (sonnet) — matches CC features against brief + research, with brief-anchored rationale per feature and a documented fallback minimum list when the catalog is empty.
  • agents/gap-identifier.md (sonnet) — emits issue-ready gap drafts (no auto-posting; no auto-generation).
  • agents/architecture-critic.md (sonnet) — adversarial review with a hallucination gate (features outside catalog + fallback list → blocker).
  • skills/cc-architect-catalog/SKILL.md — manifest + frontmatter contract.
  • 10 seed skills in skills/cc-architect-catalog/: hooks-reference, hooks-pattern, subagents-reference, subagents-pattern, skills-reference, output-styles-reference, mcp-reference, plan-mode-reference, worktrees-reference, background-agents-reference. All handwritten (no third-party content copied, per brief §4.4).

New flags:

  • --project <dir> (required) — reads {dir}/brief.md + {dir}/research/*.md, writes to {dir}/architecture/.
  • --fg — foreground execution.
  • --quick — skip adversarial review.
  • --no-gaps — do not write gaps.md (gap-section remains inside overview.md).

New stats file: ${CLAUDE_PLUGIN_DATA}/ultra-cc-architect-local-stats.jsonl.

Changed — /ultraplan-local auto-discovers architecture notes

Brief §5 of the ultra-cc-architect design said "no changes to existing commands". This release makes one permitted, documented exception: /ultraplan-local now auto-discovers {project_dir}/architecture/overview.md when running in project mode. The file is additive context — missing file produces no error, and behavior when the file is absent is identical to v2.1.0. Non-breaking.

Minimal edits:

  • commands/ultraplan-local.md — Phase 1 --project branch sets has_architecture_note / architecture_note_path when the file exists. Phase 3 launch prompt passes Architecture note: {path or "none"} to the orchestrator.
  • agents/planning-orchestrator.md — Input section documents the new optional field. Phase 4 synthesis cross-references proposed features with exploration findings and carries the note's Coverage gaps into Risks and Mitigations when relevant.

Non-goals (explicit)

  • Skill-factory is not part of this release. Cataloging, n-gram computation, auto-generation from CC changelog, concept extraction from reference repos — all deferred to a separate development process. Together with v2.2.0's architect command, that process will eventually land as v3.0.
  • No /ultra-auto chaining.
  • No auto-creation of Forgejo/GitHub issues from gap drafts.
  • No changes to /ultrabrief-local, /ultraresearch-local, or /ultraexecute-local.

[2.1.0] - 2026-04-18

Changed — Dynamic, quality-gated interview in /ultrabrief-local

The Phase 3 interview is no longer a hardcoded Q1–Q8 list with a numeric cap (3–4 questions in --quick, 5–8 in default). It is now a section-driven completeness loop: the command maintains per-section state (Intent, Goal, Success Criteria, Research Plan, and five optional sections), picks the next question from the section with the weakest signal, and keeps probing until all four required sections meet an initial-signal gate. Quality drives the loop, not a counter.

Phase 4 adds a draft → brief-reviewer → revise loop. The brief is drafted in memory, written to brief.md.draft, reviewed by the brief-reviewer agent as a stop-gate, and only renamed to brief.md after all five dimensions pass (completeness/consistency/testability/ scope_clarity ≥ 4 and research_plan == 5). If the gate fails, a targeted follow-up is generated from the weakest dimension's detail field and the draft is re-reviewed. The loop is capped at 3 review iterations to bound cost; exhaustion writes the brief with brief_quality: partial and an explicit ## Brief Quality section.

Force-stop path: when the user says "stop" during Phase 4, the current review findings are surfaced with per-dimension scores before asking whether to continue or accept a partial brief. No silent exits.

Not breaking. The /ultrabrief-local [--quick] <task> interface is unchanged from the outside; only internals change. --quick now means "start compact, escalate if gates fail" rather than "max 4 questions".

Added

  • JSON output from brief-reviewer — the agent now emits a final fenced json block with per-dimension score (1–5) and detail arrays (gaps, issues, weak_criteria, unclear_sections, invalid_topics) alongside the existing prose report. The JSON block is mandatory; empty arrays and score: 5 are required when a dimension passes cleanly. planning-orchestrator continues to use the prose verdict unchanged.
  • brief_quality frontmatter field on task briefs — complete (default) when the Phase 4 gate passed, or partial when the iteration cap was hit or the user force-stopped with known issues. planning-orchestrator can inspect this to decide how heavily to weight brief sections as assumptions.
  • review_iterations and brief_quality in ultrabrief-stats — recorded per run for telemetry.

Changed

  • Hard rule added: /ultrabrief-local never writes brief.md while the review gate is pending. The draft lives in brief.md.draft until the loop terminates.
  • Hard rule added: no hard cap on Phase 3 questions; the brief-review gate is the only loop bound (3-iteration cap) and is in Phase 4.

[2.0.0] - 2026-04-18

Breaking — Four-command pipeline with dedicated brief step

v2.0.0 introduces /ultrabrief-local as a first-class step in the pipeline. The interview previously embedded inside /ultraplan-local has been extracted into a dedicated command that produces a structured task brief — the contract between user intent and planning. /ultraplan-local now requires a brief as input and no longer conducts interviews.

All artifacts converge into one project directory: .claude/projects/{YYYY-MM-DD}-{slug}/ contains brief.md, research/NN-*.md, plan.md, sessions/, and progress.json. --project <dir> works across /ultraresearch-local, /ultraplan-local, and /ultraexecute-local.

See MIGRATION.md for v1 → v2 upgrade guide.

Breaking changes

  • /ultraplan-local requires --brief <path> or --project <dir>. Running without either exits with an error and a pointer to /ultrabrief-local.
  • /ultraplan-local --spec <path> is removed. Convert specs to briefs by adding ## Intent and ## Research Plan sections (see MIGRATION.md).
  • Interview inside /ultraplan-local is removed. Planning no longer asks questions — all intent must be captured in the brief upstream.
  • spec-reviewer agent renamed to brief-reviewer with a new 5th dimension (Research Plan validity). Old spec-reviewer file is deleted.

Added

  • /ultrabrief-local command — interactive interview (3-8 questions with adaptive depth) that produces a task brief with explicit research plan. Features: project directory creation, research topic identification with copy-paste-ready /ultraresearch-local commands, optional auto-orchestration (Claude runs research + plan in foreground), and stats tracking.
  • templates/ultrabrief-template.md — canonical task brief format with ## Intent, ## Goal, ## Non-Goals, ## Constraints / Preferences / NFRs, ## Success Criteria, ## Research Plan (N topics with research_question, scope, confidence, cost), and ## Open Questions / Assumptions.
  • brief-reviewer agent — renamed from spec-reviewer with a new 5th dimension: Research Plan validity (each topic has a valid research question ending in ?, has Required for plan steps: and Confidence needed:, and research files exist when auto_research: true).
  • --project <dir> flag on /ultraresearch-local, /ultraplan-local, and /ultraexecute-local. Single directory holds the full pipeline's artifacts. /ultraresearch-local --project auto-increments {dir}/research/NN-slug.md.
  • Two-kinds-of-briefs terminology documented across README and CLAUDE.md: "task brief" (from /ultrabrief-local) vs "research brief" (from /ultraresearch-local). Prefix used consistently in agent prompts and docs.
  • MIGRATION.md — step-by-step guide for upgrading v1 projects to v2.

Changed

  • planning-orchestrator now accepts Brief file: input instead of Spec file:. Intent→Context mapping: brief's ## Intent + ## Goal feed the plan's Context section directly (structured, no inference needed). Phase 1b now uses brief-reviewer instead of spec-reviewer. With Project dir: in input, writes plan to {dir}/plan.md.
  • /ultraresearch-local supports --project <dir> with auto-indexed output path ({dir}/research/NN-slug.md, where NN is the next available two-digit index).
  • /ultraexecute-local supports --project <dir>. Reads {dir}/plan.md, writes progress to {dir}/progress.json.
  • plugin.json description rewritten to reflect four-command pipeline.

Removed

  • /ultraplan-local --spec <path> flag. Spec files are not a valid input for v2.0+. Convert to brief via /ultrabrief-local or manual conversion (see MIGRATION.md).
  • Interview Phase in /ultraplan-local (was Phase 2). Use /ultrabrief-local to conduct the interview upstream.
  • agents/spec-reviewer.md file. Replaced by agents/brief-reviewer.md.

Rationale

The v1.x interview inside /ultraplan-local conflated two concerns: capturing intent and producing an executable plan. Briefs and plans have different lifecycles — a brief should be reviewable and editable before any research or planning starts, because every downstream decision traces back to it. Extracting the brief into its own command makes the pipeline more honest: the brief is the source of truth for what we want, research briefs are sources of truth for what we learned, and the plan is the contract for how we'll do it. Separating these makes each artifact reviewable on its own terms and enables deterministic re-planning from the same brief when research reveals new constraints.

The explicit ## Research Plan section in briefs closes a common gap: plans were implicitly assuming knowledge that neither the user nor Claude had verified. Research topics are now declared upfront, scoped, and traceable back to plan decisions.

[1.8.0] - 2026-04-17

Opus 4.7 prompt literalism — closing the schema-drift gap

Opus 4.7 reads agent instructions more literally than 4.6 (per 4.7 system card §6.3.1.1). The v1.7 planning-orchestrator described the Step+Manifest schema via prose + procedural rules ("read the template"), which 4.6 inferred correctly but 4.7 sometimes rendered as narrative "Fase N" prose. The result: plans that executed cleanly on 4.6 were rejected by ultraexecute Phase 2 parsing on 4.7 — first observed during v6.2.0 planning for llm-security. v1.8.0 closes the gap by replacing prose rules with a literal copyable template, explicit forbidden-format clauses, and a pre-handoff schema self-check.

Added

  • Inline literal Step+Manifest template in planning-orchestrator Phase 5 — a complete, copyable example (JWT middleware step) replaces "read the template" prose. Removes ambiguity about heading format, field order, and manifest YAML structure.
  • Forbidden heading-format clause in Phase 5 — explicit denylist for ## Fase N, ### Phase N, ### Stage N, and other narrative formats the executor cannot parse. Negative constraints land harder on 4.7.
  • Phase 5.5 schema self-check in planning-orchestrator — after writing the plan, grep-verify canonical ### Step N: count matches manifest: count, and narrative heading count is zero. Rewrite plan if self-check fails, before handing to plan-critic.
  • --validate mode in ultraexecute-local — schema-only check that parses steps and manifests, reports READY | FAIL with specific error hints, and exits without security scan or execution. Intended as a fast sanity-check between /ultraplan-local and full execution:
    /ultraplan-local "task"
    /ultraexecute-local --validate <plan>.md   # READY or actionable FAIL
    /ultraexecute-local <plan>.md              # full execution
    

Changed

  • planning-orchestrator Phase 5 now embeds the canonical Step template inline (~60 lines of literal example) rather than referring to templates/plan-template.md. Template file remains authoritative for cross-referencing but is no longer load-bearing for plan generation.
  • ultraexecute-local Phase 2.3 added as a hard exit point for --validate mode; Phase 2.4 security scan explicitly skips this mode.

Rationale

v1.7.0's self-verifying chain assumed the orchestrator reliably produces the v1.7 schema. That held on 4.6. v1.8.0 makes the assumption robust to 4.7-style literal interpretation by moving from "describe the format" to "show the exact format and forbid alternatives", plus a self-check loop before human-visible output. Pairs with --validate as a user-facing verification step that catches any residual drift before execution side effects begin.

[1.7.0] - 2026-04-12

The self-verifying plan chain

Wave 1 of a parallel 6-session build revealed three failure modes: (1) a session reported status=completed after only 2/5 steps — last tool call was an arbitrary file review, not a completion check; (2) 3/6 sessions had push blocked inside the sub-agent bash sandbox after all work was done; (3) plans and blueprints were prose, so the orchestrator had no machine-readable way to verify completion. v1.7.0 closes all three by making the plan itself an executable contract.

Added

  • Per-step verification manifest in plan format (plan_version: 1.7). Every step now ends with a YAML manifest: block declaring expected_paths, min_file_count, commit_message_pattern, bash_syntax_check, forbidden_paths, must_contain. The manifest is the objective completion predicate — the Verify command is necessary but not sufficient.
  • Plan-critic dimension 10 — Manifest quality (hard gate). Missing or invalid manifest (unparseable regex, path contradiction, missing block) is a major finding. v1.6 plans get a legacy-mode warning instead of a block.
  • Session Manifest aggregate in session specs — synthesized by session-decomposer as the union of per-step manifests. Gives ultraexecute-local a single YAML block per session to audit against.
  • Step 0: Sandbox pre-flight — obligatory first step in every generated session spec. Runs git push --dry-run origin HEAD; exit 77 = sandbox cannot push, session status becomes blocked (not failed), no real work attempted. Escape hatch: ULTRAEXECUTE_SKIP_PREFLIGHT=1.
  • Launch script pre-flight — headless-launch-template.md adds a git push --dry-run check outside the sandbox, before any session spawns, catching credential issues at the earliest possible point.
  • Phase 7.5 — Manifest audit (independent). After all steps complete, ultraexecute-local re-verifies expected paths, commit count, commit message patterns, bash syntax, and forbidden-path untouched-ness from git log and filesystem. Agent's own bookkeeping is ignored. Disagreement with progress file → status overridden to partial.
  • Phase 7.6 — Recovery dispatch (bounded). When Phase 7.5 detects drift in multi-session parent context, synthesize a temp session spec containing only missing steps and dispatch via existing claude -p "/ultraexecute-local --session N". recovery_depth ≤ 2 hard cap — third drift escalates to user.
  • Hard Rule 17: Manifest is the completion predicate. A step may not be marked passed if its manifest does not verify, regardless of Verify's exit code.
  • Hard Rule 18: Last-activity rule. Executor's final tool call before Phase 8 must be a manifest check, never an arbitrary file review. Prevents hallucinated completion.

Changed

  • Plan template (templates/plan-template.md) — adds plan_version: 1.7 metadata line, Manifest: field on every step, "Manifest — objective completion predicate" section.
  • Plan-critic scoring rebalanced: Headless readiness 0.15 → 0.10, Manifest quality 0.05 added. Legacy v1.6 plans skip the Manifest dimension and keep Headless readiness at 0.15.
  • Planning-orchestrator Phase 5 adds "Manifest generation rules (REQUIRED for every step)" with mechanical derivation from Files: and Checkpoint. Validates regex compilation and path existence before handoff to plan-critic.
  • Session-decomposer parses plan manifests and propagates them verbatim into session specs. For v1.7+ plans with missing manifests: abort with pointer to failing step. For legacy v1.6 plans: synthesize minimal manifests and flag legacy_synthesis: true.
  • ultraexecute-local Phase 2 parses manifest YAML. Ugyldig YAML = abort with pointer to step. v<1.7 plans: synthesize + log legacy_plan: true.
  • ultraexecute-local Phase 6 — sub-step D renamed to D1 "Command verification"; new D2 "Manifest verification" runs after D1 with 5 checks. F "Checkpoint" adds checkpoint_drift logging when HEAD message doesn't match commit_message_pattern (non-fatal).
  • Phase 8 report — table gets Manifest column; JSON summary adds plan_version, manifest_audit, drift_details, recovery_dispatched, recovery_depth, legacy_plan. Result vocabulary strict: completed | partial | blocked | failed | stopped.
  • Division of labor clarified in README — /ultraresearch-local gathers context (no decisions), /ultraplan-local transforms intent into an executable contract (manifests, plan-critic gate), /ultraexecute-local executes the contract disciplined (does NOT compensate for weak plans — escalates).

[1.6.0] - 2026-04-08

Added

  • /ultraresearch-local command — deep research combining local codebase analysis with external knowledge. Produces structured research briefs with triangulation, confidence ratings, and source quality assessment. Supports modes: default (background), --quick (inline), --local (codebase only), --external (web only), --fg (foreground).
  • 6 new agents for the research pipeline:
    • research-orchestrator (opus) — runs full research pipeline as background task
    • docs-researcher (sonnet) — official documentation via Tavily, WebSearch, Microsoft Learn
    • community-researcher (sonnet) — real-world experience from issues, blogs, discussions
    • security-researcher (sonnet) — CVEs, audit history, supply chain risks
    • contrarian-researcher (sonnet) — counter-evidence and overlooked alternatives
    • gemini-bridge (sonnet) — independent second opinion via Gemini Deep Research MCP
  • Research brief template (templates/research-brief-template.md) — structured format with dimensions, confidence ratings, triangulation, and source quality assessment.
  • --research flag for /ultraplan-local — accepts up to 3 research brief paths. Enriches the interview (focuses on decisions, not facts) and injects brief context into exploration agents. Research-scout skips already-covered technologies.
  • Research-aware planning orchestrator — planning-orchestrator.md now accepts research briefs, injects summaries into sub-agent prompts, and cross-references brief findings during synthesis.
  • Research settings in settings.json — configurable Gemini bridge (enabled/timeout), interview depth, dimension limits, and stats tracking.

Changed

  • Plugin description and keywords updated to reflect research capabilities.
  • CLAUDE.md expanded with ultraresearch command, modes, agents, architecture, and state.

[1.5.0] - 2026-04-07

Fixed

  • CRITICAL: Parallel session data loss — Phase 2.6 ran parallel claude -p sessions in the same working directory, causing git race conditions and repository corruption. Each parallel session now runs in its own git worktree with isolated branch, index, and working files. Branches are merged back sequentially after each wave completes.

Added

  • Phase 2.55 (Pre-flight safety checks) — validates clean working tree, committed plan file, no scope fence overlaps between parallel sessions, and no stale worktrees before launching parallel execution.
  • Git worktree isolation for all parallel sessions — one branch per session (ultraplan/{slug}/session-{N}), merged with --no-ff after wave completion.
  • Merge conflict detection — if merging a session branch produces conflicts, the merge is aborted and conflicting files are reported. No silent data loss.
  • Unconditional worktree cleanup — worktrees and session branches are always removed, even on failure. Manual cleanup commands are reported if automated cleanup fails.
  • Hard rules 11-13 — worktree isolation mandatory, cleanup unconditional, merge sequentially with conflict abort.
  • Session-scoped progress file naming — --session N uses .ultraexecute-progress-{slug}-session-{N}.json to prevent merge conflicts.

Changed

  • Headless launch template uses git worktrees with cleanup_worktrees trap on EXIT, clean-tree pre-flight check, and sequential merge after each wave.
  • Phase 2.6 rewritten with 5-step worktree lifecycle: create → launch → wait → merge → cleanup.

[1.4.0] - 2026-04-06

Renamed

  • /ultraexecute → /ultraexecute-local — renamed for namespace consistency with /ultraplan-local and future-proofing against potential Anthropic naming. File: commands/ultraexecute.md → commands/ultraexecute-local.md. Note: ultraexecute_summary JSON key and ultraexecute-stats.jsonl filename are unchanged for backward compatibility.

Added

  • convention-scanner agent (sonnet) — dedicated agent for discovering coding conventions: naming, directory layout, import style, error handling, test patterns, git commit style, documentation patterns. Replaces inline Explore agent prompt for medium+ codebases.
  • Success Criteria section in spec template — falsifiable "definition of done" conditions that the spec-reviewer validates and ultraexecute-local uses for verification.
  • Dry-run multi-session preview — --dry-run now shows session groupings, wave structure, billing status, and claude -p commands when plan has an Execution Strategy.
  • External verification rule in headless launch template — wave verification must run commands independently, never parse session logs as proof.
  • Billing preamble in headless launch template — unset ANTHROPIC_API_KEY prevents accidental API billing.
  • Phase mapping comment in planning-orchestrator — documents how orchestrator phases 1-7 map to command phases 4-10.

Fixed

  • git add -A in escalation — replaced with targeted staging of only files from completed steps. Prevents staging secrets, binaries, or unrelated work.
  • False background: true claim — command documentation incorrectly stated the orchestrator has background: true in its frontmatter. Corrected to explain run_in_background on the Agent tool.

Changed

  • Execution Strategy reconciliation in session-decomposer — respects existing ## Execution Strategy as input instead of re-analyzing from scratch. Warns on file-overlap conflicts.
  • Headless launch template uses --dangerously-skip-permissions instead of --allowedTools for more robust headless execution.
  • Session-decomposer updated with --dangerously-skip-permissions and unset ANTHROPIC_API_KEY for generated scripts.
  • Convention Scanner references in command and orchestrator updated to use dedicated plugin agent.
  • ROADMAP.md translated from Norwegian to English.
  • plugin.json: added homepage, repository, license, keywords. Version bumped to 1.4.0.
  • README badge updated to v1.4.0.

[1.3.0] - 2026-04-06

Added

  • Session-aware parallel execution — /ultraexecute auto-detects ## Execution Strategy in plans and orchestrates multi-session parallel execution via claude -p. No manual bash launch.sh required.
    • --fg flag — force foreground sequential execution, ignoring Execution Strategy
    • --session N flag — execute only session N from the plan's Execution Strategy (used by child processes)
    • Phase 2.5 (Execution strategy decision) — determines single-session vs multi-session mode
    • Phase 2.6 (Multi-session orchestration) — launches parallel claude -p sessions per wave, waits for completion, aggregates results
  • Execution Strategy in plan template — new ## Execution Strategy section with sessions, waves, scope fences, and execution order. Generated by planning-orchestrator for plans with > 5 steps.
  • Execution Strategy generation in planning-orchestrator — Phase 5 analyzes step file-overlap to build dependency graph, groups connected components into sessions of 3–5 steps, and organizes sessions into parallel waves.

Changed

  • planning-orchestrator Phase 5 extended with Execution Strategy generation logic
  • ultraplan-local Phase 8 now lists Execution Strategy as 10th required plan section
  • Plan template includes ## Execution Strategy section template with grouping rules
  • CLAUDE.md updated with new ultraexecute modes and architecture
  • plugin.json version bumped to 1.3.0

[1.2.0] - 2026-04-06

Added

  • /ultraexecute command — disciplined plan executor with 9-phase workflow. Reads an ultraplan or session spec, executes steps sequentially with strict failure recovery, tracks progress for resume, and reports results in machine-parseable JSON.
    • 4 modes: default (execute), --resume (continue from checkpoint), --dry-run (validate without executing), --step N (single step)
    • Per-step protocol: implement → verify → on-failure handling → checkpoint
    • Failure recovery from plan's On failure clauses (revert/retry/skip/escalate)
    • 3-attempt retry cap per step (initial + 2 retries)
    • Progress file (.ultraexecute-progress-{slug}.json) for crash recovery and resume
    • Entry/exit condition checking for session specs
    • Scope fence enforcement for session specs (never-touch file protection)
    • JSON summary block in output for headless log parsing
    • Stats tracking to ultraexecute-stats.jsonl

Changed

  • CLAUDE.md restructured with two commands table (plan + execute)
  • plugin.json version bumped to 1.2.0

[1.1.0] - 2026-04-06

Added

  • --decompose mode — splits an existing plan into self-contained headless sessions. Analyzes step dependencies, groups steps into sessions of 3–5 steps each, identifies parallel execution waves, and generates session specs + dependency graph + launch script.
  • --export headless format — shortcut for --decompose. Produces the same session decomposition output.
  • session-decomposer agent (sonnet) — dedicated agent for plan decomposition. Parses step dependencies, builds dependency graph, groups steps into sessions, generates session specs with scope fences and failure handling.
  • Session spec template (templates/session-spec-template.md) — defines the format for individual session specs: context, scope fence, steps, entry/exit conditions, failure handling, handoff state.
  • Headless launch template (templates/headless-launch-template.md) — template for generating bash launch scripts that execute sessions in parallel waves using claude -p.
  • Failure recovery per step — plan template now includes On failure: (revert/retry/skip/escalate) and Checkpoint: (git commit) fields for every implementation step.
  • Headless readiness dimension in plan-critic — new 9th review dimension checking for On failure clauses, Checkpoint fields, and circuit breakers. Weighted at 0.15 in the quality score.

Changed

  • Plan-critic scoring rebalanced: 6 dimensions (was 5), weights adjusted to accommodate headless readiness
  • Plan template step format extended with On failure and Checkpoint fields
  • Planning-orchestrator Phase 5 updated with failure recovery generation requirements
  • CLAUDE.md updated with new agent, modes, and state paths

[1.0.0] - 2026-04-06

Added

  • --quick mode — skips exploration agent swarm. Runs interview → lightweight Glob/Grep scan → planning → adversarial review. For when the developer knows the codebase and needs structure, not cartography.
  • --export mode — generates shareable output from an existing plan file. Three formats: pr (PR description), issue (issue comment), markdown (clean plan without internal metadata).
  • task-finder three-tier categorization — findings categorized as Must-change (must be modified), Must-respect (contract that must not break), or Reference (context/reuse). Replaces flat file list.
  • Adaptive interview depth — interview adapts to answer quality. Detailed answers trigger fewer, more targeted questions. Short/uncertain answers trigger simpler questions with offered alternatives.
  • Complete plugin.json metadata — author, homepage, repository, license, keywords added.
  • README badges — version, license, and platform badges.
  • Known limitations section in README — IaC projects (Terraform, Helm, Pulumi, CDK) get reduced value from exploration agents.
  • Forgejo issue templates — bug report and feature request YAML templates.
  • CONTRIBUTING.md — rewritten for honest solo-project model.

Changed

  • plugin.json version bumped to 1.0.0
  • Command header updated to Ultraplan Local v1.0
  • Orchestrator accepts mode: quick in prompt for lightweight scanning path

[0.4.0] - 2026-04-06

Added

  • 3 new agents for information-complete planning:
    • task-finder — dedicated agent for finding task-relevant files, functions, types, and reuse candidates. Replaces inline Explore agent.
    • git-historian — analyzes git log, blame, active branches, code ownership, and hot files for planning context.
    • spec-reviewer — reviews spec quality (completeness, consistency, testability, scope clarity) before exploration begins. New Phase 1b/4b.
  • Plan scoring — plan-critic produces a quantitative quality score (0–100) across 5 weighted dimensions with letter grades (A–D) and verdicts (APPROVE/REVISE/REPLAN).
  • No-placeholder rule — plan-critic flags TBD, TODO, vague instructions, and underspecified steps as unconditional blockers. 3+ blockers = REPLAN regardless of score.
  • [ASSUMPTION] marking — planning-orchestrator marks all unverifiable claims and warns when >3 assumptions exist.

Changed

  • All agents run for all codebase sizes. Small codebases get the same 6 core agents as large ones. Agent turns scale down for small codebases instead of dropping agents entirely.
  • Phase 4b (spec review) added before exploration in both command and orchestrator.
  • Orchestrator Phase 2 agent table expanded: 6 always + 1 conditional + 1 medium-only.
  • Plan-critic review checklist expanded with no-placeholder checks (section 7) and scoring output.
  • Orchestrator rules updated with assumption-marking and no-placeholder requirements.

[0.3.0] - 2026-04-05

Added

  • planning-orchestrator agent — dedicated background agent (background: true) that handles Phases 4–10 autonomously. Replaces generic background agent spawning with a purpose-built orchestrator running on Opus with maxTurns: 50.
  • effort and maxTurns on all agents — fine-grained cost and depth control:
    • Exploration agents: effort: medium, maxTurns: 15–20
    • Review agents (plan-critic, scope-guardian): effort: high, maxTurns: 10
    • Research-scout: effort: medium, maxTurns: 10
  • Plugin settings.json — default configuration for mode, research, agent counts, interview limits, and team settings. Users can override in their own settings.
  • Worktree isolation for Agent Teams — team members use isolation: "worktree" to prevent file conflicts during parallel implementation
  • Session tracking (Phase 12) — writes JSONL records to ${CLAUDE_PLUGIN_DATA}/ultraplan-stats.jsonl with task metadata, agent counts, review verdicts, and outcomes

Changed

  • Phase 3 now launches the planning-orchestrator agent instead of a generic background agent
  • Agent Team implementation uses worktree isolation by default

[0.2.0] - 2026-04-05

Added

  • Interview phase — iterative requirements gathering with AskUserQuestion before exploration. Produces a spec file that feeds into planning.
  • 7 specialized agents in agents/ directory:
    • architecture-mapper — deep architecture analysis, anti-patterns, smell detection
    • dependency-tracer — import-chain following, data-flow analysis, side-effect catching
    • test-strategist — test strategy design based on existing patterns
    • risk-assessor — threat modeling, edge cases, failure modes
    • plan-critic — dedicated adversarial reviewer with hardcoded critical perspective
    • scope-guardian — scope creep and scope gap detection
    • research-scout — external research via WebSearch/Tavily for unfamiliar technologies
  • External research capability — research-scout agent searches documentation, known issues, and best practices when the task involves external/unfamiliar technology
  • Background mode — default mode runs interview in foreground, then plans in background. User is notified when done.
  • Spec-driven mode (--spec) — skip interview, provide a pre-written spec file, plan entirely in background
  • Foreground mode (--fg) — all phases in foreground, blocks session (v0.1.0 behavior)
  • Agent Team support — when plan has 3+ independent steps, offers parallel implementation via Agent Teams
  • Spec template in templates/spec-template.md
  • Research Sources section in plan template for citing external research
  • Dual adversarial review — plan-critic and scope-guardian run in parallel

Changed

  • Exploration agents replaced with named specialized agents from agents/ directory
  • Agent count scales with codebase: 3 (small), 5 (medium), 7 (large)
  • Plan template extended with Research Sources and external tech fields
  • Handoff phase supports "execute with team" option
  • Command workflow expanded from 9 to 11 phases

[0.1.0] - 2026-04-05

Added

  • Initial release
  • /ultraplan slash command with 6-phase workflow
  • Parallel Sonnet exploration (3 agents: architecture, task-relevant, conventions)
  • Opus-driven plan generation from structured template
  • Plan refinement loop with execute/save handoff
  • Plan template with context, analysis, steps, alternatives, risks, verification
  • Cross-platform support (Mac, Linux, Windows) — pure markdown, no scripts