diff --git a/packages/engine/src/__tests__/group-merge-coordinator.test.ts b/packages/engine/src/__tests__/group-merge-coordinator.test.ts index c11ca4f111..d1102c86ad 100644 --- a/packages/engine/src/__tests__/group-merge-coordinator.test.ts +++ b/packages/engine/src/__tests__/group-merge-coordinator.test.ts @@ -1318,8 +1318,14 @@ function createPostReviewStore(task: Record, branchGroup: Record ({ global: {}, project: settings })), + emitUsageEvent: vi.fn(async () => true), listTasksByBranchGroup: vi.fn(async () => (branchGroup ? [task] : [])), getBranchGroup: vi.fn(() => branchGroup), updateTask: vi.fn(async (_id: string, patch: Record) => Object.assign(task, patch)), @@ -1477,6 +1483,11 @@ describe("resolveBranchGroupMergeRouting", () => { expect(held).toMatchObject({ merged: false, noOp: true }); expect(blockedMerge).not.toHaveBeenCalled(); expect(git(repo, "git rev-parse main")).toBe(mainBefore); + /* + FNXC:BranchGroupAutoMergeGate 2026-08-09-22:51: + The expected fatal-path stderr is the proof that the automatic hold did not land this member; + it is not a missing fixture path. + */ expect(() => git(repo, "git show mission/M-8811:user-hold-feature.txt")).toThrow(); let mergeAttempts = 0; @@ -1539,6 +1550,16 @@ describe("resolveBranchGroupMergeRouting", () => { } expect(offendingWarnings, "merge drain emitted missing-store-seam warnings").toEqual([]); + /* + FNXC:BranchGroupAutoMergeGate 2026-08-09-22:51: + An empty warning list is insufficient when a future path skips telemetry entirely. Assert the + production merger lane exercised the fake-store seam during the explicit release. + */ + expect(store.emitUsageEvent).toHaveBeenCalledWith(expect.objectContaining({ + kind: "session_start", + category: "agent-session", + meta: expect.objectContaining({ lane: "merger" }), + })); expect(released.merged).toBe(true); expect(store.listTasksByBranchGroup).toHaveBeenCalledWith("BG-user-hold"); expect(mergeAttempts).toBe(1); diff --git a/packages/engine/src/__tests__/merger-ai-cleanup.test.ts b/packages/engine/src/__tests__/merger-ai-cleanup.test.ts index dd3e671807..8b3ca959eb 100644 --- a/packages/engine/src/__tests__/merger-ai-cleanup.test.ts +++ b/packages/engine/src/__tests__/merger-ai-cleanup.test.ts @@ -111,6 +111,7 @@ function makeStore(taskId = "FN-1") { emit: vi.fn(), logEntry: vi.fn(async (_id: string, message: string) => { logs.push(message); }), appendAgentLog: vi.fn(async (_id: string, message: string) => { logs.push(message); }), + emitUsageEvent: vi.fn(async () => true), recordRunAuditEvent: vi.fn(async (event: any) => { audits.push(event); }), }; return { store, audits, logs }; diff --git a/packages/engine/src/__tests__/merger-ai-dependency-install.slow.test.ts b/packages/engine/src/__tests__/merger-ai-dependency-install.slow.test.ts index b3a8f4f4e4..3f8c1b857c 100644 --- a/packages/engine/src/__tests__/merger-ai-dependency-install.slow.test.ts +++ b/packages/engine/src/__tests__/merger-ai-dependency-install.slow.test.ts @@ -54,6 +54,7 @@ function makeStore(settingsOverrides: Record = {}) { emit: vi.fn(), logEntry: vi.fn(async () => undefined), appendAgentLog: vi.fn(async () => undefined), + emitUsageEvent: vi.fn(async () => true), }; return store; } diff --git a/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts b/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts index d7c2fd4fc2..c1cf312658 100644 --- a/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts +++ b/packages/engine/src/__tests__/merger-ai-push-after-merge.test.ts @@ -113,6 +113,7 @@ function makeStore(settingsOverrides: Record = {}) { emit: vi.fn(), logEntry: vi.fn(async (_id: string, message: string, action?: string) => { logs.push({ message, action }); }), appendAgentLog: vi.fn(async (_id: string, message: string) => { logs.push({ message }); }), + emitUsageEvent: vi.fn(async () => true), getBranchGroup: vi.fn(() => null), recordRunAuditEvent: vi.fn(), }; diff --git a/packages/engine/src/__tests__/merger-ai-renamed-columns.test.ts b/packages/engine/src/__tests__/merger-ai-renamed-columns.test.ts index fbcd94b59d..ae4f7b706b 100644 --- a/packages/engine/src/__tests__/merger-ai-renamed-columns.test.ts +++ b/packages/engine/src/__tests__/merger-ai-renamed-columns.test.ts @@ -102,6 +102,12 @@ function storeWith(current: Task, ir: WorkflowIr | undefined): TaskStore { updateTask: vi.fn(async () => current), moveTask: vi.fn(async () => current), logEntry: vi.fn(async () => undefined), + /* + FNXC:MergeQueue 2026-08-09-22:51: + A fake store that drives runAiMerge into the merger AI lane must expose emitUsageEvent because + session telemetry is defensive in production. Stores rejected at the workspace guard do not reach it. + */ + emitUsageEvent: vi.fn(async () => true), recordRunAuditEvent: vi.fn(async () => undefined), getTaskWorkflowSelection: vi.fn(() => selection), getTaskWorkflowSelectionAsync: vi.fn(async () => selection), diff --git a/packages/engine/src/__tests__/reliability-interactions/ai-merge-cleanup-enoent-idempotent.test.ts b/packages/engine/src/__tests__/reliability-interactions/ai-merge-cleanup-enoent-idempotent.test.ts index fd04dff8eb..78bfe7b75c 100644 --- a/packages/engine/src/__tests__/reliability-interactions/ai-merge-cleanup-enoent-idempotent.test.ts +++ b/packages/engine/src/__tests__/reliability-interactions/ai-merge-cleanup-enoent-idempotent.test.ts @@ -63,6 +63,7 @@ function makeStore(taskId: string, branch: string) { emit: vi.fn(), logEntry: vi.fn(async (_id: string, message: string) => { logs.push(message); }), appendAgentLog: vi.fn(async (_id: string, message: string) => { logs.push(message); }), + emitUsageEvent: vi.fn(async () => true), recordRunAuditEvent: vi.fn(async (event: any) => { audits.push(event); }), }; return { store, task, audits, logs };