Layer-2 defense-in-depth follow-up to the Windows PPID watchdog fix (#711).
That fix makes an orphaned proxy exit so its socket closes and the daemon
reaps via the refcount + idle timer. This adds two daemon-side safety nets for
the residual case where a socket close is never delivered (a Windows named-pipe
hazard) and a phantom client would otherwise pin the daemon forever:
- Liveness sweep: a proxy now sends an optional client-hello carrying its pid
(+ host pid) right after verifying the daemon hello; the daemon periodically
drops any client whose peer process is dead, re-arming the idle timer.
Fail-safe and version-pinned — a connection that never sends the hello just
falls back to the socket-close lifecycle, and the daemon reads it before the
transport so a non-hello first line is handed through untouched.
- Inactivity backstop: the daemon exits after a generous no-traffic window
(CODEGRAPH_DAEMON_MAX_IDLE_MS, default 30 min) even with clients attached, so
a phantom client that sends nothing can't keep it alive.
Pure helpers (parseClientHelloLine, peerIsDead) are unit-tested; the full
handshake + sweep and the backstop are covered end-to-end in mcp-daemon.test.ts.
Validated on a real Windows 11 VM: the sweep reaps a dead-pid client over a
named pipe and the backstop fires with a client still connected.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>