fix: detect reset-driven session divergence in status#948
fix: detect reset-driven session divergence in status#948peyton-alt wants to merge 1 commit intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds narrow, status-only handling for git reset-driven session divergence by comparing active session linkage against the current HEAD’s Entire-Checkpoint trailer, auto-reconciling only when the checkpoint match is unambiguous and otherwise emitting a warning.
Changes:
- Resolve
HEADand parseEntire-Checkpointtrailer(s) duringentire statusrendering. - Reconcile active session
BaseCommit/AttributionBaseCommitonly whenHEADcheckpoint matchesLastCheckpointID; otherwise warn without mutating session state. - Add unit tests covering safe reset reconciliation and divergence warning behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| cmd/entire/cli/status.go | Adds HEAD linkage detection, worktree-path normalization, and session divergence reconciliation + warning rendering in status. |
| cmd/entire/cli/status_test.go | Adds tests exercising reset reconciliation vs divergence warning behavior. |
| head := headLinkage{commitHash: headRef.Hash().String()} | ||
| if checkpointIDs := trailers.ParseAllCheckpoints(commit.Message); len(checkpointIDs) > 0 { | ||
| head.checkpointID = checkpointIDs[0].String() | ||
| } |
There was a problem hiding this comment.
currentHeadLinkage only records the first Entire-Checkpoint trailer (checkpointIDs[0]). trailers.ParseAllCheckpoints explicitly supports multiple checkpoint trailers (e.g., squash merges) while preserving order, so HEAD may legitimately link to several checkpoints. With the current implementation, a session whose LastCheckpointID matches a later trailer will incorrectly fail to reconcile and will show a divergence warning. Consider storing all parsed checkpoint IDs (e.g., as a []string or a map[string]struct{} in headLinkage) and treating HEAD as matching if LastCheckpointID equals any of them; update the warning text accordingly (e.g., mention the matched/available checkpoint IDs).
| head := headLinkage{commitHash: headRef.Hash().String()} | ||
| if checkpointIDs := trailers.ParseAllCheckpoints(commit.Message); len(checkpointIDs) > 0 { | ||
| head.checkpointID = checkpointIDs[0].String() | ||
| } |
There was a problem hiding this comment.
The new reset-reconciliation logic is covered for the single-trailer case, but there's no test covering HEAD commits that contain multiple Entire-Checkpoint trailers (which ParseAllCheckpoints supports for squash merges). Adding a status test where HEAD has multiple checkpoint trailers would prevent regressions (especially if reconciliation should succeed when LastCheckpointID matches any trailer).
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 f692674. Configure here.
| head := headLinkage{commitHash: headRef.Hash().String()} | ||
| if checkpointIDs := trailers.ParseAllCheckpoints(commit.Message); len(checkpointIDs) > 0 { | ||
| head.checkpointID = checkpointIDs[0].String() | ||
| } |
There was a problem hiding this comment.
Only first checkpoint ID checked, missing valid matches
Low Severity
currentHeadLinkage calls trailers.ParseAllCheckpoints but only stores the first checkpoint ID in headLinkage.checkpointID. In reconcileActiveSessionHeadDivergence, each session's LastCheckpointID is compared against only this first ID. If HEAD has multiple Entire-Checkpoint trailers (e.g. from a squash merge used as a reset target), sessions whose LastCheckpointID matches a non-first trailer will receive a false divergence warning instead of being auto-reconciled.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f692674. Configure here.


Summary
Adds lightweight support for
git resetin the CLI status path.When an active session's tracked
BaseCommitno longer matches the currentHEAD,entire statusnow:HEADlands on a commit with the sameEntire-Checkpointtrailer as the session'sLastCheckpointIDThis keeps reset support intentionally narrow: safe auto-reconciliation for the obvious same-checkpoint case, warning-only behavior for ambiguous history movement.
Fix
HEADand parse itsEntire-Checkpointtrailer instatusBaseCommitandAttributionBaseCommitonly when the session'sLastCheckpointIDmatches the checkpoint trailer onHEADHEADmoved without a matching checkpoint trailer, and surface a warning instatusTests
Passed:
GOCACHE=/tmp/go-build go test ./cmd/entire/cli -run 'Test(ResolveWorktreeBranch_|RunStatus_|WriteActiveSessions_)' -count=1GOCACHE=/tmp/go-build go test ./cmd/entire/cli ./cmd/entire/cli/session ./cmd/entire/cli/trailers -count=1GOCACHE=/tmp/go-build go test -tags=integration ./cmd/entire/cli/integration_test -run 'TestShadow_(AmendPreservesTrailer|PostRewriteAmendRemapsSessionState|PostRewriteRebaseRemapsSessionState)' -count=1GOCACHE=/tmp/go-build GOLANGCI_LINT_CACHE=/tmp/golangci-lint golangci-lint run ./cmd/entire/cliManual user-simulated reset repro:
Entire-Checkpointtrailer updated persisted sessionBaseCommitto the reset target and showed no warningtracking diverged from current HEAD after git history movementNew Behavior
Before this change,
git resetleft active session linkage stale until the user repaired it elsewhere.After this change:
git resetback to a known checkpoint-linked commit is recovered automatically on the nextentire statusgit resetto an ambiguous or unrelated commit is surfaced clearly inentire statuswithout rewriting linkage stateNote
Medium Risk
Touches session-linkage persistence during
entire statusrendering by conditionally mutatingBaseCommit/AttributionBaseCommitbased on HEAD trailers; incorrect matching or path normalization issues could cause misleading status or unintended state updates.Overview
entire statusnow detects when an active session’s storedBaseCommitno longer matches the repo’s currentHEAD(e.g., aftergit reset). IfHEAD’s commit message contains anEntire-Checkpointtrailer matching the session’sLastCheckpointID, status silently re-links the session by updating and persistingBaseCommit/AttributionBaseCommitto the currentHEAD; otherwise it leaves state unchanged and prints a per-session divergence warning.This adds HEAD inspection via
go-git, parses checkpoint trailers, and normalizes worktree paths (including symlink resolution) before comparing sessions to the current repo. New tests cover both the safe auto-reconciliation path and the warning-only divergent reset path.Reviewed by Cursor Bugbot for commit f692674. Configure here.