Stop losing uncommitted dev edits during task merges.
- `acquireReuseHandoff` no longer throws MergeHandoffRefusedError("working-tree-dirty") on a dirty reused worktree (FN-5138). It autostashes via `git add -A` + `git stash create` + `git stash store`, emits a `merge:reuse-handoff-autostash` audit event with the stash SHA and a recover command, and lets the merge proceed.
- `stashUnrelatedRootDirChanges` no longer silently proceeds when stash creation fails on a dirty tree. It throws a new `AutostashCreationFailedError`; the merger catches it and surfaces a clear "your edits are intact" message before any destructive op runs.
- New failure reason `dirty-worktree-autostash-failed` distinguishes stash failure from the old refusal.
- Tests in `merger-integration-worktree`, `merger-cwd-fallback-removed`, and `reliability-interactions/{integration-worktree-state,merge-reuse-task-worktree,cwd-integration-fallback-removed}` updated to the new contract; the FN-5348 "no cwd fallback" invariant is preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1.1 KiB
@runfusion/fusion
| @runfusion/fusion |
|---|
| patch |
Stop losing uncommitted dev edits during task merges. Two fixes to the merger:
-
The pre-merge autostash in
stashUnrelatedRootDirChangesno longer silently proceeds when stash creation fails over a dirty working tree. It now throwsAutostashCreationFailedError, which the merger catches and surfaces to the task feed before any destructivegit reset --hard/git clean -fdruns — your edits stay in the working tree. -
acquireReuseHandoffno longer refuses the handoff on a dirty reused task worktree (the FN-5138 "Merge handoff refused (working-tree-dirty)" failure). It now autostashes the dirty content (git add -A→git stash create→git stash store -m fusion-reuse-handoff-autostash:<taskId>:<ts>), emits amerge:reuse-handoff-autostashaudit event with the stash SHA and a recover command, and lets the merge proceed.
The new failure mode dirty-worktree-autostash-failed is reserved for the (rare) case where stash creation itself fails — so the operator can distinguish "we tried and failed" from the old "we refused to try."