FN-6326: quarantine deferred-hook title summarization test
Quarantine the flaky deferred-hook title summarization coverage while preserving focused store-create coverage. - Extract the deferred task-created hook summarization test into its own file. - Exclude the extracted test file from the core Vitest suite. - Record the flake investigation and quarantine rationale in the test quarantine ledger. Files changed: .../store-create-summarize-deferred-hook.test.ts | 67 ++++++++++++++++++++++ packages/core/src/__tests__/store-create.test.ts | 44 -------------- packages/core/vitest.config.ts | 1 + scripts/lib/test-quarantine.json | 5 ++ 4 files changed, 73 insertions(+), 44 deletions(-) Fusion-Task-Id: FN-6326 Fusion-Task-Lineage: a37189b3-b88b-483f-b2bf-471fde806b35
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
|
||||
import { setCreateFnAgent } from "../ai-engine-loader.js";
|
||||
import { TaskStore } from "../store.js";
|
||||
import { setTaskCreatedHook } from "../task-creation-hooks.js";
|
||||
import { createTaskStoreTestHarness } from "./store-test-helpers.js";
|
||||
|
||||
describe("TaskStore createTask title summarization deferred hook", () => {
|
||||
const harness = createTaskStoreTestHarness();
|
||||
let store: TaskStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
await harness.beforeEach();
|
||||
store = harness.store();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
setTaskCreatedHook(undefined);
|
||||
setCreateFnAgent(undefined);
|
||||
await harness.afterEach();
|
||||
});
|
||||
|
||||
it("defers the task-created hook until store-managed summarize completes", async () => {
|
||||
const longDescription = "a".repeat(201);
|
||||
let releasePrompt!: () => void;
|
||||
const promptStarted = vi.fn();
|
||||
const promptDone = new Promise<void>((resolve) => {
|
||||
releasePrompt = resolve;
|
||||
});
|
||||
setCreateFnAgent(vi.fn(async () => ({
|
||||
session: {
|
||||
prompt: vi.fn(async () => {
|
||||
promptStarted();
|
||||
await promptDone;
|
||||
}),
|
||||
state: { messages: [{ role: "assistant", content: "Deferred Hook Title" }] },
|
||||
},
|
||||
})));
|
||||
const hookSpy = vi.fn();
|
||||
setTaskCreatedHook(hookSpy);
|
||||
|
||||
const task = await store.createTask(
|
||||
{ description: longDescription, summarize: true },
|
||||
{
|
||||
settings: {
|
||||
autoSummarizeTitles: false,
|
||||
titleSummarizerProvider: "mock",
|
||||
titleSummarizerModelId: "title-model",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(promptStarted).toHaveBeenCalled());
|
||||
expect(hookSpy).not.toHaveBeenCalled();
|
||||
|
||||
releasePrompt();
|
||||
await vi.waitFor(() => {
|
||||
expect(hookSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: task.id,
|
||||
title: "Deferred Hook Title",
|
||||
}),
|
||||
store,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -501,50 +501,6 @@ describe("TaskStore", () => {
|
||||
expect(promptSpy).toHaveBeenCalledWith(expect.stringContaining(longDescription));
|
||||
});
|
||||
|
||||
it("defers the task-created hook until store-managed summarize completes", async () => {
|
||||
const longDescription = "a".repeat(201);
|
||||
let releasePrompt!: () => void;
|
||||
const promptStarted = vi.fn();
|
||||
const promptDone = new Promise<void>((resolve) => {
|
||||
releasePrompt = resolve;
|
||||
});
|
||||
setCreateFnAgent(vi.fn(async () => ({
|
||||
session: {
|
||||
prompt: vi.fn(async () => {
|
||||
promptStarted();
|
||||
await promptDone;
|
||||
}),
|
||||
state: { messages: [{ role: "assistant", content: "Deferred Hook Title" }] },
|
||||
},
|
||||
})));
|
||||
const hookSpy = vi.fn();
|
||||
setTaskCreatedHook(hookSpy);
|
||||
|
||||
const task = await store.createTask(
|
||||
{ description: longDescription, summarize: true },
|
||||
{
|
||||
settings: {
|
||||
autoSummarizeTitles: false,
|
||||
titleSummarizerProvider: "mock",
|
||||
titleSummarizerModelId: "title-model",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(promptStarted).toHaveBeenCalled());
|
||||
expect(hookSpy).not.toHaveBeenCalled();
|
||||
|
||||
releasePrompt();
|
||||
await vi.waitFor(() => {
|
||||
expect(hookSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: task.id,
|
||||
title: "Deferred Hook Title",
|
||||
}),
|
||||
store,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("should ignore malformed confirmation-prose generated titles", async () => {
|
||||
const mockOnSummarize = vi
|
||||
|
||||
@@ -18,6 +18,7 @@ export default defineConfig({
|
||||
"src/__tests__/db.test.ts",
|
||||
"src/__tests__/soft-delete-tasks.test.ts",
|
||||
"src/__tests__/store-get-task-columns.test.ts",
|
||||
"src/__tests__/store-create-summarize-deferred-hook.test.ts",
|
||||
"src/__tests__/task-dependency-mutation.test.ts",
|
||||
"src/__tests__/task-node-override.test.ts",
|
||||
],
|
||||
|
||||
@@ -55,6 +55,11 @@
|
||||
"file": "packages/core/src/__tests__/db.test.ts",
|
||||
"reason": "Flake observed during FN-6299 verification: broad `pnpm --filter @fusion/core test` timed out in `Database.recoverIfCorrupt startup guard > rebuilds a malformed database and preserves the corrupt original` after 15s; earlier `pnpm test` attempt SIGTERM'd the core package and leaked a fusion-test-workers temp dir. Follow-up FN-6334.",
|
||||
"quarantinedAt": "2026-06-12"
|
||||
},
|
||||
{
|
||||
"file": "packages/core/src/__tests__/store-create-summarize-deferred-hook.test.ts",
|
||||
"reason": "Flake observed during FN-6320 final broad `pnpm test`: `store-create.test.ts > TaskStore > createTask with title summarization > defers the task-created hook until store-managed summarize completes` timed out because the registered task-created hook had zero calls after the gated store-managed summarizer prompt was released. FN-6326 cross-check: the test passed twice standalone after FN-6313, and product code in `TaskStore.createTask` suppresses the synchronous hook only while `hasPendingSummarization` is true, then unconditionally refreshes the task and calls `invokeTaskCreatedHook(latestTask)` after `onSummarize` settles across success/null/throw branches. The broad/package load failure was therefore classified as suite-load/harness sensitivity rather than a confirmed product defect; the single flaky `it` was extracted so the rest of `store-create.test.ts` remains covered.",
|
||||
"quarantinedAt": "2026-06-12"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user