bun test runs every file in ONE process, so a 500ms setTimeout(process.exit(0))
armed in afterAll fired mid-way through a LATER file and killed the entire
suite with exit 0 and no summary — only ~16 of 434 files ran, and every
downstream failure was invisible (observed live throughout this wave's
enumeration). Changes, all guarded by fault injection:
- Replace every delayed-exit teardown with a time-boxed close of the file's
own browser (8 files across browse/ and design/); stub the daemon
/shutdown timer instead of letting its unconditional process.exit tear
the runner down.
- test/no-suicide-exit.test.ts: static tripwire — no *.test.ts may schedule
a delayed process.exit again.
- test/exit-propagation.test.ts + fixtures: fault injection with REAL bun
output proves the truncation shape (exit 0, no summary) and that
scripts/test-free-shards.ts now detects it: a shard exiting 0 WITHOUT
bun's final summary line is treated as FAILED (exit code alone is not
evidence of completion).
- handoff: the three headed-mode integration tests are darwin-skipped with
a pointer to the known macOS headed-launch breakage (#2242/#2554); they
keep running on Linux CI. Un-skip in the browse-daemon wave.
- feedback-roundtrip: repair the handler call sites unmasked by the fix —
handlers take (command, args, session, bm); passing the manager where a
session belongs broke all six tests.
- user-slug-fallback: HOME isolation makes endpoint_hash deterministic.
Fixes#2421, #2435.
Contributed by @sneakygriff (PR #2172) with repairs from @time-attack
(PR #2230 feedback-roundtrip hunks); supersedes PR #2252 by @whd4 (same
defect, credited).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>