fix(engine): auto-reattach HEAD at handoff when branch ref is authoritative

The merge handoff refused with head-branch-mismatch whenever the reused
worktree's HEAD wasn't on fusion/<id> (detached, recycled to main, or on
a sibling branch), even when the branch ref itself still held a clean,
task-attributed lineage. That wedged FN-5339-class tasks in review for
no good reason.

Add isBranchAuthoritativeForTask in branch-conflicts.ts (branch ref
exists, tip carries Fusion-Task-Id trailer, base..branch is foreign-
contamination-free) and use it in acquireReuseHandoff: when HEAD drifts
but the branch ref is authoritative, run a plain `git checkout <branch>`
inside the already-asserted-clean worktree, re-read HEAD, and emit a
branch:auto-reattach-authoritative audit. Refusal still fires unchanged
when the branch ref is missing, missing the trailer, or contaminated,
so FN-5363 strict-lease and foreign-commit guards remain authoritative.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-21 19:03:35 -07:00
parent 025683ca60
commit d947197c2a
4 changed files with 184 additions and 5 deletions

View File

@@ -275,6 +275,62 @@ async function summarizeTaskAttributedCommits(repoDir: string, range: string, ta
return { ownCount, foreignCount };
}
/**
* True iff `branch`'s tip commit carries a `Fusion-Task-Id: <taskId>` trailer.
* Used as the cheap "is this branch ref authoritative for this task" probe
* at merge handoff so that HEAD drift (detached, wrong branch) can recover
* via a safe re-attach instead of refusing the handoff outright.
*/
export async function branchTipCarriesTaskIdTrailer(
repoDir: string,
branch: string,
taskId: string,
): Promise<boolean> {
try {
const body = await runGit(repoDir, `git log -1 --pretty=%B ${quoteShellArg(branch)}`);
const escaped = taskId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const pattern = new RegExp(`(?:^|\\n)${FUSION_TASK_ID_TRAILER_KEY}: ${escaped}\\s*(?:\\n|$)`);
return pattern.test(body);
} catch {
return false;
}
}
/**
* Whole-branch authority check: the branch ref exists, its tip carries the
* task's Fusion-Task-Id trailer, and (when a base is supplied) the range
* `base..branch` has no foreign FN-attributed commits.
*
* Returns `{ ok: true }` when safe to treat the branch ref as authoritative
* for `taskId`. On failure, returns `{ ok: false, reason }` so callers can
* log/audit why the gentle recovery was refused.
*/
export async function isBranchAuthoritativeForTask(
repoDir: string,
branch: string,
taskId: string,
baseSha?: string,
): Promise<{ ok: true } | { ok: false; reason: string }> {
try {
await revParse(repoDir, `refs/heads/${branch}`);
} catch {
return { ok: false, reason: "branch-ref-missing" };
}
const tipCarriesTrailer = await branchTipCarriesTaskIdTrailer(repoDir, branch, taskId);
if (!tipCarriesTrailer) {
return { ok: false, reason: "tip-missing-task-trailer" };
}
if (baseSha) {
try {
await assertCleanBranchAtBase(repoDir, branch, baseSha, taskId);
} catch (err) {
const reason = err instanceof BranchCrossContaminationError ? "foreign-contamination" : "clean-branch-check-failed";
return { ok: false, reason };
}
}
return { ok: true };
}
export async function assertCleanBranchAtBase(
repoDir: string,
branchName: string,