Skip to content

fix: unnecessary restore prompt, wrong checkpoint on tree nav, and leaf position persistence#4

Open
LiusCraft wants to merge 1 commit into
arpagon:mainfrom
LiusCraft:main
Open

fix: unnecessary restore prompt, wrong checkpoint on tree nav, and leaf position persistence#4
LiusCraft wants to merge 1 commit into
arpagon:mainfrom
LiusCraft:main

Conversation

@LiusCraft

@LiusCraft LiusCraft commented Jul 12, 2026

Copy link
Copy Markdown

Background

When using pi agent's Tree navigation (double Esc → select a previous turn), two issues occurred:

Issue 1: Unnecessary restore prompt + wrong checkpoint restored

Two facets to this bug:

  1. Navigating to a turn that made no file changes still showed "Restore files to that point".
  2. If the user chose to restore, files were rolled back to an older checkpoint than expected — not the state at the navigated turn.

Root cause: Checkpoints are created at turn_end, with timestamps after the user message in the same turn. The original handleTreeRestore used sorted.find(c => c.timestamp <= targetTs) to locate a checkpoint for the target entry. This lookup always missed the current turn's checkpoint (its timestamp is too recent) and found one from an earlier turn instead. This caused two symptoms:

  • cp !== latestCp was always true, so the restore prompt always appeared
  • When the user accepted, the restore targeted that earlier checkpoint, not the navigated turn's state

Issue 2: Navigation position not persisted

After navigating back via the tree and exiting pi, running pi -c resumed at the latest conversation tail instead of the previously navigated position.

Root cause (surface): SessionManager._buildIndex() always sets leafId to the last entry when loading from disk — navigateTree only changes leafId in memory, never persisted.

Root cause (deeper): The original leaf file was keyed by ephemeral session UUID (leaf-{sessionId}.json). Since pi -c starts a new process with a new session UUID, the saved leaf was never found on resume.

Changes

commands.ts

  • handleForkRestore: Compute hasFileChanges by comparing target vs latest checkpoint; only show file-restore options when real changes exist. Remove the no-op if (!target && state.resumeCheckpoint) stub.
  • handleTreeRestore: Accept oldLeafId in event type; compare old-leaf checkpoint vs target-leaf checkpoint to decide whether file restore is needed. Variable names consolidated.

index.ts

  • Add leaf-position persistence (leafFilePath/saveLeafId/loadLeafId/clearLeafId) — keyed by repo root path (stable across session restarts), saved to ~/.pi/agent/pi-rewind/leaf-{repoKey}.json.
  • session_tree listener: save leaf on tree navigation.
  • before_agent_start (new): clear saved leaf on new turn.
  • initSession: restore saved leaf unconditionally on session start (no reason guard, so it works for pi -c too).

@LiusCraft

LiusCraft commented Jul 12, 2026

Copy link
Copy Markdown
Author

@arpagon This PR fixes three issues with Tree navigation in pi-rewind:

Issue 1: Unnecessary restore prompt + wrong checkpoint restored

  • Restore prompt appeared even when no files changed
  • If accepted, files rolled back to an older checkpoint than expected

Root cause: checkpoint timestamps are at turn_end (after user message), so the lookup always missed the current turn's checkpoint.

Issue 2: Navigation position not persisted
After navigating back via the tree and re-launching pi, the session resumed at the latest conversation tail. Root cause: leafId only lives in memory.

Issue 3 (new): pi update --extensions wiped the saved leaf
initSession consumed the leaf unconditionally; now guarded by reason === "resume".

Full details in the PR description. Would appreciate a review. Thanks!

@LiusCraft LiusCraft changed the title fix: smarter file-restore prompts & session-tree leaf persistence fix: unnecessary restore prompt, wrong checkpoint on tree nav, and leaf position persistence Jul 12, 2026
@LiusCraft
LiusCraft force-pushed the main branch 4 times, most recently from 3aee8ab to b615687 Compare July 12, 2026 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant