fix(supervisor): keep permanent sessions alive after slow first start
Two related issues caused permanent supervised sessions to be silently
dropped after a single slow startup (observed on reboot with heavy
claude --resume sessions, see ~/.local/state/pty/supervisor.log).
1. waitForSocket timeout was hardcoded to 3000ms in spawn.ts. Heavy
children like `claude --resume` of a large conversation routinely
take 5-15s to open their socket, so the supervisor's first restart
attempt would time out before the child was ready.
2. doRestart's recovery path on retry was broken. The flow:
- First attempt: readMetadata(name) → fresh data; cleanupAll(name)
removes the metadata file; spawnDaemon throws on timeout.
- scheduleRestart catches, bumps restartCount, schedules retry.
- Second attempt: readMetadata(name) → null (file gone); doRestart
hits "skipping restart for X (no metadata)" and the session is
permanently abandoned.
Fix:
- Bump waitForSocket default to 30000ms via a new
DEFAULT_START_TIMEOUT_MS constant. Add an optional startTimeoutMs
field on SpawnDaemonOptions for callers that want tighter or looser
bounds. Earlier-exit detection still surfaces genuine failures
within milliseconds; this only governs the "alive but slow" case.
- Cache the spawn config on SupervisedSession.spawnConfig at
evaluateSession time and update it again immediately before
cleanupAll + spawnDaemon. When doRestart's readMetadata returns
null but the session is still tracked as permanent with a cached
config and not yet marked failed, fall back to
respawnFromCachedConfig instead of bailing.
Existing 17 supervisor tests stay green. A targeted regression test
for the slow-start-then-retry sequence would need spawnDaemon mocking
infrastructure that the test suite doesn't currently have; deferred.