feat(orchestration-v2): populate subagent observability from providers (2/5) - #4629
feat(orchestration-v2): populate subagent observability from providers (2/5)#4629shivamhwp wants to merge 4 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9296337 to
760a4c2
Compare
877ef38 to
12b0111
Compare
760a4c2 to
f3666e9
Compare
f3666e9 to
2565ea0
Compare
313ae4d to
f117a4a
Compare
2567faf to
dcd0319
Compare
f4037f3 to
e4f6d13
Compare
Fills in the data model added by the previous PR. Every adapter now reports what its subagents are actually doing: role provenance, token usage, recent activity, and per-activation records. Usage needs two merge strategies because providers report it differently. Codex sends cumulative snapshots per thread, so those merge by maximum — duplicate and late out-of-order frames then leave the total unchanged instead of inflating it. Claude reports per activation, so lifetime usage accumulates only the delta since the previous snapshot. A subagent identity is reusable, so completing an activation leaves it at "idle" rather than "completed"; the timeline row for that activation is still recorded as completed via the status mapping. A Codex subAgentActivity frame carries no model of its own, so agents registered from one were recorded with none at all — the common case for Codex-native subagents, which then showed a role and a token count but no model. They are recorded against the turn's model selection, which is what they actually run on. Three activation-lifecycle fixes in the Claude adapter, found in review: - A resume that raced past settle was pre-opened by the wake buffer, which erased the terminal status the reopen check reads. The resume then reused the finished activation instead of starting a new one, so its ordinal stopped matching reality and its usage was measured against the previous activation's totals — clamping the delta to zero and silently dropping the resumed run's tokens. The pre-open now records that it happened, and the reopen check honours it. - A replayed "waiting" frame could resurrect a settled subagent; only pending/running were guarded before. - A duplicate terminal frame re-stamped completedAt, drifting the recorded completion time. Codex already preserved it; Claude now matches. Reuse across runs is deliberately not addressed here — a subagent row still carries the run it was spawned under. That is the next PR.
The adapter's workflow projection was covered in isolation and the panel derivation was covered against synthetic agents, but nothing drove real workflow frames through the orchestrator to the projection the client receives. Adds a claude_workflow replay fixture: a local_workflow task with two phases and two members, asserted on the resulting projection. Pins what the panel groups by — that members claim declared phases, that their membership points at the coordinator that actually reached the projection, and that the coordinator's usage still covers its members so subtracting theirs cannot go negative. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dcd0319 to
bad75ab
Compare
ApprovabilityVerdict: Needs human review 1 blocking correctness issue found. This PR introduces new subagent observability features across multiple provider adapters, including new event emission, status tracking, and usage accumulation logic. The scope represents significant new runtime behavior, and there is an unresolved review comment identifying a potential bug in the waiting status handling. No code changes detected at You can customize Macroscope's approvability policy. Learn more. |
- Treat pending/waiting workflow agents as active in the session-registry write guard and wake-buffer pre-open, so concurrent active transitions are not dropped and wake task_started cannot force a false resume. - Preserve the first-recorded activation completion time on duplicate terminal frames (Claude in-place update and ACP rebuilt emits). - Let a blocked/waiting first snapshot of a new attempt reopen a settled workflow agent entry instead of silently dropping its status and usage. - Settle still-active workflow members when their coordinator terminalizes, and expect the Implementer completed in claude_workflow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2038f11. Configure here.
| activeContext.subagentActivation === null | ||
| ) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Late usage skips activation records
Medium Severity
thread/tokenUsage/updated only writes per-activation usage when the turn is still in activeTurns. Turn finalization removes that entry first, so a late usage frame updates lifetime totals but leaves the activation's usage unset.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 2038f11. Configure here.


Second of five stacked PRs replacing #4551. Stacked on #4779 — review that first; this diff is against it, not the base branch.
PR 1 added the schema, migration, and storage with adapters on neutral defaults. This one makes the adapters actually populate it, across Codex, Claude, Cursor, OpenCode and ACP: role provenance, token usage, recent activity, and per-activation records.
Two usage strategies, because providers differ
Codex reports cumulative usage per thread, so those snapshots merge by maximum — a duplicate or late out-of-order frame then leaves the total unchanged rather than inflating it. Claude reports per activation, so lifetime usage accumulates the delta since the previous snapshot. Using either strategy for the other provider double-counts or freezes the number, so they are separate functions with their own tests.
A subagent identity is reusable, so finishing an activation leaves it at
idlerather thancompleted. The timeline row for that activation is still recorded as completed, via PR 1's status mapping.Three activation-lifecycle bugs found in review
All in the Claude adapter, all fixed here:
waitingframe could resurrect a settled subagent. Onlypending/runningwere guarded.completedAt, drifting the recorded completion time. Codex already preserved it; Claude now matches.Explicitly not here
Reuse across runs. A subagent row still carries the run it was spawned under, so a later run's update can still be dropped by routing — visible in the
subagent_continuefixture. That is PR 3, deliberately kept separate because it is the subtle part.Testing
Typecheck and lint clean. Server 1,682 passing; whole-repo run 5,460 passing (the only failures are pre-existing
apps/desktopcollection errors from a broken local Electron install, untouched by this PR).Reviewed by an independent agent pass before opening; the three lifecycle bugs above came out of it and are fixed in this commit.
Note
Populate subagent observability from ACP, Claude, Codex, Cursor, and OpenCode provider adapters
subagent_activation.updatedevents alongsidesubagent.updated, carrying activation id, ordinal, status, usage, and timestamps for each discrete subagent run.SubagentObservabilityhelpers:providerSubagentRole,appendSubagentActivity,mergeCumulativeSubagentUsage, andaccumulateCumulativeSubagentUsagefor normalizing and accumulating usage across activations.currentActivationId(nulled on settle),activationCount,recentActivity, and preservecompletedAtacross rebuild emits.completedprovider state toidlesubagent status; all adapters align onidleas the terminal reusable state instead ofcompleted.idle(notcompleted); existing tests and fixtures have been updated to match.Macroscope summarized 2038f11.
Note
Medium Risk
Touches orchestration projection for all major provider adapters and changes settled subagent status semantics (
idlevscompleted); Claude resume/workflow logic is intricate but heavily tested.Overview
Provider adapters (ACP, Claude, Codex, Cursor, OpenCode) now emit
subagent_activation.updatedalongside subagent updates and fill roles, usage, recent activity, and activation metadata instead of neutral defaults.SubagentObservabilityadds provider role provenance, bounded activity history, and two usage paths: Codex merges cumulative thread snapshots by maximum; Claude accumulates per-activation deltas into lifetime totals.Settled reusable subagents end in
idle(notcompleted); activations still record terminal status.currentActivationId,activationCount, and preservedcompletedAton rebuild emits align across adapters.Claude models workflow coordinators and workers from
workflow_progress, settles workers when the coordinator terminalizes, and fixes resume/reopen races (resumePending,waitingreopen guards).Codex maps collab agent states via
codexCollabAgentStatus, handles token usage and thread status, and records subagent model from the turn selection. Fixtures and tests updated foridleand activation rows.Reviewed by Cursor Bugbot for commit 2038f11. Bugbot is set up for automated code reviews on this repo. Configure here.