Skip to content

fixing checkpoint_transcript_start issue when agent continues writing logs#873

Open
Soph wants to merge 1 commit intomainfrom
soph/offset-fix
Open

fixing checkpoint_transcript_start issue when agent continues writing logs#873
Soph wants to merge 1 commit intomainfrom
soph/offset-fix

Conversation

@Soph
Copy link
Copy Markdown
Collaborator

@Soph Soph commented Apr 8, 2026

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_start behind when the agent keeps writing to the transcript after the commit; HandleTurnEnd now advances SessionState.CheckpointTranscriptStart to the current transcript position when TurnCheckpointIDs exist.

Adds integration tests covering (1) commits triggered in a later turn still include prior uncommitted-turn transcript content in the checkpoint scope, and (2) CheckpointTranscriptStart advances past the commit-time position once Stop finalizes a turn.

Reviewed by Cursor Bugbot for commit 17ee3e8. Configure here.

@Soph Soph requested a review from a team as a code owner April 8, 2026 16:36
Copilot AI review requested due to automatic review settings April 8, 2026 16:36
Copy link
Copy Markdown
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

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.CheckpointTranscriptStart at 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.

Comment on lines +2388 to +2397
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
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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
}

Copilot uses AI. Check for mistakes.
Comment on lines +159 to +162
// Record transcript length at commit time
transcriptLinesAtCommit := len(session.TranscriptBuilder.String())
_ = transcriptLinesAtCommit // for documentation

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
// Record transcript length at commit time
transcriptLinesAtCommit := len(session.TranscriptBuilder.String())
_ = transcriptLinesAtCommit // for documentation

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

}
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 17ee3e8. Configure here.

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.

2 participants