Skip to content

Commit ea96ec6

Browse files
committed
feat: skip checkpoints when worktree unchanged (read-only bash like ls, find, cat)
Compares worktreeTreeSha after creating checkpoint — if identical to last checkpoint, deletes it immediately. Eliminates false positives from read-only bash commands during planning/exploration turns. Before: every bash tool triggered a checkpoint (even ls, cat, grep) After: only checkpoints when files actually change
1 parent 62ab13a commit ea96ec6

3 files changed

Lines changed: 15 additions & 1 deletion

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pi-rewind",
3-
"version": "0.3.1",
3+
"version": "0.3.2",
44
"description": "Checkpoint/rewind extension for the Pi coding agent — per-tool snapshots, /rewind command, Esc+Esc shortcut, safe restore, redo stack",
55
"license": "MIT",
66
"author": "arpagon",

src/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
isGitRepo,
2121
getRepoRoot,
2222
createCheckpoint,
23+
deleteCheckpoint,
2324
loadAllCheckpoints,
2425
pruneCheckpoints,
2526
MUTATING_TOOLS,
@@ -97,6 +98,7 @@ export default function (pi: ExtensionAPI) {
9798
});
9899
state.resumeCheckpoint = cp;
99100
state.checkpoints.set(cp.id, cp);
101+
state.lastWorktreeTree = cp.worktreeTreeSha;
100102
} catch {
101103
// Resume checkpoint is optional
102104
}
@@ -196,7 +198,15 @@ export default function (pi: ExtensionAPI) {
196198
turnIndex: state.currentTurnIndex,
197199
description: desc,
198200
});
201+
202+
// Skip if worktree is identical to last checkpoint (read-only bash like ls, find, cat)
203+
if (state.lastWorktreeTree && cp.worktreeTreeSha === state.lastWorktreeTree) {
204+
await deleteCheckpoint(state.repoRoot!, cp.id);
205+
return;
206+
}
207+
199208
state.checkpoints.set(cp.id, cp);
209+
state.lastWorktreeTree = cp.worktreeTreeSha;
200210
updateStatus(state, ctx);
201211
} catch {
202212
// Checkpoint failures are non-fatal

src/state.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export interface RewindState {
3333
turnToolDescriptions: string[];
3434
/** Whether the current turn had any mutating tool calls */
3535
turnHadMutations: boolean;
36+
/** Last worktree tree SHA (to detect actual file changes) */
37+
lastWorktreeTree: string | null;
3638
}
3739

3840
export function createInitialState(): RewindState {
@@ -50,6 +52,7 @@ export function createInitialState(): RewindState {
5052
pendingToolInfo: new Map(),
5153
turnToolDescriptions: [],
5254
turnHadMutations: false,
55+
lastWorktreeTree: null,
5356
};
5457
}
5558

@@ -67,4 +70,5 @@ export function resetState(state: RewindState): void {
6770
state.pendingToolInfo.clear();
6871
state.turnToolDescriptions = [];
6972
state.turnHadMutations = false;
73+
state.lastWorktreeTree = null;
7074
}

0 commit comments

Comments
 (0)