fixing checkpoint_transcript_start issue when agent continues writing logs#873
fixing checkpoint_transcript_start issue when agent continues writing logs#873
Conversation
… logs Entire-Checkpoint: 04e46567beaa
There was a problem hiding this comment.
Pull request overview
Fixes incorrect checkpoint_transcript_start handling when an agent performs a mid-turn commit but continues appending transcript/log lines afterward, which previously caused “tail” content to appear at the start of the next checkpoint in the UI.
Changes:
- Advance
SessionState.CheckpointTranscriptStartat turn end to the actual transcript end when mid-turn commits occurred. - Add integration tests covering transcript offset behavior across uncondensed turns and mid-turn commits.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
cmd/entire/cli/strategy/manual_commit_hooks.go |
Updates turn-end handling to advance CheckpointTranscriptStart after mid-turn commits to prevent transcript bleed into the next checkpoint. |
cmd/entire/cli/integration_test/transcript_offset_test.go |
Adds integration coverage for checkpoint_transcript_start behavior across turns and mid-turn commits. |
| if ag, agErr := agent.GetByAgentType(state.AgentType); agErr == nil { | ||
| if analyzer, ok := agent.AsTranscriptAnalyzer(ag); ok { | ||
| if pos, posErr := analyzer.GetTranscriptPosition(state.TranscriptPath); posErr == nil && pos > state.CheckpointTranscriptStart { | ||
| logging.Debug(logging.WithComponent(ctx, "hooks"), | ||
| "advancing CheckpointTranscriptStart to turn end after mid-turn commit", | ||
| slog.String("session_id", state.SessionID), | ||
| slog.Int("old_offset", state.CheckpointTranscriptStart), | ||
| slog.Int("new_offset", pos), | ||
| ) | ||
| state.CheckpointTranscriptStart = pos |
There was a problem hiding this comment.
In this turn-end advancement block, GetTranscriptPosition is called on state.TranscriptPath directly. Elsewhere in this strategy (e.g., hasNewTranscriptWork/extractModifiedFilesFromLiveTranscript) the code calls resolveTranscriptPath(state) first to handle agents that relocate transcripts mid-session (Cursor layout changes, etc.). To avoid failing to advance CheckpointTranscriptStart when the transcript has moved (and to keep behavior consistent), resolve the transcript path here as well and use the resolved path for GetTranscriptPosition.
| if ag, agErr := agent.GetByAgentType(state.AgentType); agErr == nil { | |
| if analyzer, ok := agent.AsTranscriptAnalyzer(ag); ok { | |
| if pos, posErr := analyzer.GetTranscriptPosition(state.TranscriptPath); posErr == nil && pos > state.CheckpointTranscriptStart { | |
| logging.Debug(logging.WithComponent(ctx, "hooks"), | |
| "advancing CheckpointTranscriptStart to turn end after mid-turn commit", | |
| slog.String("session_id", state.SessionID), | |
| slog.Int("old_offset", state.CheckpointTranscriptStart), | |
| slog.Int("new_offset", pos), | |
| ) | |
| state.CheckpointTranscriptStart = pos | |
| transcriptPath := resolveTranscriptPath(state) | |
| if transcriptPath != "" { | |
| if ag, agErr := agent.GetByAgentType(state.AgentType); agErr == nil { | |
| if analyzer, ok := agent.AsTranscriptAnalyzer(ag); ok { | |
| if pos, posErr := analyzer.GetTranscriptPosition(transcriptPath); posErr == nil && pos > state.CheckpointTranscriptStart { | |
| logging.Debug(logging.WithComponent(ctx, "hooks"), | |
| "advancing CheckpointTranscriptStart to turn end after mid-turn commit", | |
| slog.String("session_id", state.SessionID), | |
| slog.Int("old_offset", state.CheckpointTranscriptStart), | |
| slog.Int("new_offset", pos), | |
| ) | |
| state.CheckpointTranscriptStart = pos | |
| } |
| // Record transcript length at commit time | ||
| transcriptLinesAtCommit := len(session.TranscriptBuilder.String()) | ||
| _ = transcriptLinesAtCommit // for documentation | ||
|
|
There was a problem hiding this comment.
transcriptLinesAtCommit is computed via len(session.TranscriptBuilder.String()) (byte length of the rendered transcript), then immediately discarded. Since it isn't used for any assertion and the measurement is misleading (bytes vs lines/position), it should be removed to keep the test focused and avoid confusion.
| // Record transcript length at commit time | |
| transcriptLinesAtCommit := len(session.TranscriptBuilder.String()) | |
| _ = transcriptLinesAtCommit // for documentation |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 17ee3e8. Configure here.
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Carry-forward transcript offset overwritten after mid-turn commit
Medium Severity
When carry-forward is active, carryForwardToNewShadowBranch intentionally resets CheckpointTranscriptStart to 0 so the next checkpoint is self-contained with the full transcript. However, the new code only checks pos > state.CheckpointTranscriptStart — and since state.CheckpointTranscriptStart is 0 after carry-forward, any non-empty transcript causes it to be overwritten to pos. This breaks the carry-forward invariant, causing the next checkpoint's scoped transcript to start mid-stream instead of from the beginning. The existing comment at line 2568–2572 explicitly warns against this exact scenario.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 17ee3e8. Configure here.


Codex (and probably other agents) continue to write logs sometimes even after a commit was run. We handle this in the checkpoints but we aren't updating the position in the logs properly so these lines bleed into the next checkpoint and are shown as first messages in the UI.
This fixes this.
Note
Medium Risk
Touches checkpoint scoping state (
CheckpointTranscriptStart) at turn end, which can affect what transcript content is shown per checkpoint; failure modes are mostly incorrect UI context rather than data loss.Overview
Prevents checkpoints created by mid-turn commits from leaving
checkpoint_transcript_startbehind when the agent keeps writing to the transcript after the commit;HandleTurnEndnow advancesSessionState.CheckpointTranscriptStartto the current transcript position whenTurnCheckpointIDsexist.Adds integration tests covering (1) commits triggered in a later turn still include prior uncommitted-turn transcript content in the checkpoint scope, and (2)
CheckpointTranscriptStartadvances past the commit-time position onceStopfinalizes a turn.Reviewed by Cursor Bugbot for commit 17ee3e8. Configure here.