a73x

bd03a5c7

fix(test): a wedged daemon fails leakcheck loudly; the sweep pins its own input

a73x   2026-08-14 08:57

Commit message
fix(test): a wedged daemon fails leakcheck loudly; the sweep pins its own input

leakcheck's poll could expire with the pid still alive and then grep a log
whose verdict was never written — reading nothing, finding nothing, and
returning 0. That swallowed two failures at once: the unreadable verdict,
and the `muxd stop` that had not killed anything. An expired poll now says
so through the file's own `why` channel.

The e2e sweep's `grep "$OUT".*` silently reads nothing if the captures ever
stop surviving to the end, so the gate no longer rests on that unstated
invariant: d1.d, written at daemon-one spawn and kept until the trap, is
asserted present before the sweep greps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

test/agent.sh
Old New
@@ -210,6 +210,11 @@ leakcheck() {
210 sleep 0.05 210 sleep 0.05
211 _i=$((_i + 1)) 211 _i=$((_i + 1))
212 done 212 done
213 # An expired poll is not a clean answer: the verdict is written on the way
214 # out, so a daemon still alive here has written nothing and the grep below
215 # would read a stale log and call it healthy — swallowing both the
216 # unreadable verdict AND the `muxd stop` that failed to kill anything.
217 kill -0 "$1" 2>/dev/null && { why "daemon still alive ${_i}x50ms after stop — leak verdict unreadable"; return 1; }
213 _dl="$XDG_STATE_HOME/mux/muxd.log" 218 _dl="$XDG_STATE_HOME/mux/muxd.log"
214 [ -f "$_dl" ] || return 0 219 [ -f "$_dl" ] || return 0
215 grep -q "LEAK:" "$_dl" || return 0 220 grep -q "LEAK:" "$_dl" || return 0
test/e2e.sh
Old New
@@ -3090,6 +3090,10 @@ ok "hub narrates the tear; the replica re-attaches across an epoch"
3090 kill "$DPID" 2>/dev/null || true 3090 kill "$DPID" 2>/dev/null || true
3091 wait "$DPID" 2>/dev/null || true 3091 wait "$DPID" 2>/dev/null || true
3092 DPID="" 3092 DPID=""
3093 # The sweep must have something to read: d1.d is created at daemon-one
3094 # spawn and survives to the trap, so its absence means the capture
3095 # convention broke and this gate is reading nothing.
3096 [ -e "$OUT.d1.d" ] || { echo "e2e FAIL: leak sweep found no captures to read"; exit 1; }
3093 # Every capture this suite wrote — daemon stderr AND client output — is a 3097 # Every capture this suite wrote — daemon stderr AND client output — is a
3094 # lifecycle log now: any binary that leaked printed a grep-able marker. 3098 # lifecycle log now: any binary that leaked printed a grep-able marker.
3095 if grep -q "LEAK:" "$OUT".* 2>/dev/null; then 3099 if grep -q "LEAK:" "$OUT".* 2>/dev/null; then