FN-8871: seed complete merge-lane state in coordinator tests

Ensure group-merge coordinator fakes initialize production merge-lane state.

- Add a reusable fixture for ProjectEngine merge-lane fields.
- Use the fixture in the group-merge routing integration test.
- Include capacity and PR-retry state required by the production drain.

Files changed:
 .../_project-engine-merge-lane-fixture.ts          | 62 ++++++++++++++++++++++
 .../src/__tests__/group-merge-coordinator.test.ts  | 15 +++---
 2 files changed, 69 insertions(+), 8 deletions(-)

Fusion-Task-Id: FN-8871

Fusion-Task-Lineage: 9bde0439-fa88-481b-a7f3-9feb7e663883

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-08-08 23:24:23 -07:00
parent fb125b6f5e
commit 8ee6eff9cd
2 changed files with 69 additions and 8 deletions

View File

@@ -0,0 +1,62 @@
type MergeLaneState = {
mergeQueue: string[];
mergeActive: Set<string>;
capacityDeferredMergeTaskIds: Set<string>;
capacityDeferredMergeReasons: Map<string, string>;
capacityDeferredMerges: Map<string, unknown>;
coordinatorAdmittedMergeTaskIds: Set<string>;
pausedReviewTaskIds: Set<string>;
mergeRunning: boolean;
mergeRunningSince: number;
activeMergeSession: { dispose(): void } | null;
activeMergeTaskId: string | null;
activeMergeStartedAtMs: number | null;
mergeBodyInFlight: Promise<unknown> | null;
mergeAbortController: AbortController | null;
mergeRetryTimer: ReturnType<typeof setTimeout> | null;
prMergeRetryTimers: Map<string, ReturnType<typeof setTimeout>>;
workspaceBusyReenqueues: Map<string, number>;
workspaceBusyReenqueueTimers: Set<ReturnType<typeof setTimeout>>;
manualMergeResolvers: Map<string, unknown[]>;
shuttingDown: boolean;
startupGeneration: number;
started: boolean;
};
/**
* FNXC:MergeQueue 2026-08-09-06:22:
* Object.create(ProjectEngine.prototype) runs no class field initializers, so a prototype-only
* merge fake starts with every merge-lane field undefined. FN-8871 requires this fixture to include
* capacity and PR-retry merge state, preventing production drain additions from drifting test fakes.
*/
export function seedMergeLaneState<T extends object>(
engine: T,
overrides: Partial<MergeLaneState> = {},
): T & MergeLaneState {
const defaults: MergeLaneState = {
mergeQueue: [],
mergeActive: new Set(),
capacityDeferredMergeTaskIds: new Set(),
capacityDeferredMergeReasons: new Map(),
capacityDeferredMerges: new Map(),
coordinatorAdmittedMergeTaskIds: new Set(),
pausedReviewTaskIds: new Set(),
mergeRunning: false,
mergeRunningSince: 0,
activeMergeSession: null,
activeMergeTaskId: null,
activeMergeStartedAtMs: null,
mergeBodyInFlight: null,
mergeAbortController: null,
mergeRetryTimer: null,
prMergeRetryTimers: new Map(),
workspaceBusyReenqueues: new Map(),
workspaceBusyReenqueueTimers: new Set(),
manualMergeResolvers: new Map(),
shuttingDown: false,
startupGeneration: 0,
started: true,
};
return Object.assign(engine, defaults, overrides);
}

View File

@@ -26,6 +26,7 @@ import {
} from "../merge/group-merge-coordinator.js";
import { ProjectEngine } from "../project-engine.js";
import { runAiMerge } from "../merge/merger-ai.js";
import { seedMergeLaneState } from "./_project-engine-merge-lane-fixture.js";
const dirs: string[] = [];
@@ -1490,14 +1491,12 @@ describe("resolveBranchGroupMergeRouting", () => {
getSessionStats: vi.fn(() => ({ tokens: { input: 1, output: 1 } })),
},
}));
engine.manualMergeResolvers = new Map();
engine.mergeActive = new Set();
engine.mergeQueue = [];
engine.capacityDeferredMergeTaskIds = new Set();
engine.capacityDeferredMerges = new Map();
engine.coordinatorAdmittedMergeTaskIds = new Set();
engine.started = true;
engine.shuttingDown = false;
/*
FNXC:SharedBranchMemberHold 2026-08-09-05:22:
FN-8811's release half runs the production drain, so this prototype fake must carry complete
merge-lane state rather than only the fields the test happened to seed when it was written.
*/
seedMergeLaneState(engine);
const released = await ProjectEngine.prototype.onMerge.call(engine, "FN-3324");
createResolvedAgentSessionMock.mockReset();