ADR 0001 - Tray quit owns the daemon
- Status: Accepted
- Date: 2026-08-19
- Scope: desktop process ownership
Context
Section titled “Context”The desktop app can own its local daemon or attach to a daemon owned elsewhere. Window lifetime and daemon lifetime are separate, so closing a window must not interrupt reviews or streams.
Decision
Section titled “Decision”The tray’s Quit action is the only desktop action that stops a daemon:
- It stops only the owned daemon: the process claimed by
daemon.jsonin the app data directory, regardless of whether the app or CLI spawned it. The graceful path — the same onerennet stoptakes — asks the daemon to shut down over its own wire (POST /shutdown), records in-flight turns asinterrupted, and clears the claim before the app exits. SIGTERM and then SIGKILL are bounded fallbacks for a daemon that will not answer. - The claim is health-verified before any command.
daemon.jsonis a claim to verify, never proof: Quit probes/healthzand commands only a PID whose identity and port the probe confirmed. A stale claim for a dead or unrelated process is removed without sending anything, so tray Quit cannot take down someone else’s process. - It waits for the process to be gone, not merely for a pid probe to fail: the
spawned child’s own
exitwhen this instance spawned the daemon, and otherwise the claim clearing plus a pid that is not in a running state. An exited-but-unreaped process is gone; it holds no port and no app bundle. - It exits even if the daemon does not confirm death within the bounded ladder, recording what it actually found in the log. The next launch verifies the claim again.
- Window close still stops nothing. Closing the last window keeps the shell tray-resident; the daemon and every stream are untouched. Only the explicit Quit tears down.
- An attached remote daemon is never signalled. A daemon running on another host belongs to that host.
Consequences
Section titled “Consequences”- There is one desktop teardown path. Background work survives window close.
- The Quit label reads “Quit Rennet and stop daemon” only when an owned local daemon is running, “Quit Rennet” otherwise.
- The action runs directly without a confirmation prompt.