You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #77 landed SessionRelationshipRecord with four relationshipTypes — root, continuation, fork, subagent — but no consumer surface yet aggregates across them. From the PR's deferred-work list:
Consumer CLI surface — burn summary --subagent-tree, burn diagnose, burn waste --patterns, burn summary --by-relationship. The execution graph is now persisted, so these can be built on top.
Issue #42 lists this as a query the substrate should enable:
burn summary --by-relationship
Examples of questions that become answerable: which sessions were forks vs continuations? how many spawned subagents never completed successfully?
Issue #109 explicitly punts on this surface in its Out-of-scope section:
New burn diagnose --execution-graph / burn summary --by-relationship surfaces — separate follow-up.
Today burn summary ships --by-subagent-type (PR #64), but only for the subagent relationship kind, and the aggregation is keyed off TurnRecord.subagent.subagentType rather than SessionRelationshipRecord. Continuations and forks are invisible to the summary surface.
Proposal
Add burn summary --by-relationship that aggregates the matched slice (respecting --since / --project / --workflow / --agent / --session) by relationshipType, joining SessionRelationshipRecord rows to TurnRecord cost data via (sessionId, agentId).
Per-row metrics.sessionCount, turnCount, totalCost, medianCost, p95Cost, meanCost — same shape as --by-subagent-type so the column set stays consistent.
Sub-grouping for subagent. Optional second-level breakdown by subagentType so the output subsumes today's --by-subagent-type view; toggleable with --by-relationship=subagent (or default to a flat subagent row with a footnote pointing at --by-subagent-type for the breakdown — implementation choice).
Joining. A turn belongs to a relationship row when its (sessionId, subagent.agentId) matches a SessionRelationshipRecord of that type. For root, that's any turn whose session has a root row and whose subagent.agentId is the session id (i.e. main-thread turns). For subagent, turns whose subagent.agentId matches a subagent row's agentId. For fork / continuation (once Claude reader: populate fork and continuation SessionRelationshipRecord rows #112 lands), turns belong to the relationship row keyed by the relationship's sessionId.
--json. Emits { relationships: Array<{ relationshipType, count, turnCount, totalCost, ... }> } so programmatic consumers can pipe the aggregation downstream.
Fallback. When relationships is empty for the matched slice (legacy ingest, no graph populated), exit with a one-line message — no SessionRelationshipRecord rows found for the matched slice; ingest a session with PR #77 wiring or run \burn rebuild` once that lands` — rather than silently zeroing.
Acceptance criteria
burn summary --by-relationship --since 7d produces a 4-row table (one per relationshipType present in the slice) with cost / turn aggregates rolled up per row.
--json output is a stable shape downstream consumers can pipe.
--by-relationship=subagent (or the equivalent sub-grouping flag) reproduces today's --by-subagent-type output, so the two surfaces can converge over time.
A slice with no relationship rows exits with a clear message (not a silent empty table).
New tests in packages/cli/src/commands/summary.test.ts cover: full 4-type slice, subagent-only slice, sub-grouping, the JSON shape, and the empty-slice message.
Context
PR #77 landed
SessionRelationshipRecordwith fourrelationshipTypes —root,continuation,fork,subagent— but no consumer surface yet aggregates across them. From the PR's deferred-work list:Issue #42 lists this as a query the substrate should enable:
Issue #109 explicitly punts on this surface in its Out-of-scope section:
Today
burn summaryships--by-subagent-type(PR #64), but only for thesubagentrelationship kind, and the aggregation is keyed offTurnRecord.subagent.subagentTyperather thanSessionRelationshipRecord. Continuations and forks are invisible to the summary surface.Proposal
Add
burn summary --by-relationshipthat aggregates the matched slice (respecting--since/--project/--workflow/--agent/--session) byrelationshipType, joiningSessionRelationshipRecordrows toTurnRecordcost data via(sessionId, agentId).relationshipType(root/continuation/fork/subagent).sessionCount,turnCount,totalCost,medianCost,p95Cost,meanCost— same shape as--by-subagent-typeso the column set stays consistent.subagent. Optional second-level breakdown bysubagentTypeso the output subsumes today's--by-subagent-typeview; toggleable with--by-relationship=subagent(or default to a flatsubagentrow with a footnote pointing at--by-subagent-typefor the breakdown — implementation choice).(sessionId, subagent.agentId)matches aSessionRelationshipRecordof that type. Forroot, that's any turn whose session has arootrow and whosesubagent.agentIdis the session id (i.e. main-thread turns). Forsubagent, turns whosesubagent.agentIdmatches asubagentrow'sagentId. Forfork/continuation(once Claude reader: populate fork and continuation SessionRelationshipRecord rows #112 lands), turns belong to the relationship row keyed by the relationship'ssessionId.--json. Emits{ relationships: Array<{ relationshipType, count, turnCount, totalCost, ... }> }so programmatic consumers can pipe the aggregation downstream.relationshipsis empty for the matched slice (legacy ingest, no graph populated), exit with a one-line message —no SessionRelationshipRecord rows found for the matched slice; ingest a session with PR #77 wiring or run \burn rebuild` once that lands` — rather than silently zeroing.Acceptance criteria
burn summary --by-relationship --since 7dproduces a 4-row table (one perrelationshipTypepresent in the slice) with cost / turn aggregates rolled up per row.subagentandrootrows) produces those two rows;fork/continuationrows appear when Claude reader: populate fork and continuation SessionRelationshipRecord rows #112 lands without further CLI changes.--jsonoutput is a stable shape downstream consumers can pipe.--by-relationship=subagent(or the equivalent sub-grouping flag) reproduces today's--by-subagent-typeoutput, so the two surfaces can converge over time.packages/cli/src/commands/summary.test.tscover: full 4-type slice, subagent-only slice, sub-grouping, the JSON shape, and the empty-slice message.Out of scope
TurnRecords or backfillingSessionRelationshipRecords for sessions ingested before Execution graph substrate: SessionRelationshipRecord + ToolResultEventRecord (#42) #77).fork/continuationpopulations — covered by Claude reader: populate fork and continuation SessionRelationshipRecord rows #112 (Claude) and the source-specific issues for Codex / OpenCode (Codex passive reader: populate SessionRelationshipRecord and ToolResultEventRecord #87 / OpenCode passive reader: populate SessionRelationshipRecord and ToolResultEventRecord #93).burn diagnoseper-session view of relationship metadata — covered by burn diagnose: surface execution-graph (relationships + tool-result chronology) #111.Refs
--subagent-tree), burn diagnose: surface execution-graph (relationships + tool-result chronology) #111 (burn diagnose), and burn waste --patterns: consume ToolResultEventRecord chronology (replace TurnRecord-only inference) #113 (burn waste --patterns).