Files
fusion/packages/engine/src/__tests__/merger-layer3-scope-partition.test.ts
Fusion (runfusion.ai) 8072554650 feat(FN-4956): complete Step 2-3 — scope-partition layer3 conflicts
Fusion-Task-Id: FN-4956
Fusion-Task-Lineage: 7105cd5e-27f4-4e84-b2ae-e811a183803f
2026-05-18 01:30:15 -07:00

150 lines
4.9 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import { createMockStore, mockedExecSync } from "./merger-test-helpers.js";
import { applyLayer3ConflictScopePartition, partitionConflictsByFileScope } from "../merger.js";
describe("partitionConflictsByFileScope", () => {
it("treats empty declared scope as no enforcement", () => {
const result = partitionConflictsByFileScope({
conflictFiles: ["AGENTS.md", "packages/core/src/store.ts"],
declaredScope: [],
});
expect(result).toEqual({
inScope: ["AGENTS.md", "packages/core/src/store.ts"],
outOfScope: [],
});
});
it("returns all in-scope files", () => {
const result = partitionConflictsByFileScope({
conflictFiles: ["packages/engine/src/merger.ts", "packages/engine/src/store.ts"],
declaredScope: ["packages/engine/src/**"],
});
expect(result).toEqual({
inScope: ["packages/engine/src/merger.ts", "packages/engine/src/store.ts"],
outOfScope: [],
});
});
it("returns all out-of-scope files", () => {
const result = partitionConflictsByFileScope({
conflictFiles: ["AGENTS.md", "packages/core/src/store.ts"],
declaredScope: ["packages/desktop/src/**"],
});
expect(result).toEqual({
inScope: [],
outOfScope: ["AGENTS.md", "packages/core/src/store.ts"],
});
});
it("partitions mixed files", () => {
const result = partitionConflictsByFileScope({
conflictFiles: ["packages/desktop/src/foo.ts", "packages/core/src/store.ts"],
declaredScope: ["packages/desktop/src/**"],
});
expect(result).toEqual({
inScope: ["packages/desktop/src/foo.ts"],
outOfScope: ["packages/core/src/store.ts"],
});
});
it("matches glob scope entries", () => {
const result = partitionConflictsByFileScope({
conflictFiles: ["packages/core/src/store.ts", "packages/core/test/store.test.ts"],
declaredScope: ["packages/core/src/**"],
});
expect(result).toEqual({
inScope: ["packages/core/src/store.ts"],
outOfScope: ["packages/core/test/store.test.ts"],
});
});
it("supports .changeset patterns", () => {
const result = partitionConflictsByFileScope({
conflictFiles: [".changeset/fn-4956.md", "AGENTS.md"],
declaredScope: [".changeset/*"],
});
expect(result).toEqual({
inScope: [".changeset/fn-4956.md"],
outOfScope: ["AGENTS.md"],
});
});
});
describe("applyLayer3ConflictScopePartition", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("resolves out-of-scope conflicts to ours and emits skip audit", async () => {
const store = createMockStore() as any;
store.parseFileScopeFromPrompt = vi.fn().mockResolvedValue(["packages/desktop/src/**"]);
const task = await store.getTask("FN-050");
const gitCalls: string[] = [];
mockedExecSync.mockImplementation((cmd: any) => {
const c = String(cmd);
gitCalls.push(c);
if (c.includes("git diff --cached --name-only")) {
return "packages/desktop/src/foo.ts\n";
}
return "";
});
const audit = { git: vi.fn().mockResolvedValue(undefined) } as any;
const result = await applyLayer3ConflictScopePartition({
store,
task,
taskId: "FN-050",
rootDir: "/tmp/root",
branch: "fusion/fn-050",
conflictFiles: ["packages/desktop/src/foo.ts", "AGENTS.md"],
auditor: audit,
});
expect(result.inScopeConflicts).toEqual(["packages/desktop/src/foo.ts"]);
expect(result.skippedFiles).toEqual(["AGENTS.md"]);
expect(gitCalls.some((call) => call.includes("git checkout --ours -- AGENTS.md"))).toBe(true);
expect(audit.git).toHaveBeenCalledWith(expect.objectContaining({
type: "merge:layer3:foreign-file-skipped",
target: "fusion/fn-050",
metadata: expect.objectContaining({
taskId: "FN-050",
skippedFiles: ["AGENTS.md"],
inScopeCount: 1,
viaScopeOverride: false,
}),
}));
});
it("emits scope override bypass audit and skips partition", async () => {
const store = createMockStore({ scopeOverride: true, scopeOverrideReason: "hotfix" }) as any;
store.parseFileScopeFromPrompt = vi.fn().mockResolvedValue(["packages/desktop/src/**"]);
const task = await store.getTask("FN-050");
const audit = { git: vi.fn().mockResolvedValue(undefined) } as any;
const result = await applyLayer3ConflictScopePartition({
store,
task,
taskId: "FN-050",
rootDir: "/tmp/root",
branch: "fusion/fn-050",
conflictFiles: ["packages/desktop/src/foo.ts", "AGENTS.md"],
auditor: audit,
});
expect(result.inScopeConflicts).toEqual(["packages/desktop/src/foo.ts", "AGENTS.md"]);
expect(result.skippedFiles).toEqual([]);
expect(audit.git).toHaveBeenCalledWith(expect.objectContaining({
type: "merge:layer3:scope-override-bypass",
metadata: expect.objectContaining({ viaScopeOverride: true }),
}));
});
});