docs/03-lifecycle-attention.md

03 — Lifecycle & Attention Models

Lifecycle (what the agent is doing) and attention (whether the human must look) are independent axes. Both are first-class in the data model, IPC, and UI.

Agent lifecycle

text
1unknown → working ⇄ blocked → done
2 │ │ │ │
3 │ ▼ ▼ ▼
4 │ failed failed (terminal)
5 ▼
6 idle ⇄ working
7 │
8 └── exited (process gone; orthogonal to task outcome)
StateMeaningTypical sources
unknownno adapter signal yetnew pane, generic shell
workingagent is making progresshooks (PreToolUse), process running, spinner/title
blockedwaiting on human (input/permission)hooks (PermissionRequest), OSC notify, idle+prompt heuristics
doneturn/task completedhooks (Stop), notify hook, exit 0 of one-shot
idlealive, nothing runninghooks (SessionStart before prompt), prompt-readline state
failederrorednon-zero exit, error hook payload
exitedPTY child gonewaitpid/pipe EOF (keeps last lifecycle as last_lifecycle)

Transitions are adapter-driven; explicit events always override heuristics. Every transition emits agent.<state> with the previous value and the source.

Attention

StateMeaningUI treatment
nonenothing to seeneutral
unreadoutput/activity since last seensubtle dot
input_requiredagent asked a questionattention ring
permission_requiredapproval gate openstrong ring
warningnon-fatal problemamber indicator
errorfailure needs triagered indicator

Severity order: error > permission_required > input_required > warning > unread > none. A pane shows its highest outstanding item.

Canonical examples

Situationlifecycleattention
agent mid-turnworkingnone (subtle activity only)
agent asks questionblockedinput_required
approval dialog openblockedpermission_required
turn finished, not yet seendoneunread
turn finished, user revieweddonenone
tool error, agent retryingworkingwarning
agent crashedfailederror
plain shell, new outputidleunread

Clearing rules

  • Ordinary attention clears only on explicit user interaction with that pane: focusing it, marking read, or replying. Visibility of the workspace/tab is not enough.
  • mark_seen(pane) records last_seen_at=now and keeps lifecycle untouched. It clears ordinary attention and emits attention.cleared. An unanswered decision and its required attention survive reading, focusing, notification clicks, and default attach. An answer or agent transition resolves the decision. See ADR-0012.
  • New signals re-raise attention (attention.created).
  • A trailing terminal signal is not a new signal. Once a done/failed pane is reviewed (attention=none, no pending decision), a session-end hook (Claude/Codex SessionEnd, Cursor sessionEnd) and the PTY exit leave it with its terminal lifecycle and attention none; its useful last message stays. A session-end hook on any done/failed pane never rewrites the outcome (failed stays failed). A first completion (working/idle → session end or exit) and a new turn (UserPromptSubmit then Stop) still raise unread. Session end retains existing gate behavior; process exit still clears pending decisions and demotes required attention to unread. Spec: 024.
  • Desktop notifications are suppressed when the target pane is already focused; clicking one focuses workspace+tab+pane and acknowledges reading.
  • "Jump to next unread" walks panes ordered by severity then recency.

Sidebar summary (per workspace)

Each sidebar row derives from its panes, never from telemetry:

  • name, repo/branch, agent kinds present
  • worst lifecycle (blocked > failed > working > done > idle)
  • worst attention (severity order above)
  • latest explicit message (notification/hook summary, not scraped text)
  • time since last attention change