fix(engine): tighten merger scope-warning diff base when baseBranch is missing

Mirrors dashboard `resolveDiffBase` display-recovery: when `baseBranch` is
absent, compute `merge-base(HEAD, main)` and prefer it over a stale
`baseCommitSha` only if it strictly descends that SHA. Pre-merge rebase
on legacy/imported tasks (no recorded baseBranch) was producing inflated
"N files changed outside declared File Scope" warnings — FN-3898 surfaced
17 ghost files for a 3-file change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-05-09 16:06:05 -07:00
parent 68ec5e2e9d
commit 200ea8ead0
3 changed files with 102 additions and 0 deletions

View File

@@ -3095,18 +3095,63 @@ export async function resolveTaskDiffBaseRef({
}
}
// Display recovery (mirrors dashboard `resolveDiffBase` with
// `enableDisplayRecovery: true`): when baseBranch is missing — common for
// legacy/imported tasks — compute merge-base(headRef, main) so we can
// tighten an outdated-but-still-ancestor baseCommitSha after a pre-merge
// rebase. Without this the scope warning compares against a stale
// baseCommitSha and surfaces every unrelated commit landed on main since
// the task forked.
let recoveredBase: string | undefined;
if (!baseBranch?.trim()) {
try {
const { stdout } = await execAsync(`git merge-base ${quotedHeadRef} main`, {
cwd,
encoding: "utf-8",
});
recoveredBase = stdout.trim() || undefined;
} catch {
try {
const { stdout } = await execAsync(`git merge-base ${quotedHeadRef} ${quoteArg("origin/main")}`, {
cwd,
encoding: "utf-8",
});
recoveredBase = stdout.trim() || undefined;
} catch {
// no recovery available
}
}
}
if (baseCommitSha) {
try {
await execAsync(`git merge-base --is-ancestor ${quoteArg(baseCommitSha)} ${quotedHeadRef}`, {
cwd,
encoding: "utf-8",
});
// Prefer recoveredBase only if it's strictly tighter (a descendant of
// baseCommitSha). When baseCommitSha lives on a deleted feature branch
// it won't be an ancestor of merge-base(HEAD, main), so we keep the
// task-scoped SHA — preserves the FN-2855 nulled-baseBranch path.
if (recoveredBase && recoveredBase !== baseCommitSha) {
try {
await execAsync(`git merge-base --is-ancestor ${quoteArg(baseCommitSha)} ${quoteArg(recoveredBase)}`, {
cwd,
encoding: "utf-8",
});
return recoveredBase;
} catch {
// recoveredBase not a descendant — keep baseCommitSha
}
}
return baseCommitSha;
} catch {
// stale or unreachable — fall through
}
}
if (recoveredBase) return recoveredBase;
try {
const { stdout } = await execAsync(`git rev-parse ${quoteArg(`${headRef}~1`)}`, {
cwd,