#793 added one small operator-run check — an MCP smoke test — and five cold-review rounds found five
false greens in the verification code itself, each after the first introduced by the fix for the
one before. The rule this records: the proof obligation follows the verdict, not the file, so it
binds harnesses, wrappers, timeouts and checkers — not only the files the guard population derives.
The part worth reviewing
The first commit stated the position the issue asked for — that operator-run checkers are exempt —
and cold review refuted it by execution:
It claimed scripts/mcp_smoke.py "cannot participate" in the mutation harness because driving it
needs the gitignored .mcp.json and a cold-built language server. False — it takes its config
path and server name as positional arguments. The record had failed its own headline rule
(READING THE CONSTRUCT IS NOT EXECUTING IT) on the one claim its decision rested on.
It split on "can CI execute it", which equally describes every .claude/hooks/*.sh and .husky/pre-push, several of which carry MUTATION rows. The real discriminator is whether a
proof test can drive the construct hermetically.
So rather than restate the exemption, this ships the proof:
scripts/tests/test_mcp_smoke.py — a stub JSON-RPC responder and six cases pinning the
defects the checker has already had (impostor identity, a body carrying only an id, a missing
expected tool, a pre-answered initialize, a pre-answered tools/list), with the positive control
as a fixture the refusal tests depend on, so a node-id or -k selection cannot skip it.
Hermetic: no .mcp.json, no language server.
A declared clause in mutation_manifest.py targeting mcp_smoke.py's unguessable request id,
using the guard=test / target=script shape that already exists for mutation_harness_lib.py —
no population derivation changes.
Witnessed red, not asserted.id_init = secrets.randbelow(...) → id_init = 1 makes the
pre-answer accepted at initialize, so the run dies one stage later at tools/list (rc 9 → 10)
and the proof reddens with its declared diagnostic. Only that test moves. The harness re-applies it
every suite run.
mcp_smoke.py still gets no inventory row — one is rejected as a phantom (measured). The row goes to
the test file, which joins the derived population automatically.
Two results worth keeping
A twin that wasn't one. Review flagged id_tools as an unproven sibling clause. Measured three
ways: id_tools = 2 alone → all green; the reader's pending-retention clause alone → all green; both → rc 0. The tools/list stage is held by two mechanisms that mask each other (#685's
shape), which is why id_init — the one place a pre-answer is singly exploitable — is the
declared clause.
An absence standing in for a refusal. The pre-answer test was satisfiable by a stub emitting nothing, since a silent server also yields rc 9. The stub now drops a marker once it has emitted,
and the test asserts it, so the case cannot pass without posing the attack it narrates.
Review
Five rounds, four of them BLOCKED. Round 2 caught a ruff format red that would have failed script-tests — a standing rule I skipped. Rounds 3–5 found only hand-maintained counts and
uniqueness claims in prose, three of which were created by the previous round's fix; round 3
correctly identified that class as the generating layer, so the counts were deleted rather than
corrected again. Round 5: VERDICT: MERGEABLE. The commit after it applies only that reviewer's
own pre-merge recommendations (8 insertions, 8 deletions, all weakenings of claims).
Cross-family review was attempted twice and produced no verdict (usage limit, then a run that
terminated before reporting), so every verdict here is same-family.
Verification
scripts/tests: 1104 passed, 2 skipped on the rebased tree (includes #868, merged mid-session).
ruff format --check + ruff check: clean over all 47 tracked Python files.
decisions_validate.py OK; build_decisions_catalog.py --check → catalog up to date.
Runtime claims executed, not read: perl -e 'alarm shift; exec @ARGV' 5 /nope → rc 0 vs rc 2 with or die; [ -x /bin ] true; no timeout/gtimeout; .mcp.json ignored at .gitignore:12;
ShellCheck 0.11.0 flags neither shell defect.
Docs updated in the same PR
docs/README.md task-signal map and docs/guard-inventory.md (new row, summary counts, scope-limit
item 6), per CLAUDE.md's docs-update rule.
Records `testing.verification-code-needs-its-own-proof`, and ships the proof the record would
otherwise have been claiming an exemption from.
fixes #796
## What this is
#793 added one small operator-run check — an MCP smoke test — and five cold-review rounds found five
false greens **in the verification code itself**, each after the first introduced by the fix for the
one before. The rule this records: the proof obligation follows the **verdict**, not the file, so it
binds harnesses, wrappers, timeouts and checkers — not only the files the guard population derives.
## The part worth reviewing
The first commit stated the position the issue asked for — that operator-run checkers are exempt —
and cold review refuted it *by execution*:
- It claimed `scripts/mcp_smoke.py` "cannot participate" in the mutation harness because driving it
needs the gitignored `.mcp.json` and a cold-built language server. **False** — it takes its config
path and server name as positional arguments. The record had failed its own headline rule
(`READING THE CONSTRUCT IS NOT EXECUTING IT`) on the one claim its decision rested on.
- It split on "can CI execute it", which equally describes every `.claude/hooks/*.sh` and
`.husky/pre-push`, several of which carry `MUTATION` rows. The real discriminator is whether a
proof test can drive the construct **hermetically**.
So rather than restate the exemption, this ships the proof:
- **`scripts/tests/test_mcp_smoke.py`** — a stub JSON-RPC responder and six cases pinning the
defects the checker has already had (impostor identity, a body carrying only an id, a missing
expected tool, a pre-answered `initialize`, a pre-answered `tools/list`), with the positive control
as a **fixture the refusal tests depend on**, so a node-id or `-k` selection cannot skip it.
Hermetic: no `.mcp.json`, no language server.
- **A declared clause** in `mutation_manifest.py` targeting `mcp_smoke.py`'s unguessable request id,
using the `guard=test / target=script` shape that already exists for `mutation_harness_lib.py` —
no population derivation changes.
**Witnessed red, not asserted.** `id_init = secrets.randbelow(...)` → `id_init = 1` makes the
pre-answer *accepted* at `initialize`, so the run dies one stage later at `tools/list` (rc 9 → 10)
and the proof reddens with its declared diagnostic. Only that test moves. The harness re-applies it
every suite run.
`mcp_smoke.py` still gets no inventory row — one is rejected as a phantom (measured). The row goes to
the test file, which joins the derived population automatically.
## Two results worth keeping
- **A twin that wasn't one.** Review flagged `id_tools` as an unproven sibling clause. Measured three
ways: `id_tools = 2` alone → all green; the reader's pending-retention clause alone → all green;
**both** → rc 0. The `tools/list` stage is held by two mechanisms that mask each other (#685's
shape), which is why `id_init` — the one place a pre-answer is *singly* exploitable — is the
declared clause.
- **An absence standing in for a refusal.** The pre-answer test was satisfiable by a stub emitting
*nothing*, since a silent server also yields rc 9. The stub now drops a marker once it has emitted,
and the test asserts it, so the case cannot pass without posing the attack it narrates.
## Review
Five rounds, four of them BLOCKED. Round 2 caught a `ruff format` red that would have failed
`script-tests` — a standing rule I skipped. Rounds 3–5 found only hand-maintained counts and
uniqueness claims in prose, three of which were *created by the previous round's fix*; round 3
correctly identified that class as the generating layer, so the counts were **deleted** rather than
corrected again. Round 5: `VERDICT: MERGEABLE`. The commit after it applies only that reviewer's
own pre-merge recommendations (8 insertions, 8 deletions, all weakenings of claims).
Cross-family review was attempted twice and produced no verdict (usage limit, then a run that
terminated before reporting), so every verdict here is same-family.
## Verification
- `scripts/tests`: **1104 passed, 2 skipped** on the rebased tree (includes #868, merged mid-session).
- `ruff format --check` + `ruff check`: clean over all 47 tracked Python files.
- `decisions_validate.py` OK; `build_decisions_catalog.py --check` → catalog up to date.
- Runtime claims executed, not read: `perl -e 'alarm shift; exec @ARGV' 5 /nope` → rc 0 vs rc 2 with
`or die`; `[ -x /bin ]` true; no `timeout`/`gtimeout`; `.mcp.json` ignored at `.gitignore:12`;
ShellCheck 0.11.0 flags neither shell defect.
## Docs updated in the same PR
`docs/README.md` task-signal map and `docs/guard-inventory.md` (new row, summary counts, scope-limit
item 6), per CLAUDE.md's docs-update rule.
#793 added one small operator-run check and five cold-review rounds found five
false greens in the verification code itself, each introduced by the fix for the
previous one. All five sat outside `docs/guard-inventory.md`'s population and
always would have: a `perl` wrapper inside an `if` is not a file, and the script
holding it is invoked by no workflow or hook.
Records `testing.verification-code-needs-its-own-proof`: the obligation follows
the VERDICT rather than the file, and how it is discharged depends on where the
construct runs. A checker CI can execute keeps the existing contract (an
inventory row, and at MUTATION a declared clause re-applied every run). A checker
CI cannot execute — operator-run, needing gitignored config or a live server —
gets neither, and ships a witnessed negative control recorded in its PR instead.
Extending the manifest to the second class was considered and rejected because it
would reproduce the defect it was meant to close: `scripts/mcp_smoke.py` needs
`.mcp.json` (gitignored) and a cold-built language server, so a row for it would
be a declared mutation that never executes — the exact false green
`testing.mutation-claims-are-executed` exists to abolish. The residual (a recorded
control decays; nothing re-runs it) is stated in the record rather than papered over.
Also folds in the stop-and-subtract trigger (two consecutive rounds of
fix-creates-the-next-defect means delete the layer, not guard it) and the macOS
timeout recipe, whose wrong form was the recommended one.
Every runtime claim in the record was executed rather than read, per its own rule:
`perl -e 'alarm shift; exec @ARGV' 5 /nope` exits 0 (the false green, reproduced)
while the `or die` form exits 2; `[ -x /bin ]` is true; neither `timeout` nor
`gtimeout` is present; `.mcp.json` is ignored at `.gitignore:12`.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cold review BLOCKED the first commit on two findings, both correct, and both
refuted by execution rather than argument.
1. The central premise was false. The record said `scripts/mcp_smoke.py` "cannot
participate" in the mutation harness because driving it needs the gitignored
`.mcp.json` and a cold-built language server. It takes its config path and
server name as POSITIONAL ARGUMENTS (`mcp_smoke.py:78`), so a test can hand it
a synthetic config pointing at a stub responder. The record failed its own
headline rule — that claim was read, not executed.
2. The split was drawn on the wrong axis. "CI cannot execute it" also describes
every `.claude/hooks/*.sh` and `.husky/pre-push`, all of which carry MUTATION
rows because a pytest proof drives them in a sandbox. The discriminator is
whether a proof test can drive the construct HERMETICALLY.
So instead of restating the exemption, this ships the proof:
- `scripts/tests/test_mcp_smoke.py` — a stub JSON-RPC responder and five cases
pinning the defects the checker has already had (impostor identity, a body
carrying only an id, a missing expected tool, a pre-answered request), plus an
anti-vacuity positive control. Hermetic: no `.mcp.json`, no language server,
7.9s.
- A declared clause in `mutation_manifest.py` targeting `mcp_smoke.py`'s
unguessable request id, using the `guard=test / target=script` shape that
already exists for `mutation_harness_lib.py` — no population derivation changes.
Witnessed red, not asserted: replacing `id_init = secrets.randbelow(...)` with
`id_init = 1` makes the pre-answer ACCEPTED at `initialize`, so the run dies one
stage later at `tools/list` (rc 9 -> 10) and the proof reddens with its declared
diagnostic. Only that one test reddened; the mutation is clause-scoped.
`mcp_smoke.py` still gets no inventory row — a row for it is rejected as a
phantom, measured — so the row goes to the test file, which joins the population
automatically. Also corrected: the "acquires a real row" migration the mechanism
would refuse (HIGH 3); "shellcheck caught 0 of 5", re-measured as neither of the
TWO shell defects, the other three being Python and outside its reach (MEDIUM 4);
a threshold misattributed to `release.verdict-vocabulary-shared`, which carries a
categorical ban rather than a count (MEDIUM 5); an unverifiable "no shared
reviewers" claim (MEDIUM 6); a dangling cross-reference to a private memory
filename (LOW 7); and the scope-limit item that actually excludes defects 2/4/5
(LOW 8).
Docs updated in the same PR per CLAUDE.md: `docs/README.md`'s task-signal map now
routes to four guard rules rather than three, and `docs/guard-inventory.md`'s
scope limit item 6 records that being outside the population is not an exemption.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Self-caught before re-review landed, and it is the same shape as the finding that
blocked round 1: a universal asserted rather than measured.
The record argued that "can CI execute it" is the wrong discriminator because
every `.claude/hooks/*.sh` and `.husky/pre-push` is operator-run yet "all carry
MUTATION rows". Reading the table: 3 of 13 hooks do (`posttooluse-worktree-marker`,
`pretooluse-bom-guard`, `pretooluse-worktree-guard`), plus `.husky/pre-push` — four
in total. Most of the rest are graded NONE.
The argument is unaffected: four guards that CI never fires as hooks are
nonetheless proven by a pytest proof driving them in a sandbox, which is all that
is needed to refute the does-CI-run-it discriminator. Only the quantifier was
wrong, and the correction now names the four and says explicitly that the NONE
majority is unproven debt rather than evidence for the other reading.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cold re-review round 2. One finding was a genuine CI red I should have caught
locally; the rest are overclaims in prose. One of its findings dissolved under
measurement into something more useful.
**The red.** `ruff format --check` failed on `scripts/tests/test_mcp_smoke.py` —
the only file of the 47 tracked Python files that did. I never ran ruff on a file
I wrote, which is a standing rule and not a subtle one. Formatted; the whole
population is clean and `ruff check` passes.
**The twin that was not a twin.** The review flagged `id_tools` as an unproven
sibling clause: mutating it leaves every case green, while the inventory advertised
the guard as catching "an answer pre-answered before the request". Measured on
isolated copies, three ways:
- `id_tools = 2` alone -> all green
- reader retention clause alone -> all green
- BOTH -> rc 0, the false green
So the tools stage is held by TWO mechanisms that mask each other — the reader keeps
only the reply matching the id in flight, so a `tools/list` frame emitted while
`initialize` is pending is dropped whatever its id. That is #685's shape, benign
here but worth naming. `id_init` is the one place a pre-answer is SINGLY
exploitable, which is why it stays the declared clause. The tools case is kept as
behavioural coverage with a docstring that states the measurement instead of the
mechanism I had assumed — the first version of it narrated a vulnerability that
does not exist, which is the defect this issue is about, one level in.
**The absence-assertion.** The review demonstrated that gutting the stub so it
emits NOTHING still satisfied the pre-answer test, because a silent server also
yields rc 9. The stub now drops a marker file once it has emitted, and the test
asserts it — so the case cannot pass without having posed the attack it narrates.
**Anti-vacuity is now a dependency, not a convention.** The positive control moved
into a module fixture the refusal tests depend on; a node-id selection or `-k` can
no longer skip it.
Prose corrections: coverage stated as six named refusal paths rather than "every
protocol branch" (the config/command/spawn stages are not driven); "the defect
history sits on the provable side" conceded — two of the five defects were in
`check-local-lsp.sh`, the file this record puts in the exempt branch; the wall-clock
timing dropped for the invariant; and the `mechanics` claim that one call site
carries all three traps narrowed to the two it actually carries. The `GUARD`
row citing itself is now recorded as a deliberate vocabulary stretch rather than
left to look routine.
Verification: 1104 passed, 2 skipped; ruff format+check clean over all 47 tracked
Python files; decisions-validate OK.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Not review findings — a systematic pass over every factual claim the record makes,
checking each against the file it describes rather than against my memory of it.
1. The record said defects 1 and 3 were "a `perl` wrapper inside an `if`, which is
not a file at all". Defect 1 was a `[ -x "$cmd" ]` test, not the wrapper, and
both live in `scripts/check-local-lsp.sh` — which IS a file. The point survives
and is now stated correctly: that file is outside the population because no
workflow or hook invokes it, and `mcp_smoke.py` because it is reached only
through it (scope limit item 6).
2. "drives SIX of its refusal paths" — the file has six test functions, of which
one is the positive control. It drives FIVE refusals plus the success path. A
count taken from the wrong denominator, which is the coverage-overclaim shape
round 2 had just corrected elsewhere in the same paragraph.
3. `docs/README.md` called this "the four rules every guard must satisfy". It is
not a fourth guard rule — its whole content is that the obligation extends
BEYOND guards, to the verification code doing the checking. Restored to three
guard rules plus this one as an extension, which is also what makes the
task-signal row useful to someone whose file holds no inventory row.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Round 3 fired this record's own stop-and-subtract trigger, and the useful part of
the review was identifying WHICH layer to delete. Round 2's findings lived in the
new test file; every round-3 finding lives in record prose, and each is a
hand-maintained QUANTITY or NOVELTY claim that round 2 introduced while correcting
a different overclaim. Both counts round 2 wrote were off by one, in the same
direction. The test file itself survived six independent attacks this round with
zero findings.
So the layer being deleted is the counts, not the proof.
- The coverage count is GONE rather than corrected a third time. The test file's
docstring already enumerates what it drives and names what it does not, so the
record points at that one list instead of keeping a number in step with it. This
is `state-the-invariant-not-the-measurement`, owed to a record whose subject is
unmeasured verification claims. Corroborating: the one place this was stated by
ENUMERATION rather than by count — the inventory's `Blocks` column — was correct
throughout.
- "Three of the five were in `mcp_smoke.py`, and those are the ones now pinned" was
false for defect 4. Reintroducing its shape (a line-cap chunker whose overflow
suffix re-parses as a fresh message) leaves the suite green, by design: the file
records that territory as deliberately uncovered, because the caps that would
bound it WERE the defect. Now says defects 2 and 5 are pinned and why 4 is not.
- The inventory's "stretches the vocabulary" overstated novelty. Measured: 10
pre-existing rows self-cite, and `test_mutation_harness.py` is already a
self-citing GUARD whose declared `target` is another script. This is the second
row of that shape, not a new one.
Two further round-3 findings were already fixed in ea0a9fd2b before the review
landed (the SIX/FIVE count and the defect-1-is-not-a-perl-wrapper claim); its
independent instrumentation of `fail()`'s call sites confirms those fixes land on
the right five sites.
Also caught by the decisions guard on the way through: a bare apostrophe inside the
single-quoted `rule:` scalar, which PyYAML rejects. Doubled.
Verification: 1104 passed, 2 skipped; ruff format+check clean over all 47 tracked
Python files; decisions-validate OK.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Self-run sweep of the whole change for hand-maintained counts, universals and
novelty claims — the class round 3 identified as this change's defect generator.
It found four more, including one introduced by round 3's own fix.
- **"the SECOND row of that shape"** (guard-inventory item 6) was FALSE. Round 3
correctly said my "vocabulary stretch" framing overstated novelty; my correction
overstated precision in the other direction. Measured by joining the inventory's
self-citing rows against the manifest: EIGHT rows are a self-citing GUARD whose
declared `target` is a different file, and `test_review_verdict_vocabulary.py` ->
`scripts/check-review-verdict.sh` is a closer analogue than the one I named. The
ordinal is deleted rather than corrected — two examples, no count.
- **"the single in-repo site carrying the perl recipe AND the check-the-exit-code
discipline"** asserted a uniqueness that cannot be checked; plenty of scripts
check exit codes. Narrowed to the half that is verifiable and verified: the perl
recipe appears in exactly one place.
- **"Every case below asserts a REFUSAL"** was false of the block it introduces —
the positive control sits below that comment and asserts a pass.
- **"the ONLY thing refusing a server that answers before it is asked"** was
unqualified in both the test message and the manifest `why`, while round 2 had
measured that the `tools/list` stage is held by two mechanisms. Both now say AT
THE `initialize` STAGE, and say why the pending-registration cannot help there:
that id is already in flight when the pre-answer arrives.
Claims swept and confirmed TRUE rather than changed: "every one of the five defects
was in code nobody had counted as a guard"; "FOUR of them carry MUTATION rows";
"NEITHER of the two shell defects"; "NONE of those controls survived as a test"
(nothing but this file and the manifest references `mcp_smoke.py`); "replacing
`id_tools` alone leaves every case here green".
Verification: 1104 passed, 2 skipped; ruff format+check clean over all 47 tracked
Python files; decisions-validate OK.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Round 4's sweep found that my round-3 fix for a false count was itself false, and
that the pending replacement for a second one was false in a new way. Both are the
same class this change keeps regenerating: a hand-maintained quantity or uniqueness
claim about prose.
- "The perl recipe appears in exactly one place in-repo" — false. `git grep 'alarm
shift'` returns three hits in two files, and two of them are inside this record
(the `mechanics:` line and defect-table row 3). Replaced with the claim that is
both true and greppable: the only place that RUNS it is `check-local-lsp.sh:107`.
An executing-site claim survives the record quoting itself; a repo-wide
uniqueness claim does not.
- "three defects with one cause" is not supported by the record's own table, which
attributes one numbered defect to the caps. It came from #796's body, so it is
not invented, but no reader can check it from here. Replaced with the invariant
it was standing in for: the layer was the cause, not any clause inside it.
- "each introduced by the fix for the previous one" — defect 1 was in the initial
version of `check-local-lsp.sh`, so it had no predecessor. Now "each after the
first".
- `docs/README.md` said "the three rules every guard must satisfy" immediately
before a cell listing four links. True today and rots on the next rule; the
count is dropped.
- The test file's list of undriven `fail()` sites read as exhaustive while omitting
the usage, `--project`, initialize-returned-an-error and zero-tools stages. Now
says "among them" and names those too.
- `mutation_harness_lib.py` is a module, not a script; the inventory now says
"another file".
The round-3 finding that prompted this (the false "SECOND row of that shape") was
already committed as fixed in 13001ee2d before this review landed — round 4
independently re-derived the population and confirms that correction, and that both
precedents it names are real.
Verification: 1104 passed, 2 skipped; ruff format+check clean over all 47 tracked
Python files; decisions-validate OK; catalog up to date.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Round 5 returned MERGEABLE and found nothing false. These are its durability
findings — statements that are true today and that an unrelated future edit would
quietly falsify. Taking them because each is one line and each removes a number
that nothing checks; the class has cost four rounds already.
- "yet FOUR of them carry MUTATION rows — <closed list>" was the most exposed
claim in the change: the same sentence calls the remaining hooks "unproven
debt", so it invites the very upgrade that falsifies its own count, in three
places (the `rule:`, the body, the mirrored catalog row), with nothing checking
it. The argument needs at-least-one, not exactly-four. Now "several … among
them".
- "The only place that RUNS this recipe is `check-local-lsp.sh:107`" was true, but
the record exists to publish that recipe for reuse — the first script to adopt it
falsifies the claim, and that author has no reason to open this record. The line
number rots on any edit above it. Both dropped.
- "scope limit item 6"/"item 7" are positional references into another file's
numbered list, bound by nothing: appending is safe, inserting silently repoints
them. Now named as well as numbered.
- "so there is one list rather than a number" — the inventory row's "what it
blocks" cell is a second enumeration, mandated by the row format. "a list".
- The defect table sits ABOVE the paragraph that said "the five defects below".
- `scripts/mcp_smoke.py`'s ACCEPTED LIMIT note said the caps "caused three defects
in an earlier round", which contradicts the record that is now the canonical
account and counts them as one of five. Pre-existing, but this PR is what makes
it a contradiction, so it is fixed here rather than left for a reader to
reconcile. Docstring only — the declared mutation clause is untouched and still
unique in the file.
Verification: 1104 passed, 2 skipped; ruff format+check clean over all 47 tracked
Python files; decisions-validate OK; catalog up to date.
Refs: #796
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Five cold-review rounds (4 BLOCKED, round 5 MERGEABLE). Round 2 caught a ruff-format red that would have failed script-tests. Rounds 3-5 found only hand-maintained counts/uniqueness claims in prose, three created by the previous round's fix; that class was deleted rather than corrected again. Code was attacked exhaustively in rounds 3 and 4 with zero findings; declared mutation witnessed red and clause-scoped. Commits after the MERGEABLE verdict apply only that reviewer's own pre-merge recommendations (8 insertions, 8 deletions, all weakenings of claims). Gate: 1104 passed, ruff clean over 47 files, decisions-validate OK.
Review-verdict: MERGEABLE @ 1080e0b
Five cold-review rounds (4 BLOCKED, round 5 MERGEABLE). Round 2 caught a ruff-format red that would have failed script-tests. Rounds 3-5 found only hand-maintained counts/uniqueness claims in prose, three created by the previous round's fix; that class was deleted rather than corrected again. Code was attacked exhaustively in rounds 3 and 4 with zero findings; declared mutation witnessed red and clause-scoped. Commits after the MERGEABLE verdict apply only that reviewer's own pre-merge recommendations (8 insertions, 8 deletions, all weakenings of claims). Gate: 1104 passed, ruff clean over 47 files, decisions-validate OK.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Records
testing.verification-code-needs-its-own-proof, and ships the proof the record wouldotherwise have been claiming an exemption from.
fixes #796
What this is
#793 added one small operator-run check — an MCP smoke test — and five cold-review rounds found five
false greens in the verification code itself, each after the first introduced by the fix for the
one before. The rule this records: the proof obligation follows the verdict, not the file, so it
binds harnesses, wrappers, timeouts and checkers — not only the files the guard population derives.
The part worth reviewing
The first commit stated the position the issue asked for — that operator-run checkers are exempt —
and cold review refuted it by execution:
scripts/mcp_smoke.py"cannot participate" in the mutation harness because driving itneeds the gitignored
.mcp.jsonand a cold-built language server. False — it takes its configpath and server name as positional arguments. The record had failed its own headline rule
(
READING THE CONSTRUCT IS NOT EXECUTING IT) on the one claim its decision rested on..claude/hooks/*.shand.husky/pre-push, several of which carryMUTATIONrows. The real discriminator is whether aproof test can drive the construct hermetically.
So rather than restate the exemption, this ships the proof:
scripts/tests/test_mcp_smoke.py— a stub JSON-RPC responder and six cases pinning thedefects the checker has already had (impostor identity, a body carrying only an id, a missing
expected tool, a pre-answered
initialize, a pre-answeredtools/list), with the positive controlas a fixture the refusal tests depend on, so a node-id or
-kselection cannot skip it.Hermetic: no
.mcp.json, no language server.mutation_manifest.pytargetingmcp_smoke.py's unguessable request id,using the
guard=test / target=scriptshape that already exists formutation_harness_lib.py—no population derivation changes.
Witnessed red, not asserted.
id_init = secrets.randbelow(...)→id_init = 1makes thepre-answer accepted at
initialize, so the run dies one stage later attools/list(rc 9 → 10)and the proof reddens with its declared diagnostic. Only that test moves. The harness re-applies it
every suite run.
mcp_smoke.pystill gets no inventory row — one is rejected as a phantom (measured). The row goes tothe test file, which joins the derived population automatically.
Two results worth keeping
id_toolsas an unproven sibling clause. Measured threeways:
id_tools = 2alone → all green; the reader's pending-retention clause alone → all green;both → rc 0. The
tools/liststage is held by two mechanisms that mask each other (#685'sshape), which is why
id_init— the one place a pre-answer is singly exploitable — is thedeclared clause.
nothing, since a silent server also yields rc 9. The stub now drops a marker once it has emitted,
and the test asserts it, so the case cannot pass without posing the attack it narrates.
Review
Five rounds, four of them BLOCKED. Round 2 caught a
ruff formatred that would have failedscript-tests— a standing rule I skipped. Rounds 3–5 found only hand-maintained counts anduniqueness claims in prose, three of which were created by the previous round's fix; round 3
correctly identified that class as the generating layer, so the counts were deleted rather than
corrected again. Round 5:
VERDICT: MERGEABLE. The commit after it applies only that reviewer'sown pre-merge recommendations (8 insertions, 8 deletions, all weakenings of claims).
Cross-family review was attempted twice and produced no verdict (usage limit, then a run that
terminated before reporting), so every verdict here is same-family.
Verification
scripts/tests: 1104 passed, 2 skipped on the rebased tree (includes #868, merged mid-session).ruff format --check+ruff check: clean over all 47 tracked Python files.decisions_validate.pyOK;build_decisions_catalog.py --check→ catalog up to date.perl -e 'alarm shift; exec @ARGV' 5 /nope→ rc 0 vs rc 2 withor die;[ -x /bin ]true; notimeout/gtimeout;.mcp.jsonignored at.gitignore:12;ShellCheck 0.11.0 flags neither shell defect.
Docs updated in the same PR
docs/README.mdtask-signal map anddocs/guard-inventory.md(new row, summary counts, scope-limititem 6), per CLAUDE.md's docs-update rule.
Review-verdict: MERGEABLE @
1080e0bFive cold-review rounds (4 BLOCKED, round 5 MERGEABLE). Round 2 caught a ruff-format red that would have failed script-tests. Rounds 3-5 found only hand-maintained counts/uniqueness claims in prose, three created by the previous round's fix; that class was deleted rather than corrected again. Code was attacked exhaustively in rounds 3 and 4 with zero findings; declared mutation witnessed red and clause-scoped. Commits after the MERGEABLE verdict apply only that reviewer's own pre-merge recommendations (8 insertions, 8 deletions, all weakenings of claims). Gate: 1104 passed, ruff clean over 47 files, decisions-validate OK.