fix(engine): skip promoted-foreign commits in contamination audit
assertCleanBranchAtBase now checks each foreign-attributed commit against `git merge-base --is-ancestor <sha> main`. If the commit is already on local main, it was promoted through integration regardless of whose Fusion-Task-Id trailer it carries — treating it as foreign contamination is wrong and was the root cause of the FN-5475 cascade (downstream worktrees inherited a sibling task's tip during the brief fast-forward window before main moved further). Audit cost: O(N) extra git calls per audit run, where N is the number of foreign-trailer commits in baseSha..branchName. Each call is ~5-10ms and N is typically 1-5. Negligible relative to the surrounding I/O. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -466,6 +466,48 @@ describe("branch-conflicts", () => {
|
||||
await expect(assertion).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
// FN-5475 / option-2 promotion check: a commit attributed to another
|
||||
// task that's already reachable from local `main` was integrated via
|
||||
// fast-forward and shouldn't be treated as contamination on a
|
||||
// downstream branch that briefly inherited it.
|
||||
it("assertCleanBranchAtBase treats foreign-attributed commits that are ancestors of main as promoted", async () => {
|
||||
mockedExecSync.mockImplementation((cmd: string | string[]) => {
|
||||
const command = typeof cmd === "string" ? cmd : cmd[0];
|
||||
if (command.includes("git log --format=%H%x1f%s%x1f%b 'main..fusion/fn-4068'")) {
|
||||
return Buffer.from("bbb222feat(FN-4386): foreignFusion-Task-Id: FN-4386\n");
|
||||
}
|
||||
if (command.includes("git merge-base --is-ancestor 'bbb222' 'main'")) {
|
||||
// Simulate the FN-5475 case: foreign commit is already on main.
|
||||
return Buffer.from("");
|
||||
}
|
||||
throw new Error(`Unexpected command: ${command}`);
|
||||
});
|
||||
|
||||
await expect(
|
||||
assertCleanBranchAtBase("/tmp/repo", "fusion/fn-4068", "main", "FN-4068"),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("assertCleanBranchAtBase still throws when foreign-attributed commits are NOT on main", async () => {
|
||||
mockedExecSync.mockImplementation((cmd: string | string[]) => {
|
||||
const command = typeof cmd === "string" ? cmd : cmd[0];
|
||||
if (command.includes("git log --format=%H%x1f%s%x1f%b 'main..fusion/fn-4068'")) {
|
||||
return Buffer.from("bbb222feat(FN-4386): foreignFusion-Task-Id: FN-4386\n");
|
||||
}
|
||||
if (command.includes("git merge-base --is-ancestor")) {
|
||||
// Not on main — exits non-zero.
|
||||
const err = new Error("not an ancestor") as Error & { stderr?: string };
|
||||
err.stderr = "";
|
||||
throw err;
|
||||
}
|
||||
throw new Error(`Unexpected command: ${command}`);
|
||||
});
|
||||
|
||||
await expect(
|
||||
assertCleanBranchAtBase("/tmp/repo", "fusion/fn-4068", "main", "FN-4068"),
|
||||
).rejects.toBeInstanceOf(BranchCrossContaminationError);
|
||||
});
|
||||
|
||||
describe("reportBranchAttribution", () => {
|
||||
const RS = "\x1e";
|
||||
const FS = "\x1f";
|
||||
|
||||
Reference in New Issue
Block a user