docs(agent): note deliberate double transcript parse in subagent scan · Entire

docs(agent): note deliberate double transcript parse in subagent scan

1771c5c→main·

suhaanthayyil·4d ago·2 files·+29 added/-0 removed

CalculateTotalTokenUsage and ExtractAllModifiedFiles (Claude Code and Factory AI Droid) parse the transcript twice per call: the sliced window plus a full-transcript scan to find subagents spawned before the window (#329). Record why the redundant full parse is kept: ParseFromBytes drops malformed lines so a parsed-entry index does not map to a raw line number, making a safe single-pass split require threading raw-line numbers through the shared parser, and a Task-marker line scan would duplicate the nested tool_result decoding. The common no-subagent case already avoids the cost via the subagentsDir == "" short-circuit.

Changes

2

402 unmodified lines

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
69 unmodified lines

490
491
492
493
494
495
496
497
498
499

402 unmodified lines

// sliced portion. A subagent spawned before this checkpoint's startLine can
    // keep writing to its transcript in later turns; scanning only the slice
    // would miss it and undercount subagent token usage (#329).
    //
    // PERF (considered, retained deliberately): this re-parses the full
    // transcript in addition to the sliced parse above — two JSONL parses per
    // call, growing with session length. A single-pass version was rejected as
    // not worth the risk: ParseFromBytes silently drops malformed lines, so a
    // parsed-entry index does not correspond to a raw line number and naively
    // slicing the full parse at startLine would misattribute main-agent usage;
    // doing it safely would mean threading raw-line numbers through the shared
    // transcript parser used by every agent. A cheap line scan for the Task
    // marker instead of a full parse would duplicate ExtractSpawnedAgentIDs'
    // nested tool_result decoding. The common no-subagent case already avoids
    // this cost entirely via the subagentsDir == "" short-circuit above.
    fullParsed, err := transcript.ParseFromBytes(transcriptData)
    if err != nil {
        return nil, fmt.Errorf("failed to parse full transcript: %w", err)
    }
69 unmodified lines

// spawned before this checkpoint's startLine may keep modifying files in
    // later turns, and scanning only the slice would miss it (#329). Main-agent
    // file extraction above stays scoped to the slice.
    //
    // PERF: the second full-transcript parse is retained deliberately for the
    // same reasons documented on CalculateTotalTokenUsage above; the common
    // no-subagent case is short-circuited by the subagentsDir == "" guard.
    fullParsed, err := transcript.ParseFromBytes(transcriptData)
    if err != nil {
        return nil, fmt.Errorf("failed to parse full transcript: %w", err)
    }

Mcmd/entire/cli/agent/claudecode/transcript.go+16

372 unmodified lines

373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
58 unmodified lines

446
447
448
449
450
451
452
453
454
455

372 unmodified lines

// Extract spawned agent IDs from the FULL transcript (startLine=0): a
    // subagent spawned before this checkpoint's startLine can keep writing to
    // its transcript, so scanning only the slice would undercount it (#329).
    //
    // PERF (considered, retained deliberately): this re-parses the full
    // transcript in addition to the sliced parse above — two JSONL parses per
    // call, growing with session length. A single-pass version was rejected:
    // the Droid parser drops non-message / malformed lines, so a parsed-entry
    // index does not map to a raw line number and naively slicing the full parse
    // at startLine would misattribute main-agent usage; doing it safely would
    // mean threading raw-line numbers through the shared parser. The common
    // no-subagent case already avoids this via the subagentsDir == "" guard.
    fullParsed, _, err := ParseDroidTranscriptFromBytes(data, 0)
    if err != nil {
        return nil, fmt.Errorf("failed to parse full transcript: %w", err)
    }
58 unmodified lines

// spawned before this checkpoint's startLine may keep modifying files in
    // later turns, and scanning only the slice would miss it (#329). Main-agent
    // file extraction above stays scoped to the slice.
    //
    // PERF: the second full-transcript parse is retained deliberately for the
    // same reasons documented on CalculateTotalTokenUsageFromBytes above; the
    // common no-subagent case is short-circuited by the subagentsDir == "" guard.
    fullParsed, _, err := ParseDroidTranscriptFromBytes(data, 0)
    if err != nil {
        return nil, fmt.Errorf("failed to parse full transcript: %w", err)
    }

Mcmd/entire/cli/agent/factoryaidroid/transcript.go+13