fix(engine): verify resumed worktrees aren't bootstrap-misbound
The resume path in acquireTaskWorktree returned a reused worktree without checking whether its branch contained foreign commits. If a sibling task's tip had been baked into the branch at creation time, the executor preflight would later fail contamination checks forever (observed in the FN-5475 cascade). The resume path now computes a fresh merge-base and runs classifyBootstrapMisbinding. For the foreign-only / zero-own-commits shape it re-anchors inline and emits a branch:reanchor audit event. Mixed contamination continues to flow through the executor's primary recovery path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
24
.changeset/fix-engine-resume-misbinding-verify.md
Normal file
24
.changeset/fix-engine-resume-misbinding-verify.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
"@fusion/engine": patch
|
||||
---
|
||||
|
||||
fix(engine): verify resumed worktree branches aren't bootstrap-misbound
|
||||
|
||||
`acquireTaskWorktree` short-circuited the resume path when
|
||||
`task.worktree` existed on disk and classified `ok`, handing the
|
||||
worktree back to the executor without inspecting its branch history.
|
||||
If the branch had been created from a poisoned local-main tip (a
|
||||
sibling task's commit), the executor preflight would later flag every
|
||||
intermediate landing as foreign and the task would loop through
|
||||
contamination recovery until pausing for human adjudication
|
||||
(observed in the FN-5475 cascade).
|
||||
|
||||
The resume path now computes a fresh merge-base against local `main`
|
||||
(falling back to `origin/main`) and runs `classifyBootstrapMisbinding`
|
||||
on the branch. When the range is purely foreign with zero own commits,
|
||||
it re-anchors the branch inline via `reanchorBranchToBase` and emits a
|
||||
`branch:reanchor` audit event with `trigger: "resume-misbinding"`.
|
||||
|
||||
Mixed contamination (own + foreign, or non-attributed commits) is
|
||||
deliberately left to the executor's existing primary path so the
|
||||
richer adjudication flow still applies.
|
||||
Reference in New Issue
Block a user