* 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>