diff --git a/packages/engine/src/__tests__/self-healing-db-corruption.test.ts b/packages/engine/src/__tests__/self-healing-db-corruption.test.ts index bee1be4ac5..8d42d6d549 100644 --- a/packages/engine/src/__tests__/self-healing-db-corruption.test.ts +++ b/packages/engine/src/__tests__/self-healing-db-corruption.test.ts @@ -36,6 +36,25 @@ function createMockStore(overrides: Record = {}): TaskStore & E isRunning: false, }), recordRunAuditEvent: vi.fn().mockResolvedValue(undefined), + /* + FNXC:TestInfrastructure 2026-07-29-16:45: + surfaceDbCorruption REFRESHES health before reading the snapshot + (FNXC:IncompletePgPorts 2026-07-26-20:45 — so PG connectivity is re-checked + rather than trusting an always-healthy sentinel). This fake carried neither + refresher, so the async branch fell through to `this.store.refreshDatabaseHealth()` + — undefined — and the step threw before reaching dispatch. Every corruption + assertion in this file was then measuring zero calls against a step that had + already aborted. + + Both are NO-OPS on purpose: production ignores the refresh return value and + reads `this.store.getDatabaseHealth()` immediately after, so the snapshot mock + stays the single source of truth. Delegating them to getDatabaseHealth instead + would consume a SECOND value per pass from the tests that queue + mockReturnValueOnce sequences (one per runMaintenance), silently shifting the + corruption -> clear -> corruption ordering they assert. + */ + refreshDatabaseHealth: vi.fn(), + refreshDatabaseHealthAsync: vi.fn(async () => undefined), ...overrides, }) as unknown as TaskStore & EventEmitter; } diff --git a/packages/engine/src/__tests__/self-healing.test.ts b/packages/engine/src/__tests__/self-healing.test.ts index 1b3c336679..ffc508d1c8 100644 --- a/packages/engine/src/__tests__/self-healing.test.ts +++ b/packages/engine/src/__tests__/self-healing.test.ts @@ -2328,7 +2328,8 @@ describe("SelfHealingManager", () => { expect(result).toBe(1); expect(store.archiveTaskAndCleanup).toHaveBeenCalledWith("FN-030"); expect(store.archiveTaskAndCleanup).not.toHaveBeenCalledWith("FN-031"); - expect(getSelfHealingLogger().log).toHaveBeenCalledWith( + // self-healing.ts:2747 emits this at DEBUG level, not log. + expect(getSelfHealingLogger().debug).toHaveBeenCalledWith( "auto-archive: archived FN-030 (age 31d, threshold 30d)", ); }); diff --git a/packages/engine/src/__tests__/worktree-pool.test.ts b/packages/engine/src/__tests__/worktree-pool.test.ts index 968fdfe3d2..8c79be90e5 100644 --- a/packages/engine/src/__tests__/worktree-pool.test.ts +++ b/packages/engine/src/__tests__/worktree-pool.test.ts @@ -93,9 +93,22 @@ let warnSpy: ReturnType; beforeEach(() => { errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); + /* + FNXC:TestInfrastructure 2026-07-29-17:05: + worktree-pool logs its checkout-failure at DEBUG level, and createLogger's debug + writes to console.error like the rest — but debug is GATED on FUSION_DEBUG + (logger.ts:43), which is unset under vitest. So the line was never emitted and + the two checkout-failure cases below measured zero calls. One of them is even + named "logs checkout -- failure at debug level" while asserting a channel debug + could not reach without this flag. Enabling it is what makes those assertions + real; re-pointing them at another channel would only describe whatever the code + happened to do. Deleted in afterEach so the flag cannot leak into sibling files. + */ + process.env.FUSION_DEBUG = "worktree-pool"; }); afterEach(() => { + delete process.env.FUSION_DEBUG; errorSpy.mockRestore(); warnSpy.mockRestore(); });