Skip to content

fix: subagent file modifications invisible to checkpoint detection (ENT-297)#323

Open
khaong wants to merge 11 commits intomainfrom
alex/ent-297-fix-subagent-only-changes-checkpointing
Open

fix: subagent file modifications invisible to checkpoint detection (ENT-297)#323
khaong wants to merge 11 commits intomainfrom
alex/ent-297-fix-subagent-only-changes-checkpointing

Conversation

@khaong
Copy link
Contributor

@khaong khaong commented Feb 13, 2026

Summary

Fixes subagent file modifications being invisible to checkpoint detection. When Claude Code delegates work to subagents via the Task tool, file changes made by those subagents were not tracked, causing:

  • Missing checkpoints at Stop (subagent-only changes → totalChanges=0)
  • Missing checkpoint trailers on mid-session commits
  • Incomplete file lists in condensed checkpoint metadata
  • Failed PostCommit condensation for mid-subagent commits (transcript data unavailable)

Changes

  • ExtractAllModifiedFiles() — new function that scans both main and subagent transcripts (agent-<id>.jsonl) for Write/Edit/NotebookEdit tool calls
  • Stop hook — uses ExtractAllModifiedFiles so checkpoints aren't skipped when only subagents modify files
  • sessionHasNewContentFromLiveTranscript — augmented with subagent transcript scanning for mid-session commit detection
  • Shared helper extractModifiedFilesFromLiveTranscript — consolidates 3 duplicated code blocks (main transcript extraction + subagent augmentation + path normalization)
  • extractSessionDataFromLiveTranscript — uses shared helper so condensed checkpoints include subagent files
  • PostCommit ACTIVE sessions — trusts PrepareCommitMsg's trailer validation instead of re-analyzing transcripts (unreliable when subagents are still running at commit time)
  • Removed sessionHasNewContentInCommittedFiles — now unused after the PostCommit simplification

Key insight

At PostCommit time during a mid-subagent commit, subagent transcript data is unavailable: the main transcript has no tool_result with agentId: yet, and subagent files may still be in-flight. Since PrepareCommitMsg already validates the trailer (unconditionally for no-TTY/agent commits, via content detection for TTY/human commits), PostCommit trusts that decision for ACTIVE sessions rather than re-validating.

Fixes ENT-297

Test plan

  • Unit tests for ExtractAllModifiedFiles (4 cases: includes subagent files, deduplicates, no subagents, subagent-only changes)
  • Unit test for sessionHasNewContentFromLiveTranscript with subagent-only modifications
  • Unit test for PostCommit ACTIVE session always condensing
  • Integration test TestHookRunner_SimulateStop_SubagentOnlyChanges (both strategies)
  • Manual test: subagent commit → trailer added → checkpoint created
  • Full CI suite passes (mise run fmt && mise run lint && mise run test:ci)

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings February 13, 2026 12:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes ENT-297 by ensuring checkpoint detection includes file modifications performed by Claude Code subagents (spawned via the Task tool), so turns aren’t skipped when only subagents write/edit files.

Changes:

  • Added claudecode.ExtractAllModifiedFiles() to aggregate modified files across main + subagent transcripts.
  • Updated Claude Code stop hook (commitWithMetadata) and mid-session “new content” detection to include subagent transcripts.
  • Added unit and integration tests to cover subagent-only modification scenarios.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
cmd/entire/cli/agent/claudecode/transcript.go Adds ExtractAllModifiedFiles() to collect modified files from main + subagent transcripts.
cmd/entire/cli/hooks_claudecode_handlers.go Stop hook now uses ExtractAllModifiedFiles() for subagent-aware modified-file detection.
cmd/entire/cli/strategy/manual_commit_hooks.go Mid-session commit detection now checks subagent transcripts for Claude Code sessions.
cmd/entire/cli/agent/claudecode/transcript_test.go Adds unit tests for ExtractAllModifiedFiles() (subagent inclusion + dedupe cases).
cmd/entire/cli/strategy/mid_turn_commit_test.go Adds test ensuring subagent-only changes are detected as “new content.”
cmd/entire/cli/integration_test/hooks_test.go Adds integration regression test for stop-hook checkpointing when only subagents modify files.
cmd/entire/cli/strategy/registry.go Updates //nolint:ireturn rationale comment.
cmd/entire/cli/strategy/manual_commit.go Updates //nolint:ireturn rationale comment.
cmd/entire/cli/strategy/auto_commit.go Updates //nolint:ireturn rationale comment.

@khaong khaong force-pushed the alex/ent-297-fix-subagent-only-changes-checkpointing branch from 2d26295 to 97fb2a9 Compare February 15, 2026 03:32
@khaong khaong changed the base branch from main to soph/one-to-one-checkpoints February 15, 2026 03:33
khaong and others added 8 commits February 15, 2026 17:22
…gents

This function extracts modified file paths from both the main transcript and
any subagent transcripts spawned via the Task tool. It follows the same pattern
as CalculateTotalTokenUsage: parse once, extract agent IDs, read subagent
transcripts, and merge results with deduplication. This is the foundation for
fixing ENT-297 where subagent-only file changes were invisible to checkpointing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 732abe6dd3e4
Replace extractModifiedFiles (main transcript only) with
claudecode.ExtractAllModifiedFiles which also parses subagent
transcripts. This fixes the core bug where subagent-only file
changes produced totalChanges=0, causing checkpoints to be skipped.

Falls back to main-transcript-only extraction on error. Also reuses
the subagentsDir variable for token usage calculation to avoid
redefinition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 732abe6dd3e4
…difications

The PrepareCommitMsg hook's live transcript check only scanned the main
transcript via ExtractModifiedFilesFromOffset, missing file changes made
by subagents spawned via the Task tool. When the main transcript contained
only Task calls (no direct Write/Edit), modifiedFiles was empty and the
function returned false -- causing missing checkpoint trailers on commits
that included subagent-written files.

After the existing main transcript scan, also call
claudecode.ExtractAllModifiedFiles which parses both the main and subagent
transcripts, picking up Write/Edit tool calls from subagent files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 732abe6dd3e4
…-297)

Verify that the Stop hook creates checkpoints when only subagents
modify files. The test constructs a main transcript with only a Task
tool call and a subagent transcript with Write tool calls, then
confirms both auto-commit and manual-commit strategies detect the
changes via ExtractAllModifiedFiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 732abe6dd3e4
- Add logging.Debug when ExtractAllModifiedFiles errors in
  sessionHasNewContentFromLiveTranscript (was silently swallowed)
- Fix AddTaskToolResult to produce "agentId: <id>" format matching
  real Claude Code transcripts (was "Task completed by agent <id>")
- Use AddTaskToolResult in integration test instead of reaching into
  TranscriptBuilder internals

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 1facd4391816
Three functions duplicated the same pattern: extract modified files from
the main transcript, augment with subagent transcripts, normalize paths.
Consolidate into extractModifiedFilesFromLiveTranscript(state, offset)
and two thin wrappers (extractFilesFromLiveTranscript for carry-forward,
extractNewModifiedFilesFromLiveTranscript for content detection).

Also wires subagent file extraction into extractFilesFromLiveTranscript
(carry-forward) and sessionHasNewContentInCommittedFiles (PostCommit
ACTIVE sessions) which were missing it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: fc1317d7f797
When condensing a mid-session commit (no shadow branch), FilesTouched
was extracted only from the main transcript. Subagent-modified files
were missed, causing the condensed checkpoint to have incomplete file
lists. Use the shared extractModifiedFilesFromLiveTranscript helper
which includes subagent transcripts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: e91ff0dab977
For ACTIVE sessions in PostCommit, always set hasNew=true instead of
re-validating via transcript analysis. PrepareCommitMsg already validates
the trailer (unconditionally for no-TTY/agent commits, via content
detection for TTY/human commits). Transcript-based re-validation is
unreliable because subagent transcripts may not be available at
PostCommit time (subagent still running).

Removes sessionHasNewContentInCommittedFiles which is now unused.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: f20127b19334
@khaong khaong force-pushed the alex/ent-297-fix-subagent-only-changes-checkpointing branch from 017c468 to cdc5c7e Compare February 15, 2026 06:23
@khaong khaong requested a review from Copilot February 15, 2026 06:43
@khaong
Copy link
Contributor Author

khaong commented Feb 15, 2026

bugbot run

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

For Claude Code agents, skip the generic ExtractModifiedFilesFromOffset
call and go directly to ExtractAllModifiedFiles, which parses the main
transcript and subagent transcripts in one pass. Previously both were
called, parsing the main transcript twice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 184069756ffc
@khaong
Copy link
Contributor Author

khaong commented Feb 15, 2026

bugbot run

@khaong khaong marked this pull request as ready for review February 15, 2026 08:08
@khaong khaong requested a review from a team as a code owner February 15, 2026 08:08
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Base automatically changed from soph/one-to-one-checkpoints to main February 15, 2026 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant