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

  • 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) sets attention=none, read_at=now, keeps lifecycle untouched, emits attention.cleared.
  • New signals re-raise attention (attention.created).
  • Desktop notifications are suppressed when the target pane is already focused; clicking one focuses workspace+tab+pane and clears.
  • "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