# ADR — daemon-idle-exit-002

### ADR-002: Respawn in client_for(None) reverses the MCP no-auto-start non-goal  [status: accepted]

- **Context:** `daemon_for_tool()` documents "Per the spec's Non-goals: do NOT auto-start the daemon from MCP" (`src/adapters/mcp/tools.rs:268`), and `ensure_daemon_running` fires exactly once at `serve` startup (`src/app/cli.rs:287-290`). With idle-exit (ADR-001), a mid-session exit would turn every subsequent MCP tool call into a JSON-RPC `-32603` "daemon unavailable" error and strand CLI users the same way (`client.rs:49-51`).
- **Decision:** `client_for(None)` invokes `ensure_daemon_running()` once on connect failure, then retries the connect; a second failure returns today's loud error. This heals MCP and CLI (`ground`, `index`) at one seam — all three non-test callers route through `client_for`. Explicit-socket callers (`client_for(Some(path))`), `lifecycle::status`, and `lifecycle::stop` keep calling `connect_at` and never spawn — `stop` must not resurrect what it stopped; the `HALLOUMINATE_SOCKET` override still no-ops the spawn for test harnesses (`bootstrap.rs:38-40`).
- **Alternatives:** MCP-only respawn in `daemon_for_tool` (rejected: CLI regresses — eviction kept the daemon alive for CLI; idle-exit would not); no respawn, honoring the non-goal (rejected: breaks every long-lived agent session, ruling out default-on idle-exit).
- **Consequences:** Version-skew self-heal rides free — `ensure_daemon_running` stops a version-mismatched daemon and respawns (`bootstrap.rs:43-61`), now reachable from the client hot path. The spawn machinery (flock race, 200ms poll, 30s timeout) moves onto that hot path; it is already production-tested by every `serve` startup. No automatic retry of a request that dies mid-call — respawn applies to connect only.
