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>
Round 8 (0f400d3..29b4ac9, BLOCK: 1 BLOCKER, 12 MAJOR, 1 MINOR). Each fix
began with a test that failed on 29b4ac9 (13 tests, all red there); suite
2221 (2219/0/2).
- BLOCKER: a backticked check whose trailing comment holds a quote, $,
backtick or backslash is refused, not dropped. The comment was never
screened, while the executor hands the Verify span as written to red
proof, the test lock and the done line inside --cmd "...", where a $(...)
runs and a quote ends the argument. trekplan's text and the reviewer's
NOT RUN table say so.
- A span that is only a comment is not-a-command, not a placeholder. The
dropComment text says the allowlist still refuses a word with a # in it.
- The criteria runner, comparison-gate and end-state-gate use isMain: they
did nothing and exited 0 under a symlinked path. The test now refuses any
process.argv[1] comparison outside lib/util/is-main.mjs.
- Files: in a field with backticked paths, a plain word counts only before
the entry's description (a dash, or a colon after the path); a name with
no slash only first in its entry or after and/or/+/&. "mocks
fs.readFileSync", "runs on Node.js 22.x" or "no change to package.json"
no longer make a tests-only step look like it builds something.
Lowercase makefile, rakefile and justfile are build files. Measured on the
520 Files: fields in 48 plans of the marketplace and the test repo:
3 fields read differently (two notes no longer read as files, one
duplicate name dropped), tests-only changed in 0.
- The test lock compares --cmd without its trailing comment, and the test
lock and the done line read a stop with stoppedBy, the one reading.
red-proof drops its second reading, spawnError.
- release-check reads a relative --review in --repo or, when only that one
exists, from the current directory as 6.3.0 did; two different files are
exit 2, never guessed. The runbook says so.
- One trailing-json reader: a closing fence may be longer than three
backticks, in the block reader and the verdict gate alike, and the review
validator and the synthesis digest use it, so three backticks inside a
JSON string no longer hide a BLOCKER from the remediation-step check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 7 (516dffa..45aa9e1, WARN: 12 MAJOR, 0 BLOCKER) and the fence defect
found while writing its review.md. Each fix began with a test that failed on
0f400d3 (v6.3.0); suite 2208 (2206/0/2), 14 tests more.
- Tests-only (operator 2026-10-11): the plan's Files: alone decides, and the
text says so (red-proof, trekexecute Sub-step B, step-implementer,
HANDOVER-CONTRACTS). red-proof no longer reads the step's diff, so a change
already in the tree when the step began no longer counts against it, and a
plan placed outside .claude/ reads the same. The round-6 test that had the
diff overrule the plan is rewritten to the new rule.
- The Files: reader keeps a plain file beside a backticked path
(", Dockerfile", "the CLI entry src/cli.mjs", "and Makefile"). Measured on
the 520 Files: fields in 182 plans: no field reads differently.
- Red proof reports a command its timeout killed as killed after the timeout,
not "could not start"; the release check tells a timeout from output past
its buffer and from another signal. One reading of a stop
(criteria-runner stoppedBy) for red proof, the criteria runner and the
release check.
- A trailing `# comment` is dropped in a backticked check too, and in a
command passed as written, so the words screened are the words run.
- The release check reads a relative --review in --repo.
- The 15-minute timeout is defined once (criteria-runner.mjs).
- The findings check reads each cited file once per validation.
- One isMain helper (lib/util/is-main.mjs) for every CLI: the 31 copies of
the realpath guard and the 20 modules still on the file:// guard, which
exited 0 having done nothing under a symlink or a path with a space.
- The Bash guard writes its no-one-to-ask refusal once, on a direct condition.
- The findings check ends a ```json block only at a fence on its own line, so
three backticks inside a JSON string no longer end it (also in 6.2.0).
- Brief-conformance notes: a test for test-lock green on exit 127 (it
passed at once; it fails when 127 is read as could-not-run); the prose now
names the git revision `@~1` as the one leading-@ exception.
Not changed: the example plan's steps 1-2 keep their tests-only warning
(operator decision 2026-10-09; the r5 test records it). Brief note 4 (a
Regression: whose runner is not installed goes to the fix rounds) is a
routing question for the operator.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 3 (v6.2.0..96cb977, BLOCK: 1 BLOCKER, 8 MAJOR, 2 MINOR), each fixed
behind a test that failed first.
- Every allowlisted runner, not only git, takes plain words and a short list
of options that only read: an option that writes a file or loads code
(--test-reporter-destination, --outputFile, --junitxml, --basetemp,
--import, --config, -p, -o, -exec, a reporter path) is on no list; after
`npm test --` only paths follow; `make test` takes no VAR=value. A built-in
node test reporter (tap, spec, dot, junit, lcov) stays allowed.
- /trekexecute: a restore the guard refuses (destructive git, in the mode
that shows no prompts) or the operator declines is never recorded as
reverted: simplify = "revert-refused" and the run stops before review; a
refused step revert is reported with its paths.
- stepTestsOnly: a fixture document under tests/ is a test file, "e.g." is
not a path, ./ is dropped; the plan-file sweep reads Files: with the same
reader (fieldPaths); the validator hands its parsed fields over.
- plan-validator --steps-from asks for Verify: on a 1.8 plan too.
- skill frontmatter: a value starting with # is a hazard; a quote after an
escaped backslash closes the value. Routing reads kind tags with hasOwn.
- release-check reads scope_sha_end as written (an all-digit sha keeps its
leading zero), and Voyage's own artifacts under .claude/projects/ and
.claude/voyage/ committed after the review do not count as unreviewed.
Suite 2170 (2168/0/2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
P13 (wave 2, order 8). docs/release-runbook.md has three parts: before the
release, the release, and the rollback. The rollback was drilled first, in a
sandbox with local bare repos as the remotes: a release 6.2.0 -> 6.2.1, then
path A (git revert, catalog ref back to v6.2.0) and path B (a forward patch
6.2.2 that carries the revert), with the catalog's check-versions green after
each. Nothing reached a real remote; the real catalog was byte-identical
before and after.
Measured: release-plugin.mjs refuses a ref backwards while plugin.json still
says the newer version, and accepts it once the release commit is reverted.
scripts/release-check.mjs decides before a release: clean tree, npm test
green at HEAD, review verdict not BLOCK (K7) and covering HEAD, and a door
type per delivery (### Doors in the CHANGELOG section). 0 ready, 1 not
ready, 2 could not run (never green). A ready run prints the K2 command that
logs the operator's yes.
tests/lib/release-prose-pins.test.mjs holds every command in the rollback
part to the commands the drill ran (tests/fixtures/release-drill/).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>