test(FN-4344): complete Step 2 — add HEAD-drift audit cache lookup tests

Fusion-Task-Id: FN-4344
Fusion-Task-Lineage: 5c3fc80e-619d-4daf-a224-580cea402b4c
This commit is contained in:
Fusion
2026-05-13 21:50:45 -07:00
committed by gsxdsm
parent c3da1684ce
commit 0d4ea23871

View File

@@ -2493,7 +2493,7 @@ describe("aiMergeTask post-squash audit gate", () => {
});
}
function setupRebaseRouteExecSync() {
function setupRebaseRouteExecSync(treeOverrides?: Record<string, string | Error>) {
let headIndex = 0;
const landedHeads = ["landedcommit001", "landedcommit002"];
mockedExecSync.mockImplementation((cmd: any) => {
@@ -2503,6 +2503,14 @@ describe("aiMergeTask post-squash audit gate", () => {
if (cmdStr === "git rev-parse HEAD" || cmdStr.startsWith("git rev-parse HEAD ")) {
return (headIndex > 0 ? landedHeads[Math.min(headIndex - 1, landedHeads.length - 1)] : "basehead123") as any;
}
if (cmdStr.includes("^{tree}") && treeOverrides) {
for (const [ref, value] of Object.entries(treeOverrides)) {
if (cmdStr.includes(`git rev-parse ${ref}^{tree}`) || cmdStr.includes(`git rev-parse "${ref}"^{tree}`)) {
if (value instanceof Error) throw value;
return `${value}\n` as any;
}
}
}
if (cmdStr.includes('git rev-parse "main"') || cmdStr.includes("git rev-parse main")) return "basehead123" as any;
if (cmdStr.includes('git rev-list --count "main..fusion/fn-050"')) return "2\n" as any;
if (cmdStr.includes('git rev-list --reverse "main..fusion/fn-050"') || cmdStr.includes('git rev-list --reverse "basehead123..fusion/fn-050"')) {
@@ -2618,6 +2626,136 @@ describe("aiMergeTask post-squash audit gate", () => {
});
});
it("clears overlap-only post-rebase findings when branch-tip tree is verified despite audit ref drift (FN-4344)", async () => {
setupRebaseRouteExecSync({
landedcommit002: "tree-unverified",
"fusion/fn-050": "tree-verified",
});
mockedAuditSquashMerge.mockResolvedValue({
strategy: "rebase",
rangeBaseSha: "basehead123",
rangeHeadSha: "landedcommit002",
parentSha: "basehead123",
auditTargetLabel: "basehead123..landedcommit002",
lookback: 30,
branchSubjects: ["fix: substantive one", "feat: substantive two"],
recentMainSubjects: [],
duplicateSubjects: [],
touchedFiles: ["src/feature-a.ts"],
touchedFileOverlaps: [{
type: "touched-file-overlap",
file: "src/feature-a.ts",
recentMainCommits: [{ sha: "abc1234", subject: "fix: overlap" }],
}],
findings: [{
type: "touched-file-overlap",
file: "src/feature-a.ts",
recentMainCommits: [{ sha: "abc1234", subject: "fix: overlap" }],
}],
issueCount: 1,
clean: false,
});
mockedExistsSync.mockReturnValue(false);
const store = createAuditStore({ postMergeAuditMode: "block", testCommand: undefined, buildCommand: undefined }, { branch: "fusion/fn-050" });
vi.mocked(store.getVerificationCacheHit).mockImplementation((treeSha: string) => (
treeSha === "tree-verified" ? { recordedAt: "2026-05-13T00:00:00.000Z", taskId: "FN-049" } : null
));
await aiMergeTask(store, "/tmp/root", "FN-050");
expect(store.moveTask).toHaveBeenCalledWith("FN-050", "done");
expect(store.appendAgentLog).toHaveBeenCalledWith(
"FN-050",
expect.stringContaining("post-rebase audit overlap cleared by deterministic verification"),
"text",
expect.any(String),
"merger",
);
});
it("keeps blocking overlap-only post-rebase findings when neither ref tree is verified (FN-4344)", async () => {
setupRebaseRouteExecSync({
landedcommit002: "tree-unverified-a",
"fusion/fn-050": "tree-unverified-b",
});
mockedAuditSquashMerge.mockResolvedValue({
strategy: "rebase",
rangeBaseSha: "basehead123",
rangeHeadSha: "landedcommit002",
parentSha: "basehead123",
auditTargetLabel: "basehead123..landedcommit002",
lookback: 30,
branchSubjects: ["fix: substantive one", "feat: substantive two"],
recentMainSubjects: [],
duplicateSubjects: [],
touchedFiles: ["src/feature-a.ts"],
touchedFileOverlaps: [{
type: "touched-file-overlap",
file: "src/feature-a.ts",
recentMainCommits: [{ sha: "abc1234", subject: "fix: overlap" }],
}],
findings: [{
type: "touched-file-overlap",
file: "src/feature-a.ts",
recentMainCommits: [{ sha: "abc1234", subject: "fix: overlap" }],
}],
issueCount: 1,
clean: false,
});
mockedExistsSync.mockReturnValue(false);
const store = createAuditStore({ postMergeAuditMode: "block", testCommand: undefined, buildCommand: undefined }, { branch: "fusion/fn-050" });
vi.mocked(store.getVerificationCacheHit).mockReturnValue(null);
await expect(aiMergeTask(store, "/tmp/root", "FN-050")).rejects.toThrow(/post-rebase range audit blocked auto-completion/);
expect(store.moveTask).not.toHaveBeenCalledWith("FN-050", "done");
expect(store.updateTask).toHaveBeenCalledWith("FN-050", { status: null });
});
it("continues to branch-tip lookup when audit ref tree is unresolvable and still short-circuits on cache hit (FN-4344)", async () => {
const auditTreeError = new Error("fatal: bad revision 'landedcommit002^{tree}'");
setupRebaseRouteExecSync({
landedcommit002: auditTreeError,
"fusion/fn-050": "tree-verified",
});
mockedAuditSquashMerge.mockResolvedValue({
strategy: "rebase",
rangeBaseSha: "basehead123",
rangeHeadSha: "landedcommit002",
parentSha: "basehead123",
auditTargetLabel: "basehead123..landedcommit002",
lookback: 30,
branchSubjects: ["fix: substantive one", "feat: substantive two"],
recentMainSubjects: [],
duplicateSubjects: [],
touchedFiles: ["src/feature-a.ts"],
touchedFileOverlaps: [{
type: "touched-file-overlap",
file: "src/feature-a.ts",
recentMainCommits: [{ sha: "abc1234", subject: "fix: overlap" }],
}],
findings: [{
type: "touched-file-overlap",
file: "src/feature-a.ts",
recentMainCommits: [{ sha: "abc1234", subject: "fix: overlap" }],
}],
issueCount: 1,
clean: false,
});
mockedExistsSync.mockReturnValue(false);
const store = createAuditStore({ postMergeAuditMode: "block", testCommand: undefined, buildCommand: undefined }, { branch: "fusion/fn-050" });
vi.mocked(store.getVerificationCacheHit).mockImplementation((treeSha: string) => (
treeSha === "tree-verified" ? { recordedAt: "2026-05-13T00:00:00.000Z", taskId: "FN-049" } : null
));
const warnSpy = vi.spyOn(mergerLog, "warn");
await aiMergeTask(store, "/tmp/root", "FN-050");
expect(store.moveTask).toHaveBeenCalledWith("FN-050", "done");
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("could not resolve post-merge audit verification tree for ref landedcommit002"));
warnSpy.mockRestore();
});
it("honors the per-task always-squash override", async () => {
setupAutoResolvedMergeExecSync();
const store = createAuditStore({}, { prompt: "**Direct Merge Commit Strategy:** always-squash" });