AGENTS.md@src/daemon · git:20260822.cf9f031 · 2026-08-22 · sha256 c4df417e49eab4ac

AGENTS.md@src/daemon git:20260822.cf9f031A

Immutable. This exact content is served forever at /api/v1/blob/c4df417e49eab4ac.

# Daemon design contract

These rules define the product architecture and runtime behavior for
`src/daemon`. `agent-driver/AGENTS.md` adds package-specific rules.

## Design from the product guarantee

- Never trade away a stronger user capability because a weaker state machine is
  easier to implement, own, clean up, or test. Define the user's minimum
  guarantee first; optimization and deduplication operate above that floor.
- Persistent execution is the default and preferred product model. If a backend
  supports a native persistent session, process, or transport, keep it
  persistent. Never replace it with per-turn execution for engineering
  convenience. A lifecycle downgrade requires an explicit product decision.
- A priority statement is not cancellation. Do not remove or rewrite a locked
  architecture, capability, module, or package boundary without an explicit
  decision to change that design.

## Architecture

- D1/server state owns durable messages and read state. The wake coordinator
  owns unread reminder coverage. The daemon manager owns logical-session and
  admission orchestration. The independent agent-driver package owns provider
  protocols, physical sessions, capabilities, and process lifecycles.
- A stored message is not proof of wake delivery. A WebSocket acknowledgement is
  not proof of session injection. A driver receipt is not proof of terminal
  cleanup. Keep these boundaries and authorities separate.
- Daemon code consumes declared contracts and capabilities. Provider names,
  wire events, SDK objects, and transport quirks stay inside adapters.
- In-memory state coordinates only the current daemon instance. Unread work must
  remain recoverable after disconnect, crash, restart, reset, model switch, or
  failed spawn.

## Wake is lossless

- Every unread must be covered by at least one effective wake injection. Wakes
  may merge from N to 1; they must never collapse from N to 0.
- Every accepted WebSocket wake that advances an unread watermark must reach the
  current logical session or remain reliably queued for it. This is required
  while the agent is active or admitting too; never acknowledge and suppress a
  new watermark into unowned memory.
- Coverage ends only when model-seen proves the agent actually observed that
  unread. `active`, `admitting`, persistence, transport send/ack, driver receipt,
  or a later incidental inbox pull do not satisfy this condition.
- A higher watermark arriving during active work enters the same persistent
  logical session. Its adapter may steer now, inject at a safe boundary, or
  queue the next turn, but delivery cannot wait for outbound alignment or
  shutdown.
- Deduplicate by stable semantic identity and covered watermark, not by the
  existence of an active turn. Preserve order; settle multi-channel coverage per
  channel; return every unseen watermark to idempotent FIFO retry after failure,
  idle, close, or epoch replacement.

## Session and turn authority

- Bind mutable authority to the exact session instance/epoch and root turn.
  Stale, duplicate, unknown, child, or superseded events cannot close, revive,
  delete, or settle the current owner.
- Only the matching root terminal ends root execution. Subagent completion is
  not root completion. Long-running root tools remain live work across silence;
  a queued-next-turn diagnostic must not hide that tool ownership.
- A queued command receipt preserves provisional responsibility; it does not
  complete the command. Acceptance settles it. Failure, close, or exit requeues
  it exactly once. True unacknowledged admissions and true inactive roots must
  still time out.
- Reset, stop, model switch, restart, and recovery preserve unread work and
  fence the old epoch. Old cleanup can affect only its captured instance and
  must never delete or terminate a replacement.
- A stop receipt, including `already_stopping`, is not terminal. The exact
  session's `closed` completion is authoritative only after logical and physical
  cleanup has finished.

## Capability and process ownership

- Busy delivery is capability-driven: immediate steer, safe-boundary injection,
  or next-turn queue. These modes change when an injection is consumed, never
  whether it is delivered. Do not fake unsupported steering or branch shared
  code on backend names.
- Every CLI, tool, and MCP server belongs to one agent-driver process authority.
  Before spawn, the daemon/host ensures the workspace and working directory
  exist; fresh start cannot depend on a previous run or adapter side effect.
- On POSIX, retain bounded authority over the exact root's captured descendant
  PIDs and descendant-owned process groups through TERM/KILL. Never global-scan
  or signal an unrelated group. On Windows, retain the Job Object boundary.
- Shutdown completes only after snapshotted sessions reach `closed` and every
  owned process is dead. Killing only the root, sending a signal, or exhausting
  a grace period is not successful cleanup; daemon exit must leave no orphan.

## Required behavioral proof

- Test the public chain: durable unread -> wake coverage -> session injection ->
  model-seen -> ordered handling. Isolated downstream tests cannot prove wake
  delivery.
- Cover persistent reuse, rapid-message N-to-1 delivery, message-during-work,
  failure/retry, partial observation, reset/replacement fencing, long root tools,
  root-vs-child terminal correlation, and clean shutdown.
- Process cleanup requires real operating-system trees, including detached
  descendants. Every built-in backend must pass the same user journeys with its
  declared capability and without loss, duplication, false terminal, or orphan.