End-to-end tests in browse/test/watchdog.test.ts that prove the three
invariants v0.18.1.0 depends on. Each test spawns the real server.ts
(not a mock), so any future change that breaks the watchdog logic fails
here — the thing /ship's adversarial review flagged as missing.
1. BROWSE_PARENT_PID=0 disables the watchdog
Spawns server with PID=0, reads stdout, confirms the
"watchdog disabled (BROWSE_PARENT_PID=0)" log line appears and
"Parent process ... exited" does NOT. ~2s.
2. BROWSE_HEADED=1 disables the watchdog (server-side guard)
Spawns server with BROWSE_HEADED=1 and a bogus parent PID (999999).
Proves BROWSE_HEADED takes precedence over a present PID — if the
server-side defense-in-depth regresses, the watchdog would try to
poll 999999 and fire on the "dead parent." ~2s.
3. Default headless mode: watchdog fires when parent dies
The regression guard for the original orphan-prevention behavior.
Spawns a real `sleep 60` parent and a server watching its PID, then
kills the parent and waits up to 25s for the server to exit. The
watchdog polls every 15s so first tick is 0-15s after death, plus
shutdown() cleanup. ~18s.
Total runtime: ~21s for all 3 tests. They catch the class of bug this
branch exists to fix: "does the process live or die when it should?"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>