What is measured
$ sed -n 24p tools/gate.sh
LOGDIR="${TMPDIR:-/tmp}/pxx-gate-$$"
$ ls -d /tmp/pxx-gate-* | wc -l -> 78
$ du -shc /tmp/pxx-gate-* | tail -1 -> 5.3G
$ oldest -> 2026-09-10
No trap, no reaper, one directory per gate run, and gate.sh quick is
advertised as OPTIONAL PER FIX — so the rate scales with how well seats follow
the advice to gate often.
Why the obvious fix is wrong, and this is the whole point of the ticket
trap 'rm -rf "$LOGDIR"' EXIT is what CLAUDE.md's own cleanup guidance
suggests for exactly this shape ("if cleanup genuinely matters, it belongs in a
committed script with a trap ... EXIT"). Here it would break the tool.
- The summary is written INTO
$LOGDIRdeliberately —tools/gate.sh:27says so in its own comment, because "background the gate and grep the LOG for the verdict" is the instruction everywhere, the wrapper's exit code having lied three times in one day. - Every
FAILrow printslog: $LOGDIR/<step>.log. Readingpinned-rtl-canary.logis how tonight's red was diagnosed. - The failure direction is silent and delayed. A trap reaps green runs first, where nobody wants the logs, so it looks correct for as long as it is not needed. The first time it matters is a RED whose per-step log is already gone — and that reader has no way to know the log ever existed.
What it probably wants instead
An age-based reap (delete pxx-gate-* older than N hours at gate START,
not at exit) or keep-on-red (reap only when every row passed). Both are
design calls with trade-offs — how long is long enough to diagnose, and does a
green run's log ever get read — which is why this is filed rather than fixed.
/etc/tmpfiles.d/tmp.conf is at 6h, so plexus already reaps these eventually;
the accrual above says it is not keeping up, and seven's /tmp is a tmpfs
where the binding limit is INODES and not bytes.
The trap caveat is frankZ's, who reached for the trap first and caught it.
What reaping does NOT fix, and quietly makes harder to notice
frankZ, 2026-09-11, and it cuts against this ticket's own fix. Reading
another session's gate dir is an established practice and an established
mistake: L=$(ls -td /tmp/pxx-gate-* | head -1); cat "$L/summary.log" is in
debugging-playbook.md:12418 under "The two wrong ways, both of which look
careful", measured 2026-09-05 with three gates running, where ls -td returned
a different session's directory.
Reaping shrinks the population of stale dirs, so ls -td | head -1 returns
the caller's own dir more often. The known-broken method therefore becomes
more reliable, which means it gets CERTIFIED more often and corrected less —
the passing-arrangement failure the fixture clause in CLAUDE.md describes,
arriving through a cleanup change nobody would connect to it.
This is not an argument against reaping. It is a statement that must be in the
ticket so no later reader takes "we reaped the dirs" as having addressed the
ls -td hazard. It does not. The two are independent and the reap makes the
second one quieter.
Why age-based-at-start rather than keep-on-red
Keep-on-red has to read the verdict that lives inside the directory it is judging, and be right about it. Invert that test once and it deletes exactly the reds — a reaper whose failure mode is losing the only evidence anyone needed. Age-based never reads a verdict: it needs a clock, and it degrades to "you waited too long" rather than to "the evidence is gone".
At START, never at exit, so a run can never delete its own output.
Plus one syscall to remove the clock coupling (frankZ): a purely
time-keyed reap can delete a CONCURRENTLY RUNNING gate's directory if the
threshold is ever tuned below a long run's duration — a full gate is not a
30-second quick one, and whoever tunes it later will not be thinking about that.
The directory name IS the pid, so kill -0 "${dir##*-}" skips any live producer
and removes the coupling rather than relying on the threshold staying generous.
Checking this ticket's own claims
grep -n 'trap' tools/gate.sh returns a hit — line 89, matching bootstrap
inside a comment. So the fast check of "is there a trap" answers YES and the
truth is NO. The word-boundary form is honest:
grep -nE '(^|[^a-z])trap[[:space:]]' tools/gate.sh returns nothing.