Problem
Claude Code writes each subagent's transcript to its own file under <project>/<session-uuid>/subagents/agent-*.jsonl. Every entry in those files carries isSidechain: true.
codeburn optimize counts each of these as a session. On my machine that is a 3.3x inflation of the session count, and it feeds two of the five High-severity findings, both of which subagents fail by construction rather than by waste.
Note up front: subagent token spend is real and should keep counting toward cost totals. The problem is treating a sidechain transcript as a session for the session-level detectors.
Evidence
codeburn 0.9.20 (npm), Claude Code 2.1.228, Linux (WSL2).
Transcript files modified in the last 30 days:
$ cd ~/.claude/projects
$ find . -name '*.jsonl' -mtime -30 | wc -l
266
$ find . -name 'agent-*.jsonl' -mtime -30 | wc -l
188
$ find . -name '*.jsonl' -mtime -30 ! -name 'agent-*' | wc -l
78
Reported session counts over that window:
| Source |
Sessions |
codeburn optimize (default --period 30days) |
257 |
Claude Code /insights |
66 analyzed (76 total) |
real (non-agent-*) transcript files |
78 |
257 tracks the 266 total files. 66/76 tracks the 78 real sessions.
Every entry in a sampled subagent file is flagged:
$ # ./-home-adam-Code-claude-memory-mcp/51d23210-.../subagents/agent-a104705e05a4bebdc.jsonl
entries: 291 isSidechain value counts: {True: 291}
Impact on findings
Finding "N context-heavy sessions". Its own examples are subagents:
-home-adam-Code-job-agent/agent-ad163f3e75953e7eb 7.1M input/cache vs 87.7K output (80.6:1)
-home-adam-Code-claude-memory-mcp/agent-a769c824627f199aa 3.4M input/cache vs 55.5K output (60.6:1)
A subagent is given a large context and returns a short answer. A high input:output ratio is its correct behavior, not context bloat. Flagging it inverts the signal.
Finding "N possibly low-worth expensive sessions". The delivery test in the shipped bundle is:
DELIVERY_COMMAND_PATTERNS = [
/(?:^|[;&|]\s*)git\s+(?:commit|push)(?=\s|$|--)(?![^;&|]*--dry-run)/,
/(?:^|[;&|]\s*)gh\s+pr\s+(?:create|merge)(?=\s|$|--)(?![^;&|]*--dry-run)/
]
Subagents do not commit or open PRs; the parent session does. So every subagent is an unsatisfiable candidate. 70 sessions were flagged for me against 78 real sessions.
This is the same detector class as #664 (founding/bootstrap sessions flagged as waste) misfiring on a different population.
The signal is already parsed
isSidechain is captured at session level. From the bundle's own comment:
// rich-session-capture-v1: parse-time capture of per-turn gitBranch, per-call
// LOC deltas / interruptions / userModified / toolErrors, and session-level
// title / prLinks / isSidechain.
The session-meta validator also carries isSidechain, agentType, and parentSessionId, and emptySessionMeta() initialises { prLinks: [], isSidechain: false, agentSpawnLinks: {}, ambiguousSpawnAgentIds: [] }.
There is also an entry-level skip in the parser:
if (entry.isSidechain === true) continue;
Given that every entry in these files is isSidechain: true, that filter would empty them out — so the path feeding optimize's session list evidently does not apply it. The flag is honoured in one parse path and ignored in the one that produces the session population for the detectors.
Suggested direction
Listing options rather than assuming a preference:
- Exclude sessions with session-level
isSidechain === true from findLowWorthCandidates and the context-heavy detector, while leaving their cost in the totals.
- Attribute subagent cost and tokens to
parentSessionId so a parent session is judged on the full work it dispatched — this would also make the low-worth delivery test meaningful, since the parent is what commits.
- If subagents stay in the session list, report them in a separate bucket with their own thresholds, since a 60:1 input:output ratio is normal for a sidechain.
Option 2 seems the most faithful, but 1 is a much smaller change and removes the false positives on its own.
Related
Problem
Claude Code writes each subagent's transcript to its own file under
<project>/<session-uuid>/subagents/agent-*.jsonl. Every entry in those files carriesisSidechain: true.codeburn optimizecounts each of these as a session. On my machine that is a 3.3x inflation of the session count, and it feeds two of the five High-severity findings, both of which subagents fail by construction rather than by waste.Note up front: subagent token spend is real and should keep counting toward cost totals. The problem is treating a sidechain transcript as a session for the session-level detectors.
Evidence
codeburn 0.9.20 (npm), Claude Code 2.1.228, Linux (WSL2).
Transcript files modified in the last 30 days:
Reported session counts over that window:
codeburn optimize(default--period 30days)/insightsagent-*) transcript files257 tracks the 266 total files. 66/76 tracks the 78 real sessions.
Every entry in a sampled subagent file is flagged:
Impact on findings
Finding "N context-heavy sessions". Its own examples are subagents:
A subagent is given a large context and returns a short answer. A high input:output ratio is its correct behavior, not context bloat. Flagging it inverts the signal.
Finding "N possibly low-worth expensive sessions". The delivery test in the shipped bundle is:
Subagents do not commit or open PRs; the parent session does. So every subagent is an unsatisfiable candidate. 70 sessions were flagged for me against 78 real sessions.
This is the same detector class as #664 (founding/bootstrap sessions flagged as waste) misfiring on a different population.
The signal is already parsed
isSidechainis captured at session level. From the bundle's own comment:The session-meta validator also carries
isSidechain,agentType, andparentSessionId, andemptySessionMeta()initialises{ prLinks: [], isSidechain: false, agentSpawnLinks: {}, ambiguousSpawnAgentIds: [] }.There is also an entry-level skip in the parser:
Given that every entry in these files is
isSidechain: true, that filter would empty them out — so the path feedingoptimize's session list evidently does not apply it. The flag is honoured in one parse path and ignored in the one that produces the session population for the detectors.Suggested direction
Listing options rather than assuming a preference:
isSidechain === truefromfindLowWorthCandidatesand the context-heavy detector, while leaving their cost in the totals.parentSessionIdso a parent session is judged on the full work it dispatched — this would also make the low-worth delivery test meaningful, since the parent is what commits.Option 2 seems the most faithful, but 1 is a much smaller change and removes the false positives on its own.
Related