The known issue "E's own review has no Claude Security scan" no longer
holds: with the operator's consent (S214) Claude Security 0.12.0 scanned
the branch against main at e6c6a54 (scan changes, effort high, 64 changed
files, 10 of 10 researchers returned): 0 findings, verification status
verified. The bullet now says that, and that the scan ran by hand outside
/trekreview, so no review verdict holds it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CHANGELOG Unreleased gains E: the stop rule, "Known issue" after it, the
optional threat model, the critic's own security key SECURITY_RISK and the
security engine (Added); the Pass 2 heading, "6 of 3" and the dedup null
crash (Fixed); the known issues of decisions 220-226 and of E's own review
(the between-rounds holes, a fixed security MAJOR after the review stop
rule, the planted report folder, F5, the below-threshold check, the
unattended cost question, scan_prefix, no real /trekreview with Claude
Security, the plan side's rests, --brief next to --hash or --diff, the fix
round's test gaps, no Claude Security scan of E's own diff, copies and
repeated work); and one two-way door.
verdict-gate.mjs: the comment on the threat model's repo no longer says
"the answers' repo" (with a subdirectory as --repo the answers are read
from the top level and the threat model from the subdirectory; V2 of the
fix round's check). No code change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The one narrow fix round after /code-review high on E (three findings of
new classes; the between-rounds findings are known issues, decision 226):
- threat-model.mjs isOwnSecurityFinding: the engines' key in rule_key is
never Voyage's own, also when rule_keys names a key of its own (keysOf
reads rule_keys alone when it is a list, so an entry with rule_key
SECURITY_REVIEW_VULNERABILITY and rule_keys [SECURITY_RISK] could be
backed, against decision 218).
- plan-gate.mjs: --brief without --record is a usage error (exit 2); the
bare gate and --accept-open read the verdict's brief_path, and a --brief
there was silently ignored.
- verdict-gate.mjs: the known_outside check reads the threat model from the
answers' repo (--repo, else the review file's own work tree); with no
work tree nothing is backed. A review outside any work tree, gated from
another repo, was backed by that repo's brief (ALLOW).
Each with a test seen failing on an assertion first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quality only, no behaviour change (four cleanup reviewers, one implementer;
npm test 2480/0 on the working tree):
- threat-model.mjs splitBacked(): the one known_outside backing check of
plan-gate (record and bare gate), verdict-gate and review-finalize, with
one why-text; the engines' security keys derived from ENGINES; isSecurity.
- coordinator-contract: "not a security engine" read from ENGINES (a string
engine only), not the code-review literal.
- review-rounds owns trailingBlock, findingsBlockSha, isMajor, isBlocker;
review-answers imports them (review-rounds still imports nothing from it).
prepare keeps the archive bytes it read instead of reading the previous
archive again.
- engine-compare exports rowIn and payloadEngine; finalize uses them.
- plan-gate: one accepted_open builder; the stop-rule check hoisted; one
top-level lookup for --record --brief.
- security-engine: notFullShas(), runCli's usage flag, readScopeList shared
with engine-findings; findReport and reviewRoundSummary module-private;
two dead defaults gone.
- tests: shared plan-gate harness and threat-model brief helpers; the [CNV]
table cases call convertReport in-process, one CLI case per exit path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tests/lib/review-rounds.test.mjs: round 2 whose Claude Security payload
holds the round-1 BLOCKER only in out_of_scope keeps it counted through
the real finalize and verdict gate (BLOCK, gate exit 1, not under
Resolved since round 1); a clean run resolves it (F-V4; red under the
mutation that drops out_of_scope from raisedOutside).
- README.md, SECURITY.md: "blocks only at confidence high" names the
exception of decision 222 (counted at high in an earlier round, it stays
counted when it comes back below high or outside the scope) (F-V5).
- commands/trekreview.md Phase 5: an engine finding is held by a matching
finding in review.md (engine MAJOR/BLOCKER put back first) or a matching
below_threshold / out_of_scope entry; an engine MINOR or SUGGESTION the
coordinator left out holds nothing, a known issue (decision 226).
- tests/lib/review-prose-pins.test.mjs: both sentences pinned; red on the
old prose.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two fail-closed checks in security-engine.mjs convert (decision 224), both
"not measured" (exit 2, the reason on stderr, nothing on stdout):
- the stamp's findings.total is not a non-negative integer, or the JSONL
holds another number of records (a JSONL that lost the only BLOCKER line
converted clean before; part 3 verifier, F3);
- the stamp's scope is not an empty list: a scan limited by --scope, an
absent scope or a non-list scope (Claude Security 0.12.0 writes scope: []
for an unscoped scan; F4).
The real Claude Security 0.12.0 probe report still converts: exit 0, one
BLOCKER, two below_threshold.
Decision 223, text only: the module header and SECURITY.md keep the
head/base check and say it is a trace, not a signature: code the reviewed
run executed can write a report folder of its own (convert reads the
matching one whose name sorts last) or delete the real one first (F2, a
known issue). /trekreview's not-measured list names the two new reasons.
The test helper writes the real stamp shape by default (findings.total =
the records in the JSONL written, scope: []). New tests for behaviour that
had none (F6): no fallback from an unverified newest match, a two-stamp
folder passed over, a symlinked stamp, JSONL or folder refused, a malformed
or absent scan_prefix, an unrecorded empty_diff or empty_scope.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Claude Security finding counted at confidence high in round N that Claude
Security raises again at a lower confidence in round N+1 landed in that
payload's below_threshold, never in findings. Finalize passed only findings
to carry, the engine was in ran.engines, so the round-N finding was marked
resolved and the verdict fell from BLOCK to WARN (part 3 verifier, F1).
carry takes a new option, raised: the engine entries a round raised outside
findings. A previous engine finding that no current finding matches stays
carried, never resolved, when an entry of its own engine matches it (the
same file, then the same rule_key or content overlap); each entry holds at
most one previous finding. Without the option carry behaves as before.
Finalize's carry pass builds raised from every engine payload's
below_threshold and out_of_scope, the engine taken from the payload's
reviewer, never from the entry.
The carry rule is restated in the review-rounds and review-finalize headers,
/trekreview's round prose and Handover 6.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase 4.7 of /trekreview runs security-engine.mjs choose first. Claude
Security runs through its own skill (scan changes --base {before_sha}
--effort high); its cost question goes to the operator, and "No", a
question nobody can answer or a missing Workflow tool records it as not
run, never a fallback to /security-review. /security-review runs only
when choose picked it. Its report is converted by security-engine.mjs
convert, never transcribed; below_threshold is declined as
engine:below-threshold. With no engine the expected reviewer
security-engine never reports, so the verdict gate exits 2 and the
summary says "security: not measured" and why, never 0. --quick keeps no
security engine. The Engine summary line, the template's ran line, the
hard rules (the engine's report folder, scan changes only) and the
allowed-tools (Workflow) follow.
Engine prose follows in commands/trekexecute.md, docs/command-modes.md,
docs/architecture.md, CLAUDE.md, README.md, SECURITY.md and Handover 6:
Claude Security recommended, proprietary so called by name and never a
manifest dependency; without it /security-review; with neither "not
measured".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/review/security-engine.mjs (decisions 175, 196, 219):
- choose: Claude Security when available and base..head has committed
changes; else /security-review when origin/HEAD resolves and
origin/HEAD...HEAD is non-empty; else no engine (no-engine, no-origin,
empty-diff), which is "not measured", never 0. A git failure or bad
usage is exit 2, never a reason.
- convert: reads the newest CLAUDE-SECURITY-<ts>/ report whose stamp is a
changes scan of exactly base..head; confidence high becomes engine
findings through toReviewerPayload, the rest go to below_threshold and
never into findings. An unverified scan, missing researcher counts,
fewer researchers returned than dispatched, an empty diff or scope, or
a malformed record is exit 2.
- NO_ENGINE_REVIEWER: with no engine chosen the expected reviewer
security-engine never reports, so the verdict gate exits 2.
ENGINES gains claude-security (its own reviewer and brief_ref, the
engines' key) with a per-engine label for the written action; it is a
security engine in isSecurityFinding, RAN_ENGINES, the coordinator
contract (out-of-scope and brief-conflict rules) and the coordinator
prose; engine:below-threshold is an unverified reason fed like
engineOutOfScope. Pins of the changed coordinator prose follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The verifier's look at ff46f57 found three fail-safe MINOR findings, all
text that did not yet say decision 221 or said it inaccurately:
- commands/trekplan.md Phase 9 and the plan-gate.mjs comment said only that a
backed finding leaves the count and the stop rule; both now say it applies
to the round's new findings, and a finding counted in an earlier round
stays counted until a reviewer marks it resolved.
- Handover 4 said a known_outside entry "left the counted findings"; it now
says that holds for a new finding of its round, and that a carried copy of
the same id stays counted, so one id can sit in both findings and
known_outside.
- The CHANGELOG Known issues bullet said the loop "then stops" and that the
way on is the operator's choice at the stop rule. The stop rule fires only
when the blocking findings do not get fewer, and a counting security
finding is never accepted (PLAN_GATE_SECURITY_OPEN): the way on is a
reviewer marking it resolved or "New mechanism". The bullet also names the
shared id (two findings at one line and key, one mark resolves both).
No code change.
Part 2 of the E plan, decision 221.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Undone: item 2 of the Part 2 fix round (1be961a). recordVerdict no longer
drops a copy rule A carried as counted when a finding with the same id is
backed this round, and no longer recomputes the counts, `lowered` and the
stop-rule summary for it; the isLowered helper and the SEVERITIES import it
needed are gone. Why: the id is (file, line, rule_key), so a DIFFERENT
backed security finding at the same line and key knocked a counted security
finding inside the threat model out of the count (round 2 PASS, its text
gone), against decisions 218 and 220.
The rule now, as decided: the threat model applies only to this round's
new findings (the deduped findings, before countRound); a finding counted
in an earlier round stays counted, through rule A's carry, until a reviewer
marks it resolved. The gate never counts less. Items 1 and 3-8 of the fix
round are untouched.
Tests: the fix-round case for item 2 now asserts the decided rule (the
carried copy stays counted, BLOCK, the stop rule fires not-fewer, the gate
stops); a new case pins that a different backed finding at the same line
and key leaves the counted one, with its own text, in the count.
The plan-gate header and the known_outside comment, and Handover 4's
known_outside sentence, state the rule. CHANGELOG Unreleased, Known issues:
a finding counted earlier stays counted when an Outside: line approved
later puts it outside, or when it moves to another plan line; the way on is
the operator's choice at the stop rule.
Part 2 of the E plan, decision 221.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1. plan-review-dedup skips only a null or undefined finding; any other
entry that is not an object (a string, a number, an array) goes on as
before E, a finding with no valid severity that the plan gate counts as
a blocker (it was dropped, so a string blocker recorded PASS).
2. plan-gate --record: a previous finding that rule A carried as counted and
whose id is backed this round leaves the counted set, the counts, the
verdict and the stop rule's summary (it was counted and listed in
known_outside at once: BLOCK, not-fewer, and --accept-open refused).
3. A known_outside entry keeps rule_keys; extractVerdict accepts it (a list
of strings), and the bare gate re-checks with the same keys the recorder
used, so a merged finding whose security key is only in rule_keys is a
WARN, not a STOP.
4. plan-critic, scope-guardian and /trekplan Phase 9's round-2 sentences say
the Critic Verdict also lists known_outside and each is marked by id in
previous. Code already accepts such a mark (dedup passes it; countRound
ignores ids it does not carry; --record removes the entry on true);
pinned in diff mode and full count.
5. The approval prose names ## Threat Model where it named only ## Intent +
## Goal: skills/annotating/SKILL.md (description, step 4, guard list),
docs/command-modes.md, Handover 1's intent_approved_hash row, README
(approval, Approve row, intent approval gate) and CLAUDE.md's /trekbrief
row.
6. threat-model.mjs gains usableInRepo (a brief path relative to the repo
top level) and repoRelativeBrief; --record stores brief_path relative to
the top level, never absolute, and both gates read it from there, so the
gate run from a subdirectory reads the same brief. reviewThreatModel
uses usableInRepo. Handover 4 and the gate header say so.
7. review-finalize's outside pass puts an entry back only when no finding
carries its row yet (engine-compare rowOf): an engine finding listed in
known_outside while its payload is saved went back twice.
8. A test runs scripts/release-check.mjs on a review whose known_outside
entry the brief does not back: exit 2 (control: backed passes the review
check).
Existing tests changed: plan-gate-threat-model's entry-keys assertion now
expects rule_keys (item 3), and its planted non-security entry drops the
security key from rule_keys too, since the gate reads rule_keys (item 3).
Part 2 fix round of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The code-correctness reviewer's dimension 6 shrinks to what the engines do
not read: command, skill and agent markdown carrying shell, with Claude
Code's threshold (a concrete attack path, high confidence), the keys
SECURITY_INJECTION or SECURITY_RISK, and threat_model_ref quoting the
brief's Outside: line; the code-level bullets go to the engines.
The coordinator puts a Voyage security finding with a threat_model_ref
into the trailing JSON block's known_outside, never into findings.
review-finalize gains the pass `outside`, right after engine: it only
raises. An entry the brief at the review's brief_path does not back now
(line gone, threat model not usable, an engine finding, not a security
finding) goes back into the findings at its catalogue tier with a Source
line, R-step and raised verdict, as the engine put-back does; the rest are
listed under the new `## Outside the Threat Model` section.
verdict-gate decideOpenFindings (and so scripts/release-check.mjs)
re-checks every entry against brief_path through the new
notBackedOutside and exits 2 for one not backed. review-validator
shape-checks the optional known_outside (REVIEW_KNOWN_OUTSIDE_MALFORMED).
threat-model.mjs gains reviewThreatModel and isKnownEntry for the three.
/trekreview Phase 8.8 lists the known issues outside the threat model
(not answered, not counted); the review template shows the section and
field; Handover 1 names the optional ## Threat Model and its code,
Handover 6 names known_outside and its code.
Part 2, step 2.5 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
plan-gate.mjs --record --brief <brief.md> (a known flag; its value is kept
out of the positional arguments, a missing value is a usage error) applies
the brief's threat model to the deduped findings before countRound when
threat-model.mjs usable() says it may: a backed finding (Voyage's own
security finding whose threat_model_ref equals an Outside: line's text)
leaves the counted set and the stop rule and goes to the new optional
verdict field known_outside ({id, rule_key, text, line}), carried to later
rounds until a reviewer marks it resolved or it is reported again under its
id. The verdict stores brief_path (carried when a later round has none).
The --record line adds known_outside (a count) and threat_model
({applied, why}): a threat model that is not usable backs nothing, every
security finding counts, and the output says why. extractVerdict
shape-checks both new fields.
The bare gate re-reads the brief at brief_path each run: an entry still
backed is a warning, PLAN_GATE_KNOWN_OUTSIDE; one no longer backed (line
gone, approval stale or not logged, brief unreadable, no brief_path, or not
a Voyage security finding) stops the plan, PLAN_GATE_OUTSIDE_NOT_BACKED: it
counts in full. gatePlan takes an optional threatModel for tests.
plan-review-dedup keeps threat_model_ref on a merge only when every merged
copy carries the same one; the S160 known issue is fixed: a null in a
reviewer's findings list is skipped instead of crashing the CLI.
plan-critic and scope-guardian: a security finding needs a concrete attack
path and high confidence (Claude Code's threshold, 167), uses
SECURITY_INJECTION or SECURITY_RISK, and quotes the Outside: line's text in
threat_model_ref when one applies; the json template carries the field.
/trekplan Phase 9 passes the brief path to plan-critic and --brief to
--record. Handover 4 names the two fields, the two codes and the flag.
Part 2, step 2.4 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/review/rule-catalogue.mjs gains SECURITY_RISK (BLOCKER, category
security, memory route rule): Voyage's own security key for a finding by
its own reviewers that SECURITY_INJECTION does not cover.
SECURITY_REVIEW_VULNERABILITY is described as the engines' key only.
plan-critic and scope-guardian name SECURITY_INJECTION or SECURITY_RISK
and no longer the engines' key.
The count moves from 17 to 18 in every pin: rule-catalogue.test,
claude-md-scope [CAT] (which now also refuses a stale 17), doc-consistency,
review-prose-pins, docs/architecture.md and the two reviewer agents.
critic-severity-rules pins three security keys; its "every security key
named" check leaves out the engines' key, and a new pin says the critic
never names it.
Existing tests changed for the planned rule: the four count pins above
(17 -> 18), and critic-severity-rules' two-key test (now three keys).
tests/lib/engine-findings.test.mjs: a comment naming the "(17 keys)" pin
now says 18.
Part 2, step 2.3 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New lib/review/threat-model.mjs, the one reader both gates use:
readThreatModel(briefText) -> {present, inside, outside, problems} through
brief-validator's parseThreatModel; usable(briefPath, repo) = present, well
formed, and the intent approval current by the two checks /trekplan Phase 1
runs (checkIntentApprovalContent, then verifyLog kind intent with the
hash's sha256: stripped and the subject normalized), else not usable with
the reason in `why`; backedLine(finding, tm) = the Outside: text the
finding's threat_model_ref equals exactly, else null. Only a security
finding not from an engine can be outside (218): a finding with an
`engine`, or carrying the engines' key SECURITY_REVIEW_VULNERABILITY, is
never backed.
Part 2, step 2.2 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A brief may carry an optional `## Threat Model` with one line per bullet,
`- Inside: <text>` or `- Outside: <text>`. Present and malformed (no such
bullet, another label or form, empty text, two sections) is
BRIEF_THREAT_MODEL_MALFORMED; absent is today's rule. No brief_version bump
(the ceremony / artifact_store precedent). Sections are found fence- and
comment-aware through intent-approval's new sectionTexts, so the validator
and the hash count the same sections; brief-validator exports
parseThreatModel for the reader.
The intent hash covers `## Threat Model` when present (two sections -> null
hash, as Intent and Goal), so an edited, added or removed threat model
makes the approval stale; a brief without one hashes exactly as before. The
stale message and the /trekplan halt table name the section.
/trekbrief offers the section in its question round when the task touches
a guard, a gate, untrusted input, secrets or publishing, writes it only
when given, shows it verbatim at the Phase 4h approval, and --approve reads
it out. The template documents it; brief-gate-coverage pairs the new code.
Part 2, step 2.1 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- plan-gate: the bare gate's stale-verdict reason no longer says "run the
next round" once the stop rule fired; it says there is no next round, as
acceptOpen already does.
- trekplan Phase 9: "REVISE after the last round" (Fix now with
--extra-round) is qualified "and the stop rule did not fire", pinned in
review-loop-docs.test.mjs next to the [STP] pins.
- plan-gate-stop-rule tests: a planted stop-rule acceptance claiming an open
security blocker stays STOP; a planted acceptance without under:
"stop-rule" stays STOP; the "a blocker -> refused" test now asserts the
blocker refusal; --accept-open under the stop rule covers an open MAJOR
and the gate passes with a WARN.
- review-rounds prepare: when the stop rule is judged (P >= 2) and either
round's JSON block cannot be read, exit 2 (not measured) with "stop rule:
a round has no readable JSON block" instead of skipping the rule. The
[RND] differing-archive and [CAP] fixtures now use readable archives; one
new [STP] test covers an unreadable archive and an unreadable review.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekplan Phase 9: when --record or the gate reports the stop rule there
is no new round; AskUserQuestion with the class and counts, "Known issue"
(--accept-open, a security finding refused) or "New mechanism" (stop, the
plan stays unapproved); the round-3 blocker path never offers
--extra-round after the stop rule. Phase 10 prints round of
max_rounds + extra_rounds.
/trekexecute Phase 7.2 step 4: after a round-2 BLOCK or fixed-pending,
before any R-step, review-rounds.mjs prepare --dry-run; review-stop-rule:
gives the same question ("Known issue" = /trekreview --answers, a BLOCKER
keeps the merge locked; "New mechanism" = stop). /trekreview Phase 3 tells
the stop rule's exit 1 from the cap's. plan-critic and scope-guardian:
rule_key names the class, never the instance.
New pins in review-loop-docs, critic-severity-rules and review-prose-pins.
Part 1, step 1.4 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
prepare (also --dry-run) judges the previous round's archive and
review.md when it would open round 3: blocking = BLOCKER + counting MAJOR
with the verdict gate's pre-existing reading, new = no carried_from, class
= classOf. Fired -> exit 1, `review-stop-rule: <describeStop line>` and
`stop_rule`, nothing archived. The cap stays. A round with no readable
JSON block gives no summary and the rule is not judged.
countingMajors moves from review-answers.mjs into review-rounds.mjs and is
re-exported by review-answers (as isSecurityFinding is); review-rounds
still imports nothing from review-answers.
Existing test updated for the planned rule: the [CRY] occurrence case adds
a third round-1 MAJOR resolved in round 2, so its round-3 control is not
stopped by "not fewer".
Part 1, step 1.3 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recordVerdict appends each round's summary to a new optional verdict
field `rounds` (carried from the previous verdict; newByClass null for a
round counted in full) and stores `stop_rule`; extractVerdict shape-checks
both. After a fired stop rule --record exits 1 with PLAN_GATE_STOP_RULE
and writes nothing (--extra-round included). The bare gate stops with
PLAN_GATE_STOP_RULE and the operator line in place of the open-blocker and
open-major reasons; --json and --record output carry the decision.
--accept-open after a fired stop rule is allowed with rounds left, covers
open blockers and majors (`under: "stop-rule"`), refuses a counting
security finding (PLAN_GATE_SECURITY_OPEN); the gate then warns.
Known issue fixed: REVIEW_LOG_SECTIONS drops "Adversarial Pass 2 (v5.1.1
high-effort)"; the CHANGELOG known-issue line closes and Handover 4 names
the heading list, the new fields and codes.
Existing tests updated for the planned rule: fixtures that ran a later
round after one with no fewer blocking findings now use a falling count
(plan-gate.test round cap, plan-gate-open-major lastRound, diff-mode
5/18/27 resolve two earlier majors in round 2); the diff-mode CLI pipe
case now expects PLAN_GATE_STOP_RULE (round 3: 2 blocking) after its
clean round 2.
Part 1, step 1.2 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New lib/review/stop-rule.mjs: classOf (catalogue key, else the lower-cased
dimension before the first slash, else unclassified), roundSummary
(blocking = blockers + counting majors; new = no carried_from; null map
for a round counted in full), decideStop (same-class / not-fewer on the
last pair, round 1 alone never fires) and describeStop (one operator line
with the class, the counts per round and the two recommendations).
Part 1, step 1.1 of the E plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes Voyage's own stats/OTel export (R1), STORM and the --engine
research choice (R2), and profiles, phase signals and the effort dialog
(R3), plus the R-a leftovers. One fixed path per command (209).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/code-review high on main..HEAD: the four commands that parse their own
arguments in prose (/trekbrief, /trekplan, /trekresearch, /trekexecute) lost
their --profile handling, and /trekresearch its --engine, so a typed value
became the path or the question. Each now strips a retired flag with its
value; the arg parser retires --profile only for the commands that had it
(not /trekendsession) and --engine for /trekresearch, seen red first.
Stale lines R-b left: architecture's hook row (9 scripts) and bridge agent,
the gap row's removed event ledger, README's contrarian marker, and a
dangling "also" in /trekexecute Phase 8.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The retired --profile is one list the parser drops (with its value, never
an error) instead of a valued flag in six schemas, so the removed-surfaces
check exempts one parser line, not seven; seen red on the old parser.
The empty OPTIONAL_STRING_KEYS machinery, a one-item loop and an unused
plugin-data dir go; the removed-surfaces check reads each file once; the
Phase 8 slice in executor-prose-pins asserts both anchors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The /trekresearch Phase 4 sentence said contrarian-researcher runs every
time, also under --local; it now runs whenever the scope includes external.
Three stale "sequencing gate" and stats mentions in touched files follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The four profiles, the resolver, the profile validator and docs/profiles.md go;
/trekbrief Phase 3.5 and the brief's phase_signals checks go (an older brief's
key is ignored); MANIFEST_PROFILE_DRIFT and profile_used go. Every Profile,
Composition rule, Sequencing gate and High-effort section leaves the commands.
Decision 209: /trekresearch runs the full swarm with contrarian-researcher as
wave 2 every run; /trekreview and the coordinator run all four passes with no
high-effort normalization. Voyage agents are spawned with no model (their own
model: opus applies); the two built-in spawns pass model "opus". --profile
stays in the parser as a retired flag that swallows its value. §Model & effort
moves to docs/architecture.md; the sequencing-gate eval case goes.
Files removed: 44 (43 from the R3 list + tests/commands/trekreview.test.mjs,
whose every test pinned removed text). Files edited: 43.
Tests: 2467 (2466 pass / 0 fail / 1 skipped) before, 2309 (2309 pass / 0 fail /
0 skipped) after. Durable check: all three groups green, none pending.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/trekresearch loses Phase 4.5, the bounded Phase 5 loop (Phase 5 keeps its
single pass of at most 2 follow-ups), the --engine flag, the deep-research
adapter and its output self-check. hooks.json loses the pre-agent-cap
PreToolUse entry (README: 9 hooks = 9 scripts). The STORM env vars leave the
docs; query-privacy-gate.mjs stays, called by no command, and says so.
Files removed: 13 (4 docs, 1 hook, 1 lib module, 1 script, 5 tests, 1 fixture).
Files edited: 17. Tests: 2600 (2598 pass / 0 fail / 2 skipped) before,
2467 (2466 pass / 0 fail / 1 skipped, R3 pending) after.
Durable check: group R2 green and no longer pending.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes Voyage's measurement, statistics and export apparatus (decision 189;
condition 175 met in step 1) and the R-a leftovers: lib/stats/, lib/exporters/,
the otel-export and post-bash-stats hooks, yardstick, end-state and comparison
gates, synthesis-measure, gold-scorer, docs/observability.md,
examples/observability/, docs/T1-cc26-delegated-orchestration.md and their
tests and fixtures. The six command stats phases and the /trekexecute
main-merge event blocks go; intent-approval --stamp no longer emits
brief-approved. README and docs point to Claude Code's own OpenTelemetry.
Files removed: 52. Files edited: 37.
npm test: 2930 tests (2928 pass / 0 fail / 2 skipped) before, 2600 tests
(2598 pass / 0 fail / 2 skipped) after. removed-surfaces group R1 green.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seen red with REMOVED_SURFACES_ALL=1 before any removal: R1 546, R2 251,
R3 606 lines. Each stage of R-b empties its own pending group.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The trekcontinue-stats line_ref follows Phase 5 to 271-275 (the Phase 1.5
cut moved it). gold-eval.test.mjs and its run fixture come back: they
are the one end-to-end check that the review contract keeps every
seeded finding, and they stay with the scorer until R-b. CHANGELOG:
the removed validator leaves the known-issues text; the review's other
findings outside R-a's files are listed as known issues.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
engine-compare imports the coordinator's title limit and trim instead
of a copy whose reason went with Arm B; the autonomy gate exports one
parser and its test runs in-process with two CLI runs; one import
scanner in lib-imports; the fenced-section walker shared from
tests/helpers/md-section.mjs instead of six copies; plan-gate hash
in-process; living-paths scans once; routing drops the orchestrator
filter whose files are gone; small leftovers removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
33 more tests of live behaviour from the deleted round files, each in
the test file named after its source and seen failing under a mutation
of that source (log in the project folder). Two stay dropped: one pinned
the removed gate states, one the old Phase 1.5 file comparison. The two
trekexecute.md sentences that still said /trekcontinue compares the two
prompt files now say it uses the project-folder file (line count kept).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
R4-R7 of the cleanup list (decision 188): the June trial docs and
fixtures, the three orchestrator reference docs, the dormant
synthesis-agent, code with no caller (project-discovery, bash-normalize,
fidelity-diff, test-census, the next-session prompt validator, arm B and
the --workflow flag) and the fix-round chain. Living docs repointed; the
reasons for in-session orchestration and the all-opus pin are now written
in docs/architecture.md and docs/profiles.md.
New tests/lib/living-paths.test.mjs: living tracked text names only
plugin paths that exist (seen red with 22 dead pointers before this
commit). docs/T1-cc26-delegated-orchestration.md and
lib/review/gold-scorer.mjs stay until R-b: the frozen end-state registry
names them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/util/autonomy-gate.mjs keeps only gatesValue + parseGatesArgs and the
CLI ({"ok":true,"gates":true|false}; exact usage error on a bad value;
the old --state/--event arguments are a usage error). The four commands
run 'autonomy-gate.mjs --gates [value]' and read gates. Prose (README,
operations, architecture, sdlc-playbook-gap) and the S24, gates-flag
and [#1] tests follow (R9).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
R8 of cleanup R-a (plan .claude/projects/2026-11-07-cleanup-r-a, appendix A).
The live tests of the round files move into the test named after their
source; each moved test was seen red under a mutation of its source.
New: tests/lib/lib-imports.test.mjs, tests/lib/timing.test.mjs (from
timing-under-load). The [#1] --gates rule and shim-line pins move into
tests/lib/autonomy-gate.test.mjs.
Removed: the round test files (retterunde, retterunde-prose-pins,
trial-mechanical-fixes, trial2-fixes, trial2-minor, trial2-minor-prose-pins,
fix-round-4-5a-prose, fix-round-4-5b2-b-prose, timing-under-load), the 8 R8
e2e scripts, and seven round test files on the R-a removal list that pinned
them (fix-round-4-5b-prose, fix-round-4-5b-part-2/3/4-scripts,
fix-round-4-5b-part-4-prose, fix-round-4-5b2-b/c-scripts). The diff-mode e2e
pin (test 24) and the red-script round-wrapper cases go too.
tests/synthetic/plan-run-C.md becomes tests/fixtures/plan-run-c.md,
regenerated from buildPlan({ version: '1.9' }). The red judge, reporter and
judge test headers now name the shared red script.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>