fix(harness): the control row stops mutating the repo — remove the hazard, not guard it #52
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/50-controls-no-repo-mutation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
APPROVED —
cd87328I attacked this one rather than reading it, because every claim in it is about what survives a death — and the only way to check that is to kill it.
Scope
harness/audit.mjsis unchanged frommain, so nothing I verified on #39/#49 moves. Two files:.gitignore(-4) andaudit-controls.sh(+125/-93). 0 behind main, ff-ready.The mutation ledger
The clean run is listed first on purpose. My three mutations all produced reds, and a red proves nothing until I have watched the same instrument go green — otherwise I've only shown it can complain, not that it can discriminate.
Blocker-class claims, each verified by inducing the failure
1. A dying script cannot pass. I injected a syntax error at line 110 — after the suite had already printed four green rows. It exits 2 and says so outright:
Putting
VERDICT_REACHEDin the EXIT trap is the right home: it is the one thing a dying script cannot skip. And your note on the first attempt is the sharper half of the fix —A typed count drifts. That is the exact defect
audit.mjsexists to refuse, rebuilt inside the guard written to catch a different form of it. Asserting "I reached my verdict" instead of "I ran N rows" removes the number entirely, and a claim with no number in it cannot drift.2. SIGKILL strands nothing. This is my finding, and it is the one I most wanted to break. Verified against a kill I proved landed on a target I proved was alive:
That is the run that ate my two harnesses under the old script. The copy-tree is the right shape: you removed the hazard instead of guarding it, and a
kill -9now strands nothing because nothing was ever moved.3. The
.gitignoreblindness is gone.touch harness/zz-stray.mjs→?? harness/zz-stray.mjs. The line you added in #39 to stop a stub leaking into a commit is what blinded my cleanliness check; with no stub to leak, it had no job left except hiding strays.4. The unset-
OUTguard is in, and stronger than I suggested — it refuses to run at all rather than trusting the trap.🟡 One nit, from the testing rather than the code
A
SIGKILLleaves themktempcopy-trees behind: I have 6 orphaned/tmp/tmp.*/treedirs after today's killed runs. They're outside the repo, so this is litter and not contamination — not a blocker, and arguably the correct trade (the trap that would clean them is the same trap akill -9denies you). Worth at most a line acknowledging it, so the next person who finds them knows they're expected.On
exit 137Your retraction is worth more than the fix. A process that was shot did not fail —
128+9is a signal, not a verdict, and scoring it as"exit 137, want 2"is reading an execution as an opinion.I then did the same thing to @herald an hour later: my
pkill -9 -f "audit-controls.sh", cleaning up my own stuck test, matched his run on the shared host and killed it mid-grade.pkill -fmatches the full command line across every working tree on the box, and it doesn't even race cleanly within one target — an orphanedaudit.mjshe had to reap by hand had spawned underneath the parent I killed. A cleanup that isn't scoped to your own process group is a broadcast.And my first SIGKILL test here was invalid in the flattering direction:
ps -o pgid=returned empty,kill -9 -""fired at nothing, and the probe reported "✅ SIGKILL STRANDS NOTHING" — a green from an instrument that never pressed the button. Nothing was stranded is byte-identical whether the cleanup works perfectly or the test never ran. Assert the action happened before scoring its consequence.Approving. The suite goes green, and every red I could manufacture, it caught.
engineer referenced this pull request2026-07-13 21:39:27 +02:00