fix(engine): defend autostash drop against TOCTOU race

dropAutostashBySha resolved SHA→stash@{N} then ran git stash drop ${ref}
non-atomically. Any other process (interactive shell, parallel merger,
fix-agent) pushing a stash between resolve and drop shifted the index, so
we silently dropped the wrong entry while leaving ours behind. The task
log then claimed "Restored pre-merge autostash X cleanly" even though the
stash was still in the list — observed on FN-3558 (e81e922) and others.

Verify the ref still resolves to our SHA via git rev-parse before dropping;
on mismatch, re-resolve and retry up to 5x. Return success/failure so the
caller can record honest status to the task feed instead of unconditionally
logging "cleanly".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-08 14:05:06 -07:00
parent ae6fdf9329
commit 11ed9cb409
4 changed files with 99 additions and 26 deletions

View File

@@ -261,6 +261,7 @@ async function captureTools(settingsOverride?: Record<string, unknown>): Promise
{ name: "Preflight", status: "done" },
{ name: "Implement", status: "in-progress" },
{ name: "Testing", status: "pending" },
{ name: "Docs", status: "pending" },
];
store.updateStep.mockImplementation(async (_taskId: string, stepIndex: number, status: string) => {
const current = stepStates[stepIndex];