Skip to content

feat(orchestration-v2): populate subagent observability from providers (2/5) - #4629

Open
shivamhwp wants to merge 4 commits into
subagent-obs/01-contractsfrom
subagent-obs/02-adapters
Open

feat(orchestration-v2): populate subagent observability from providers (2/5)#4629
shivamhwp wants to merge 4 commits into
subagent-obs/01-contractsfrom
subagent-obs/02-adapters

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

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 idle rather than completed. 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:

  • A raced resume silently lost its tokens. When a resume arrives past settle, the wake buffer pre-opens the registry entry — which erased the terminal status the reopen check reads. The resume then reused the finished activation instead of starting a new one: its ordinal stopped matching reality, and its usage was measured against the previous activation's totals, clamping the delta to zero. 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.
  • Duplicate terminal frames re-stamped 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_continue fixture. 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/desktop collection 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

  • Each provider adapter now emits subagent_activation.updated events alongside subagent.updated, carrying activation id, ordinal, status, usage, and timestamps for each discrete subagent run.
  • Adds SubagentObservability helpers: providerSubagentRole, appendSubagentActivity, mergeCumulativeSubagentUsage, and accumulateCumulativeSubagentUsage for normalizing and accumulating usage across activations.
  • Subagent tasks now track currentActivationId (nulled on settle), activationCount, recentActivity, and preserve completedAt across rebuild emits.
  • The Claude adapter gains full workflow coordinator/worker modeling: worker subagents are created under a coordinator with phase membership, parent linkage, per-attempt reopen semantics, and are settled when the coordinator terminalizes.
  • Codex adapter maps completed provider state to idle subagent status; all adapters align on idle as the terminal reusable state instead of completed.
  • Behavioral Change: subagent status for settled reusable agents is now idle (not completed); 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 (idle vs completed); Claude resume/workflow logic is intricate but heavily tested.

Overview
Provider adapters (ACP, Claude, Codex, Cursor, OpenCode) now emit subagent_activation.updated alongside subagent updates and fill roles, usage, recent activity, and activation metadata instead of neutral defaults.

SubagentObservability adds 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 (not completed); activations still record terminal status. currentActivationId, activationCount, and preserved completedAt on 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, waiting reopen 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 for idle and activation rows.

Reviewed by Cursor Bugbot for commit 2038f11. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 41ca544d-dcf6-4c8b-a001-f29b8fa09bfd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch subagent-obs/02-adapters

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Jul 27, 2026
@shivamhwp
shivamhwp force-pushed the subagent-obs/02-adapters branch from 9296337 to 760a4c2 Compare July 27, 2026 23:03
@shivamhwp
shivamhwp force-pushed the subagent-obs/01-contracts branch from 877ef38 to 12b0111 Compare July 28, 2026 15:31
@shivamhwp
shivamhwp force-pushed the subagent-obs/02-adapters branch from 760a4c2 to f3666e9 Compare July 28, 2026 15:31
Base automatically changed from subagent-obs/01-contracts to t3code/codex-turn-mapping July 28, 2026 19:27
@shivamhwp
shivamhwp force-pushed the subagent-obs/02-adapters branch from f3666e9 to 2565ea0 Compare July 28, 2026 19:27
@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Jul 28, 2026
@shivamhwp
shivamhwp force-pushed the t3code/codex-turn-mapping branch from 313ae4d to f117a4a Compare July 28, 2026 20:12
@shivamhwp
shivamhwp changed the base branch from t3code/codex-turn-mapping to subagent-obs/01-contracts July 28, 2026 20:12
@shivamhwp
shivamhwp force-pushed the subagent-obs/02-adapters branch 2 times, most recently from 2567faf to dcd0319 Compare July 30, 2026 00:00
@shivamhwp
shivamhwp force-pushed the subagent-obs/01-contracts branch from f4037f3 to e4f6d13 Compare July 30, 2026 00:00
Comment thread apps/server/src/orchestration-v2/testkit/fixtures/claude_workflow/output.ts Outdated
shivamhwp and others added 2 commits July 30, 2026 06:14
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>
@shivamhwp
shivamhwp force-pushed the subagent-obs/02-adapters branch from dcd0319 to bad75ab Compare July 30, 2026 00:45
Comment thread apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts
@macroscopeapp

macroscopeapp Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: 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 2038f11. Prior analysis still applies.

You can customize Macroscope's approvability policy. Learn more.

T3 Code Test and others added 2 commits July 31, 2026 04:45
- 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>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2038f11. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant