• v6.4.0 a3fa5de42a

    v6.4.0 Stable

    ktg released this 2026-10-16 22:25:08 +00:00 | 85 commits to main since this release

    Signed by ktg
    SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q

    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).
    Downloads