Found while working #13800 (verdict handshake, PR #14960), which probed this file and left it untouched. Filed unassigned. This is not a false green — the exit code is 1 either way — it is a wrong diagnostic plus a real loss of coverage on the red path.
The shape
scripts/check-durability-degradation-log-level.mjs runs TWO batteries. Its dispatch says, verbatim:
if(args.includes('--self-test')){// Both rules' fixtures always run -- a red one must not hide the other.constlogLevelStatus=selfTest();if(!selfTestReachedVerdict){ ...exit1...}constreadSeamStatus=selfTestReadSeams();But selfTest() sets selfTestReachedVerdict = true only on its SUCCESS path; its failure path is console.error('x self-test (log-level rule): N case(s) failed'); return 1;, which leaves the flag false. So a genuine red trips the handshake guard.
Measured, not read
A mutated copy beside the original (the tracked file was never touched), forcing the first battery's failure branch and nothing else; mutation confirmed on disk before running:
EXIT: 1
did the SECOND battery (read-seam) run at all? false
x self-test (log-level rule): 0 case(s) failed
x check-durability-degradation-log-level self-test: selfTest() returned without reaching its verdict,
so no success line was printed. Exiting 0 here would report a self-test
that never finished as a self-test that passed.
Two defects in one reading:
- The message is false.
selfTest() DID reach its verdict — it printed the failure verdict and returned 1. A maintainer reading this hunts for a truncated run that did not happen. - The second battery never ran, which is exactly what the comment one line above says must not happen. Before the handshake landed, a red log-level rule still let the read-seam rule report; now it does not.
Why it is not fixed in #14960
The repair is a decision, not a transplant: either the flag is set on both exit paths (handshake means "ran to the end", pass or fail) and the returned status keeps carrying the verdict, or the two batteries each get a handshake that is checked after BOTH have run. Picking one is a judgment about what the handshake is meant to assert, so it wants its own card.
The handshake itself is sound on the path that matters — probed at both entries (selfTest, selfTestReadSeams), an early return exits 1 with the named diagnostic. Only the interaction with a genuine red is wrong.
Same landed shape ships in scripts/check-dispatcher-error-vocabulary.mjs, but it is NOT affected: there the failure path calls process.exit(1) inside the self-test, so the flag is never consulted.
Generated by Claude Code
Found while working #13800 (verdict handshake, PR #14960), which probed this file and left it untouched. Filed unassigned. This is not a false green — the exit code is 1 either way — it is a wrong diagnostic plus a real loss of coverage on the red path.
The shape
scripts/check-durability-degradation-log-level.mjsruns TWO batteries. Its dispatch says, verbatim:But
selfTest()setsselfTestReachedVerdict = trueonly on its SUCCESS path; its failure path isconsole.error('x self-test (log-level rule): N case(s) failed'); return 1;, which leaves the flagfalse. So a genuine red trips the handshake guard.Measured, not read
A mutated copy beside the original (the tracked file was never touched), forcing the first battery's failure branch and nothing else; mutation confirmed on disk before running:
Two defects in one reading:
selfTest()DID reach its verdict — it printed the failure verdict and returned 1. A maintainer reading this hunts for a truncated run that did not happen.Why it is not fixed in #14960
The repair is a decision, not a transplant: either the flag is set on both exit paths (handshake means "ran to the end", pass or fail) and the returned status keeps carrying the verdict, or the two batteries each get a handshake that is checked after BOTH have run. Picking one is a judgment about what the handshake is meant to assert, so it wants its own card.
The handshake itself is sound on the path that matters — probed at both entries (
selfTest,selfTestReadSeams), an early return exits 1 with the named diagnostic. Only the interaction with a genuine red is wrong.Same landed shape ships in
scripts/check-dispatcher-error-vocabulary.mjs, but it is NOT affected: there the failure path callsprocess.exit(1)inside the self-test, so the flag is never consulted.Generated by Claude Code