Found while classifying scripts/audits/14744-before-update-per-row-value-census.mjs for #13799 batch 10a (the census row the PM asked for). Filed unassigned. Sibling of #14842 and #14963 — same instrument, a third and different root cause — and adjacent to #14968, which asks for a handshake reading the instrument does not take.
The mechanism
probeEarlyReturn() in scripts/measure-self-test-floor.mjs decides its verdict on the mutated run's exit code and nothing else:
verdict: mut.status === 0 ? 'DEFEATED' : 'HELD',
There is a guard above it for a mutation that changed nothing observable (same output AND same status is NOT MEASURED), but no requirement that the mutated run SAY anything. So any file whose early-returned run happens to exit non-zero scores HELD — including one that carries no verdict handshake at all.
The measured instance
scripts/audits/14744-before-update-per-row-value-census.mjs (landed by #15301, 655 lines) carries none of the three handshake spellings #14968 tallies: zero SELF_TEST_VERDICT, zero selfTestReachedVerdict, zero requireReachedVerdict. Its dispatch is:
if (process.argv.includes('--self-test')) {
process.exit(runSelfTest() === 0 ? 0 : 1);
}
An early return makes runSelfTest() yield undefined; undefined === 0 is false; the process exits 1 printing nothing. The instrument's own row records exactly that and still calls it HELD (measured on 103677652, node scripts/measure-self-test-floor.mjs --probe --json, exit 0):
{"file":"scripts/audits/14744-before-update-per-row-value-census.mjs","floor":"NONE","defs":["runSelfTest"],
"probe":{"verdict":"HELD","entry":"runSelfTest","baselineExit":0,"mutatedExit":1,"mutatedBytes":0,"mutatedHead":""}}
mutatedBytes 0 and an empty mutatedHead are the tell, and they are already in the row — the verdict just does not read them. Compare the same run's scripts/check-osv-exemptions.mjs: mutatedBytes 206, mutatedHead naming the handshake by name. Both are HELD.
Why it matters
This is precisely the accident-versus-handshake distinction #14842 drew by hand for one file (selfTest mutated to a TypeError stack: "an accident, not a handshake. A row naming this entry would record a hold this file does not have"). Here the instrument makes that mistake on its own, with no ambiguous entry to blame — so a green --probe sweep is not evidence that the files in it have handshakes, and #13798's completion picture cannot be read off it.
Options
Recommendation: A, with C as the separate repair #14968 already asks for. A costs one condition over a field the instrument already records, it turns a wrong answer into an honest one, and it does not commit the instrument to knowing any spelling. B is the same coupling #14968 is filed to remove.
Scope note
The audits file is ALSO unfloored (floor: NONE) and is 10a's classification target; its census row goes to #13799. Nothing here asks for it to be floored — this card is about the instrument's verdict, not about that file.
Duplicate-checked before filing against 284 open issues from the repo-scoped issues list plus a local grep (control terms returned the known family #14842 / #14963 / #14968 / #15296 / #15317, confirming a live read); no existing card for this criterion.
Generated by Claude Code
Found while classifying
scripts/audits/14744-before-update-per-row-value-census.mjsfor #13799 batch 10a (the census row the PM asked for). Filed unassigned. Sibling of #14842 and #14963 — same instrument, a third and different root cause — and adjacent to #14968, which asks for a handshake reading the instrument does not take.The mechanism
probeEarlyReturn()inscripts/measure-self-test-floor.mjsdecides its verdict on the mutated run's exit code and nothing else:There is a guard above it for a mutation that changed nothing observable (same output AND same status is NOT MEASURED), but no requirement that the mutated run SAY anything. So any file whose early-returned run happens to exit non-zero scores HELD — including one that carries no verdict handshake at all.
The measured instance
scripts/audits/14744-before-update-per-row-value-census.mjs(landed by #15301, 655 lines) carries none of the three handshake spellings #14968 tallies: zeroSELF_TEST_VERDICT, zeroselfTestReachedVerdict, zerorequireReachedVerdict. Its dispatch is:An early return makes
runSelfTest()yieldundefined;undefined === 0is false; the process exits 1 printing nothing. The instrument's own row records exactly that and still calls it HELD (measured on103677652,node scripts/measure-self-test-floor.mjs --probe --json, exit 0):{"file":"scripts/audits/14744-before-update-per-row-value-census.mjs","floor":"NONE","defs":["runSelfTest"], "probe":{"verdict":"HELD","entry":"runSelfTest","baselineExit":0,"mutatedExit":1,"mutatedBytes":0,"mutatedHead":""}}mutatedBytes0 and an emptymutatedHeadare the tell, and they are already in the row — the verdict just does not read them. Compare the same run'sscripts/check-osv-exemptions.mjs:mutatedBytes206,mutatedHeadnaming the handshake by name. Both are HELD.Why it matters
This is precisely the accident-versus-handshake distinction #14842 drew by hand for one file (
selfTestmutated to a TypeError stack: "an accident, not a handshake. A row naming this entry would record a hold this file does not have"). Here the instrument makes that mistake on its own, with no ambiguous entry to blame — so a green--probesweep is not evidence that the files in it have handshakes, and #13798's completion picture cannot be read off it.Options
HELDonly whenmutatedExit !== 0ANDmutatedBytes > 0; the exit-1-silent case becomes a third verdict (SILENT REFUSAL/NOT A HANDSHAKE). Cheap, mechanical, and reads a field the row already carries. Cost: files that legitimately refuse silently — if any exist — move out of HELD and need reading.Recommendation: A, with C as the separate repair #14968 already asks for. A costs one condition over a field the instrument already records, it turns a wrong answer into an honest one, and it does not commit the instrument to knowing any spelling. B is the same coupling #14968 is filed to remove.
Scope note
The audits file is ALSO unfloored (
floor: NONE) and is 10a's classification target; its census row goes to #13799. Nothing here asks for it to be floored — this card is about the instrument's verdict, not about that file.Duplicate-checked before filing against 284 open issues from the repo-scoped issues list plus a local grep (control terms returned the known family #14842 / #14963 / #14968 / #15296 / #15317, confirming a live read); no existing card for this criterion.
Generated by Claude Code