feat(orchestration-v2): add subagent observability data model (1/5) - #4768
Conversation
Introduces the schema, storage, and migration for richer subagent tracking. Nothing produces the new data yet — adapters populate neutral defaults so every subagent row remains valid — which keeps this change reviewable as a pure data-model step. Contracts gain a reusable subagent identity: per-activation records (SubagentActivationId, OrchestrationV2SubagentActivation), cumulative usage, a role, recent activity, and workflow grouping. A subagent may now also rest at "idle" between activations. Because a subagent status is not a turn item status, the two are bridged by an explicit mapping rather than a copy. The Record type makes that total: adding a subagent status without giving it a timeline meaning is a compile error. Without it, a producer can emit a turn item whose own schema cannot decode it, which is unrecoverable — the projection rebuild then fails on every subsequent startup and the server cannot boot. Migration 043 backfills existing rows so old events stay readable. Its riskiest path is a partially-migrated row, where already-present JSON is round-tripped through COALESCE; a test pins that structured values keep their JSON subtype rather than being rewritten as quoted strings. Also narrows event-envelope attribution in ProviderEventIngestor: a payload carrying an explicit null run or node id now keeps that null instead of inheriting the ambient run. Activations legitimately have no run id, and the envelope is persistence metadata only — routing reads payload fields — but this does change stored metadata for existing event types that already pass explicit nulls.
|
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 |
|
Not actually merged by review — a mistaken push put this branch's commits directly onto |
First of five stacked PRs replacing #4551, which bundled the whole subagent-observability feature into one ~3,100-line change. Splitting it out so each piece can actually be reviewed; the seams between these pieces are where the bugs were hiding.
Scope: data model, storage, and migration only. Nothing produces the new data yet. Adapters are given neutral defaults so every subagent row stays valid. Populating them for real is 2/5, and reuse semantics are 3/5.
What's here
Contracts gain a reusable subagent identity — per-activation records (
SubagentActivationId,OrchestrationV2SubagentActivation), cumulative usage, a role, recent activity, and workflow grouping. A subagent can also now rest atidlebetween activations.Migration 043 backfills existing rows so old events stay readable.
The status mapping is the important part
A subagent status is not a turn item status —
idlehas no timeline equivalent. The two are bridged by an explicitRecord<subagent status, turn item status>rather than a copy, which makes the mapping total: adding a subagent status without giving it a timeline meaning is a compile error.This is not hypothetical. An earlier iteration copied the raw status through, which wrote a
turn-item.updatedevent that its own schema could not decode. Nothing failed at write time — but the projection rebuild runs at startup and died on that stored event, so the server became permanently unbootable with no in-app recovery. Addingidlein this PR immediately trips the new compile error atCodexAdapterV2.ts, which is the guard doing its job.Notes for review
ProviderEventIngestorno longer replaces an explicit nullrunId/nodeIdwith the ambient run. Activations legitimately have no run id. The envelope is persistence metadata only (routing reads payload fields), but this does change stored metadata for existing event types that already pass explicit nulls.COALESCE. A test pins that structured values keep their JSON subtype rather than being rewritten as quoted strings.idle. Only relevant if that build ran anywhere beyond local dev.Testing
Typecheck clean and lint clean across server, contracts, client-runtime, and web.
Also booted a server on a fresh state directory and confirmed migration 043 applies and the app starts.
Reviewed by an independent agent pass before opening; its findings on helper scope and the missing mixed-row migration test are folded in.
Note
Medium Risk
Touches event-sourced projections, a new migration with JSON backfill, and envelope attribution semantics; mistakes could corrupt stored events or startup rebuilds, though tests target the risky migration and status-mapping paths.
Overview
Introduces the orchestration v2 subagent observability contracts and persistence layer ahead of adapter/UI work. Subagents gain reusable identity fields (
kind,role,usage,activationCount,workflow,recentActivity, etc.), a new restingidlestatus, and separateOrchestrationV2SubagentActivationrecords with asubagent-activation.updateddomain event and SQLite projection table (schema version 3).Migration 043 backfills legacy subagent JSON and creates activation storage; tests cover partial backfills and projection rebuild cleanup of stale activation rows.
Provider adapters and the orchestrator only wire neutral defaults and minimal lifecycle hooks (e.g. delegated-task spawn/terminal activation events); real population is deferred. Codex now maps subagent status to turn-item status via
orchestrationV2SubagentStatusAsTurnItemStatussoidlecannot be written raw onto timeline rows.ProviderEventIngestor stops substituting ambient
runId/nodeIdwhen the payload explicitly passesnull, so detached activations and messages keep correct envelope metadata.Reviewed by Cursor Bugbot for commit 877ef38. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add subagent observability data model with activation tracking to orchestration-v2
OrchestrationV2SubagentActivationas a new schema and domain event type (subagent-activation.updated), tracked per subagent by ordinal with status, usage, and timestamps.OrchestrationV2Subagentwith new fields:kind,role,usage,currentActivationId,activationCount,workflow,workflowMembership, andrecentActivity, all with decoding defaults for backward compatibility.orchestration_v2_projection_subagent_activationstable and backfills missing fields in existing subagent payload rows.subagent-activation.updatedevents when delegated subagent tasks start and reach terminal status; all provider adapters (Claude, Codex, ACP, Cursor, OpenCode) populate the new fields on subagent nodes.subagentActivationson the thread projection.orchestrationV2SubagentStatusAsTurnItemStatusmaps the newidlestatus tocompleted; Codex adapter now routes subagent turn item statuses through this mapping rather than passing them directly.Macroscope summarized 12b0111.