Commit Graph
1 Commits
Author SHA1 Message Date
Brennan BensonandBrennan Benson 31cff75a7b feat(agent-status): show Claude subagent child rows and gate premature done (#8211)
* feat(agent-status): show Claude subagent child rows and gate premature done

A Claude pane that spawned background subagents/teammates showed a green
done check the moment the lead's turn ended, even while a background
review loop was still running. Orca now tracks the pane's live children
from Claude hook events and:

- keeps the pane 'working' while at least one child is working (Stop is
  gated; Claude wakes the lead when a child finishes, so the pane
  resolves to done on the follow-up Stop with an empty roster)
- renders the children as indented child rows under the pane's sidebar
  row (name/type + working/idle dot), reusing the existing lineage UI

Tracking is lifecycle-primary: SubagentStart/SubagentStop/TeammateIdle
(newly registered hooks) plus child-origin tool events (they carry
agent_id) own the roster. Stop's background_tasks is folded only where
unambiguous — verified live on Claude Code 2.1.207 that teammates report
status "running" while idle-alive and their task ids never match
lifecycle agent_ids, so the list cannot decide teammate working-ness.

Child-origin events no longer overwrite the lead's tool/prompt caches
(a live AskUserQuestion card survives child churn); a child's own
PermissionRequest records waitingAgentId so only that child's progress
or death clears the wait. The interrupted flag survives the gated
window, inferred interrupts sync the lead record and refuse while a
child works, and hydration reseeds the roster after a restart.

* fix(agent-status): drop identity icon on subagent child rows

The child's agentType carries its NAME (e.g. "pr-reviewer"), which is not
an iconable agent and rendered the unknown "?" glyph. Nesting under the
parent row already conveys identity.

* fix(agent-status): restore displaced lead state and reconcile phantom subagents

Four review findings from the adversarial pass on the subagent child-row
feature:

- Stash the lead state a child-induced wait displaces
  (ClaudeLeadTurnState.stateBeforeWait) and restore it when the wait
  clears, instead of inventing 'working' — a lead that had already
  stopped left the pane spinning forever after the roster drained,
  since the done-gate only ever downgrades done → working.
- Tag snapshot-seeded and background_tasks-recreated roster entries
  (backgroundTasksAuthoritative) and demote them when a PRESENT
  background_tasks list omits their id. A phantom child seeded before a
  restart could otherwise gate the pane 'working' indefinitely in teams
  sessions, whose task list is never empty. Live activity clears the
  tag so lifecycle-tracked teammates keep their state.
- Match teammate ids with a hyphen-free suffix after `a<name>-` so
  TeammateIdle for "lane" cannot idle "lane-hooks"'s rows or clear its
  pending permission wait.
- Route turn-boundary events (Stop/StopFailure/UserPromptSubmit) that
  carry a KNOWN child agent_id through the child-driven re-emit instead
  of adopting them as lead state, and tie the prompt-cache new-turn
  reset to lead-origin events so child refreshes can't blank the
  prompt label.

---------

Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
2026-07-10 23:34:49 -07:00