mirror of
https://github.com/stablyai/orca.git
synced 2026-09-24 00:02:24 +00:00
* fix(agent-status): a structured session with live child work reads as working An idle native-chat session whose subagent was still running showed a green check in the sidebar, the collapsed worktree pill, and worktree ps, while a terminal Claude session in the same situation showed working. The two lanes folded child work into the parent's status with different code: the hook listener did, the structured lane did not. Both lanes now share one child-work liveness vocabulary and one lead-status fold. Live agent work makes a settled lead working; shells and monitors alone make it monitoring. The structured lane derives liveness from the background task list already on the wire, in both its readers, so the sidebar, the CLI, the dashboard and mobile agree. The Claude task-kind table is one shared file covering both the hook inventory and SDK stream names, and the renderer bridge reuses the shared child-work projection instead of carrying its own copy. * fix(agent-status): a blocked or out-of-contact subagent still holds its session working Child-work liveness retired an agent-kind child on any state but working/monitoring, while the shell beside it stayed live on everything except done/idle. A subagent waiting on a permission prompt, or one whose host lost contact, therefore counted for less than a backgrounded sleep and let the session read done. Both kinds now share the settlement rule `resolveAgentChildWorkFreshness` already reads rows by: only an explicit done/idle retires child work. Also keep empty task labels out of the shared background-task projection candidate, so a host that publishes `name: ''` cannot beat the child-row fallbacks. * test(agent-status): pin the widened hook-inventory agent names, and correct two stale claims The hook inventory now classifies through the shared kind table, which also maps the SDK stream's `local_agent` / `local_subagent`. Nothing pinned that widening, so add cases for all four agent names — including `teammate`, whose pane state stays `done` under the #8825 idle-squat rule. Two comments the fold made false: - the teardown marker rule's comment claimed it could not disagree with what the UI calls working; it is deliberately lead-only, so now it says that and why; - the agent-status store reference still described the structured row's `state` as the deleted `structuredAgentSessionStatusState`, and omitted the `workingMode` the ingest now writes. * fix(agent-status): the state clock restarts when monitoring becomes a real turn `stateStartedAt` carried forward whenever the prior `state` matched, which was sound while `state` meant "a turn is running". Now that it folds in child work, an idle lead watching a `sleep 3600` publishes `working`/`monitoring`; the user's prompt 45 minutes later keeps `state: 'working'`, so the row inherited the watch loop's clock and read "Working for 45m" the instant the turn began. Monitoring is its own displayed label (`worktree-card-compact-agent-row.tsx:40`), so the continuity key is now the whole published work identity — state AND workingMode — in both writers. Also record two facts the code stated wrongly: the structured lane's `interrupted: false` is inert (a projected session status has no interrupted member) rather than a decision, and the child-work liveness rule's escape hatch is the roster's session lifetime, not a settled state. * fix(agent-status): a workflow is watch work, and child work dates itself Two defects the fold introduced. `isAgentChildWorkKind` counted `workflow` as agent work, so a structured session whose only live task was a backgrounded `local_workflow` published a full working spinner while the children projection — which admits `kind === 'agent'` only — rendered nothing to expand, and the same workflow in a terminal pane showed the monitoring badge instead. The repo already decides this: `isClaudeSubagentTask` excludes workflows by name, and MATERIALIZED_TASK_KINDS leaves "the backgrounded shell command and the workflow" to the non-agent owner. The predicate is now `kind === 'agent'`, and the three sites that restated the same test route through it, so a new kind is decided in one place instead of three that merely agree. `evidenceObservedAt` dated every row by `summary.updatedAt`, the journal's last activity. The journal cannot date child work: its clock stopped when the lead's turn did, so a genuinely live roster aged past the 30-minute staleness window and mobile's dot decayed a running session to idle. The fold now reports whether child work alone holds the row open, and only then does the host's observation clock stand in — keeping "a restart's republish is not new evidence" for lead turns. * fix(agent-status): the sidebar dates child work the same way the host does `fromChildWork` reached the host ingest but not the renderer bridge, so after ~30 minutes of live child work with no journal activity the sidebar's row aged into staleness while `worktree ps` and mobile stayed fresh — two writers for one session answering differently, which is the defect this PR exists to remove. For a remote host the client's own receipt time is also the more honest clock, since the journal stamp is the host's and is never comparable against this machine's now.