Context
Burn's normalized TurnRecord is intentionally compact, but it is now too lossy for the backlog that depends on historical / passive ingest.
What is currently lost or flattened:
- session relationships beyond a flat
subagent.isSidechain
- parent / child session structure for forks, continuations, and subagents
- tool-result chronology and terminal status
- mapping from a tool call to the subagent session it spawned
- richer passive-reader evidence already present in logs from Claude, Codex, and OpenCode-style sources
This matters because several backlog items implicitly assume those facts exist:
#8 subagent tree wants parent -> child -> grandchild attribution
#11 waste-pattern detection wants retries, failure streaks, and compaction / failure context
#3 waste / attribution gets better if tool-result events exist, not just tool-call names
- archive work needs stable normalized tables for relationships and tool-result events
Agentsview's strongest parser lesson is that historical logs already carry much more structure than burn currently preserves. We should not make rich relationships depend only on hook path #7.
Goal
Define and preserve a normalized execution graph from passive readers.
This is not raw-content storage. It is structured metadata:
- how sessions relate to each other
- how tool calls and tool results unfold over time
- which tool call spawned which subagent session
- which events completed, errored, cancelled, or just streamed progress
Why #8 is not sufficient
#8 is about surfacing subagent trees from the current flat isSidechain model.
That is necessary, but it is still Claude-centric and mostly focused on the final tree view.
This issue is broader and lower-level:
- not just subagents, but forks and continuations
- not just final tree shape, but event chronology
- not just Claude, but passive readers across Claude / Codex / OpenCode / future collectors
Think of this as the normalized substrate that #8 and #11 should consume.
Proposed record types
Do not overload TurnRecord with every field. Add sibling normalized record types.
A. SessionRelationshipRecord
One row / event per discovered session relationship.
type RelationshipType = 'root' | 'continuation' | 'fork' | 'subagent';
interface SessionRelationshipRecord {
v: 1;
source: SourceKind;
sessionId: string;
relatedSessionId?: string;
relationshipType: RelationshipType;
ts?: string;
// provenance
sourceSessionId?: string;
sourceVersion?: string;
parentToolUseId?: string;
agentId?: string;
subagentType?: string;
description?: string;
}
B. ToolResultEventRecord
Canonical chronological tool-output / terminal-status events.
type ToolResultStatus = 'running' | 'completed' | 'errored' | 'cancelled' | 'unknown';
interface ToolResultEventRecord {
v: 1;
source: SourceKind;
sessionId: string;
messageId?: string;
toolUseId: string;
callIndex?: number;
eventIndex: number;
ts?: string;
status: ToolResultStatus;
eventSource: 'tool_result' | 'subagent_notification' | 'queue_event' | 'progress_event' | 'function_call_output';
contentLength?: number;
contentHash?: string;
isError?: boolean;
subagentSessionId?: string;
agentId?: string;
}
These records can live beside TurnRecord in the ledger or in the future derived archive. The key point is that they are normalized and append-only.
Source-specific expectations
Claude passive reader
Historical Claude logs already expose more than burn uses today.
Reader should preserve when available:
parentUuid chain information relevant to forks / continuations
- queue-operation / enqueue evidence mapping
tool_use_id -> task_id
- newer progress /
agent_progress evidence mapping parentToolUseID -> agentId
- source-session metadata when file session id and in-log session id differ
- compaction boundaries as distinct events rather than only inferred later
Codex passive reader
Reader should preserve:
function_call_output as tool-result events
spawn_agent / wait relationships to subagent ids
- terminal subagent notifications as chronological events attached to the originating tool call when possible
- result status transitions instead of only the final tool-call name list
OpenCode / future SQLite-backed readers
Reader should preserve:
- parent session ids / relationship metadata when available
- tool-result sizes and statuses where exposed
- chronology sufficient to rank failures and retries
Design constraints
- This issue is about metadata, not full content.
contentHash and contentLength are enough for most of the intended analyses.
- Hook-based ingest (
#7) may produce cleaner data, but passive readers must still populate the same normalized records where historical logs support it.
- The contract must be cross-source. Do not invent a Claude-only side structure.
Query surface this should enable
Not necessarily in this issue, but this is the substrate for:
burn summary --subagent-tree <session>
burn diagnose <session>
burn waste --patterns
burn summary --by-relationship
Examples of questions that become answerable:
- which subagent invocation cost the most?
- which sessions were forks vs continuations?
- which tool calls errored three times before succeeding?
- how many spawned subagents never completed successfully?
Acceptance
- Claude passive ingest can preserve fork / continuation / subagent relationships without relying on hook path
#7.
- Codex passive ingest can preserve
function_call_output and subagent terminal status as ToolResultEventRecords.
- The normalized execution graph is additive; existing
TurnRecord consumers keep working.
- The graph is rich enough that
#8 can consume it instead of reconstructing everything from isSidechain and parentUuid alone.
- The graph is rich enough that
#11 can compute failures / retries / subagent terminal outcomes without source-specific hacks.
Depends on
- none strictly, though archive work will want this normalized before locking schema
Unblocks
#8 subagent tree with real historical structure
#11 failure / retry / terminal-outcome analysis
- derived archive issue for stable relationship and event tables
- future search / analytics without needing hook-only data
Priority
High. This is the missing passive-reader substrate for several of burn's most interesting analyses.
Context
Burn's normalized
TurnRecordis intentionally compact, but it is now too lossy for the backlog that depends on historical / passive ingest.What is currently lost or flattened:
subagent.isSidechainThis matters because several backlog items implicitly assume those facts exist:
#8subagent tree wants parent -> child -> grandchild attribution#11waste-pattern detection wants retries, failure streaks, and compaction / failure context#3waste / attribution gets better if tool-result events exist, not just tool-call namesAgentsview's strongest parser lesson is that historical logs already carry much more structure than burn currently preserves. We should not make rich relationships depend only on hook path
#7.Goal
Define and preserve a normalized execution graph from passive readers.
This is not raw-content storage. It is structured metadata:
Why
#8is not sufficient#8is about surfacing subagent trees from the current flatisSidechainmodel.That is necessary, but it is still Claude-centric and mostly focused on the final tree view.
This issue is broader and lower-level:
Think of this as the normalized substrate that
#8and#11should consume.Proposed record types
Do not overload
TurnRecordwith every field. Add sibling normalized record types.A.
SessionRelationshipRecordOne row / event per discovered session relationship.
B.
ToolResultEventRecordCanonical chronological tool-output / terminal-status events.
These records can live beside
TurnRecordin the ledger or in the future derived archive. The key point is that they are normalized and append-only.Source-specific expectations
Claude passive reader
Historical Claude logs already expose more than burn uses today.
Reader should preserve when available:
parentUuidchain information relevant to forks / continuationstool_use_id -> task_idagent_progressevidence mappingparentToolUseID -> agentIdCodex passive reader
Reader should preserve:
function_call_outputas tool-result eventsspawn_agent/waitrelationships to subagent idsOpenCode / future SQLite-backed readers
Reader should preserve:
Design constraints
contentHashandcontentLengthare enough for most of the intended analyses.#7) may produce cleaner data, but passive readers must still populate the same normalized records where historical logs support it.Query surface this should enable
Not necessarily in this issue, but this is the substrate for:
Examples of questions that become answerable:
Acceptance
#7.function_call_outputand subagent terminal status asToolResultEventRecords.TurnRecordconsumers keep working.#8can consume it instead of reconstructing everything fromisSidechainandparentUuidalone.#11can compute failures / retries / subagent terminal outcomes without source-specific hacks.Depends on
Unblocks
#8subagent tree with real historical structure#11failure / retry / terminal-outcome analysisPriority
High. This is the missing passive-reader substrate for several of burn's most interesting analyses.