fix(engine): recover workspace landedSha + strip shared branch overrides for sub-repo worktrees (FN-7360)

This commit is contained in:
gsxdsm
2026-07-07 08:42:47 -07:00
parent dacbead012
commit f2202619e0
2 changed files with 29 additions and 3 deletions

View File

@@ -1222,10 +1222,28 @@ export async function landWorkspaceTask(
// it so a retry never re-advances the ref. This makes a re-run after a partial
// land idempotent for the already-landed repos.
if (await isRepoLanded(repoRootDir, integrationBranch, entry.landedSha, taskId, entry.branch)) {
await log(`AI merge (workspace): sub-repo ${repoRel} already landed (${short(entry.landedSha!)} ⊑ ${integrationBranch}) — skipping`);
/*
FNXC:Workspace 2026-07-07-08:35 (Phase C A1 recovery — recover landedSha for finalize proof):
isRepoLanded's A1 trailer-fallback can prove a sub-repo is landed even when its landedSha
was never persisted (the persist-after-advance window in persistRepoLandedSha threw). That
left the in-memory result with landedSha: undefined, so finalizeWorkspaceTask's
`status === "landed" && landedSha` filter dropped the recovered repo, `anyLanded` stayed
false, and the proven repo's retry STRANDED the task in-review with missing-merge-confirmation
(finalizeTask's hasDurableMergeProof needs mergeConfirmed). Recover the CURRENT integration
tip as landedSha — the trailer-fallback already proved the task branch is an ancestor of this
tip — so the finalize builds durable mergeConfirmed proof and the A1 retry completes to done.
*/
let recoveredLandedSha = entry.landedSha;
if (!recoveredLandedSha) {
recoveredLandedSha = await git(
["rev-parse", "--verify", `refs/heads/${integrationBranch}`],
repoRootDir,
).catch(() => undefined);
}
await log(`AI merge (workspace): sub-repo ${repoRel} already landed (${short(recoveredLandedSha ?? "?")} ⊑ ${integrationBranch}) — skipping`);
repos.push({
repo: repoRel, repoRootDir, integrationBranch, branch: entry.branch,
status: "landed", landedSha: entry.landedSha, alreadyLanded: true,
status: "landed", landedSha: recoveredLandedSha, alreadyLanded: true,
});
continue;
}

View File

@@ -862,7 +862,15 @@ export async function acquireWorkspaceRepoWorktree(
task: { ...task, worktree: undefined, branch: undefined },
rootDir: repoAbsPath,
store,
settings,
// FNXC:Workspace 2026-07-07-08:40 (FN-7360 regression — strip shared branch overrides for per-repo start-point):
// FN-7360 pinned fresh task worktree creation to `resolveIntegrationBranch(rootDir, settings)`
// when no executionStartBranch is present, so new branches never inherit an ambient root HEAD.
// For a workspace sub-repo, `settings` carries the SHARED project integrationBranch/baseBranch;
// honoring it resolves a branch absent from this sub-repo and fails `git worktree add` with
// "invalid reference". Strip both overrides here so freshStartPoint falls through to this
// sub-repo's own origin/HEAD — matching the per-repo base-SHA capture below, which already
// resolves against stripped settings (F4/KTD3).
settings: { ...settings, integrationBranch: undefined, baseBranch: undefined },
logger,
secretsStore,
audit,