FN-8093: rescue dist-barrel coverage
Restore the isolated built-core barrel regression guard to the default CLI test lane. - Hoist recompilation and PostgreSQL fixture setup outside timed test bodies. - Inject the fixture store into the dynamic extension and retain text-budget assertions. - Skip cleanly per test when a transitive dist artifact is unavailable. - Remove the matching CLI quarantine exclusion and ledger entry. Files changed: .../src/__tests__/extension-dist-barrel.test.ts | 234 +++++++++++---------- packages/cli/vitest.config.ts | 8 +- scripts/lib/test-quarantine.json | 5 - 3 files changed, 121 insertions(+), 126 deletions(-) Fusion-Task-Id: FN-8093 Fusion-Task-Lineage: 352b3675-0579-43bc-acd9-6a11919ed646 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { mkdtemp, mkdir, rm } from "node:fs/promises";
|
||||
import { describe, it, expect, vi, beforeAll, afterAll } from "vitest";
|
||||
import { mkdir, rm } from "node:fs/promises";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { setTimeout as delay } from "node:timers/promises";
|
||||
|
||||
@@ -25,9 +24,9 @@ vi.mock("../commands/task.js", () => ({
|
||||
runTaskPlan: vi.fn(),
|
||||
}));
|
||||
|
||||
import kbExtension, { closeCachedStores } from "../extension.js";
|
||||
import { TaskStore, MAX_TASK_LIST_TEXT_CHARS } from "@fusion/core";
|
||||
import { hasBuiltCoreDistBarrel } from "@fusion/test-utils";
|
||||
import { createTaskStoreForTest, pgDescribe, type PgTestHarness } from "../../../core/src/__test-utils__/pg-test-harness.js";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
@@ -101,130 +100,135 @@ async function removeDirWithRetries(path: string) {
|
||||
}
|
||||
}
|
||||
|
||||
describe("fn pi extension (dist-barrel recompilation slice)", () => {
|
||||
let tmpDir: string;
|
||||
let api: ReturnType<typeof createMockAPI>;
|
||||
let openStores: TaskStore[] = [];
|
||||
pgDescribe.skipIf(!hasBuiltCoreDistBarrel(resolve(__dirname, "../../../core/dist")))(
|
||||
"fn pi extension (dist-barrel recompilation slice)",
|
||||
() => {
|
||||
let tmpDir: string;
|
||||
let fixtureHarness: PgTestHarness | undefined;
|
||||
let fixtureStore: TaskStore | undefined;
|
||||
let listTool: RegisteredTool;
|
||||
let closeRuntimeCachedStores: (() => Promise<void>) | undefined;
|
||||
let runtimeDistArtifactUnavailable = false;
|
||||
|
||||
function createStore(): TaskStore {
|
||||
const store = new TaskStore(tmpDir);
|
||||
openStores.push(store);
|
||||
return store;
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await mkdtemp(join(tmpdir(), "kb-ext-distbarrel-"));
|
||||
await mkdir(join(tmpDir, ".fusion"), { recursive: true });
|
||||
api = createMockAPI();
|
||||
kbExtension(api);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
for (const store of openStores.splice(0)) {
|
||||
try {
|
||||
await store.close();
|
||||
} catch {
|
||||
// Best effort: close all real stores before removing fixture roots.
|
||||
}
|
||||
}
|
||||
await closeCachedStores();
|
||||
await removeDirWithRetries(tmpDir);
|
||||
});
|
||||
|
||||
/*
|
||||
FNXC:TaskListOutput 2026-06-17-02:37:
|
||||
FN-6535 reproduces the heartbeat failure at the actual CLI tool surface while forcing @fusion/core to resolve through the built dist barrel. The normal CLI suite aliases @fusion/core to source, so this targeted mock is the regression guard for stale exports.import dist artifacts.
|
||||
|
||||
FNXC:CoreTests 2026-06-18-01:35:
|
||||
FN-6627 aligns the skip gate with every built @fusion/core dist artifact this runtime-dist mock loads, so a partial stale dist skips cleanly while a complete dist still exercises the heartbeat fn_task_list surface.
|
||||
|
||||
FNXC:CliTests 2026-06-19-11:17:
|
||||
FN-6734 keeps this guard in the default 5s lane by preserving the runtime-dist truncation invariant with fewer fixture writes instead of appeasing timeouts or reducing workers.
|
||||
|
||||
FNXC:CliTests 2026-06-19-13:16:
|
||||
The full CLI affected lane runs this file beside many module-mocking suites; verify the built barrel is importable in the executing worker before installing the mock, then skip like the partial-dist gate if a concurrent lane observes stale dist artifacts.
|
||||
|
||||
FNXC:CliTests 2026-07-04-13:50:
|
||||
FN-7530 moved this case out of extension.test.ts unchanged (same assertions, same dist-resolution invariant, same skip gate). The sibling source-@fusion/core test "bounds large column-filtered listings as a single plain-text block" in extension.test.ts covers the identical truncation invariant against source; this test's only marginal coverage is that the built dist barrel resolves/executes identically, which is why it stays a dedicated, narrowly-scoped file rather than being deleted.
|
||||
*/
|
||||
it.skipIf(!hasBuiltCoreDistBarrel(resolve(__dirname, "../../../core/dist")))(
|
||||
"executes with @fusion/core resolved through the built dist barrel",
|
||||
async () => {
|
||||
const distCoreIndex = resolve(__dirname, "../../../core/dist/index.js");
|
||||
|
||||
const store = createStore();
|
||||
await store.init();
|
||||
try {
|
||||
const first = await store.createTask({
|
||||
title: `Runtime-dist todo task 001 ${"x".repeat(300)}`,
|
||||
description: "Runtime-dist todo task 001",
|
||||
beforeAll(async () => {
|
||||
fixtureHarness = await createTaskStoreForTest({ prefix: "fn_ext_dist_barrel" });
|
||||
tmpDir = fixtureHarness.rootDir;
|
||||
await mkdir(join(tmpDir, ".fusion"), { recursive: true });
|
||||
fixtureStore = fixtureHarness.store;
|
||||
await fixtureStore.updateSettings({ taskPrefix: "FN" });
|
||||
const first = await fixtureStore.createTask({
|
||||
title: `Runtime-dist todo task 001 ${"x".repeat(300)}`,
|
||||
description: "Runtime-dist todo task 001",
|
||||
column: "todo",
|
||||
});
|
||||
for (let i = 2; i <= 20; i += 1) {
|
||||
await fixtureStore.createTask({
|
||||
title: `Runtime-dist todo task ${String(i).padStart(3, "0")} ${"x".repeat(300)}`,
|
||||
description: `Runtime-dist todo task ${String(i).padStart(3, "0")}`,
|
||||
column: "todo",
|
||||
dependencies: [first.id],
|
||||
});
|
||||
for (let i = 2; i <= 20; i += 1) {
|
||||
await store.createTask({
|
||||
title: `Runtime-dist todo task ${String(i).padStart(3, "0")} ${"x".repeat(300)}`,
|
||||
description: `Runtime-dist todo task ${String(i).padStart(3, "0")}`,
|
||||
column: "todo",
|
||||
dependencies: [first.id],
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await store.close();
|
||||
}
|
||||
|
||||
vi.resetModules();
|
||||
const distCoreUrl = pathToFileURL(distCoreIndex).href;
|
||||
let distCoreModule: typeof import("@fusion/core");
|
||||
/*
|
||||
FNXC:CliTests 2026-07-16-06:27:
|
||||
FN-8093 rescues the dist-barrel guard by doing its entire CPU-bound recompilation unit and PostgreSQL fixture seeding once in beforeAll, outside each default-5s test body. The dynamic dist extension cannot bootstrap its PostgreSQL backend because its dist migration artifacts are absent, so inject this external fixture store through that module instance's own cache API. Its cache cleanup does not own external stores; afterAll closes the dynamic cache, then this store, before removing the temp root.
|
||||
|
||||
FNXC:CliTests 2026-07-16-06:27:
|
||||
The synchronous barrel predicate covers its direct artifacts but cannot prove every transitive runtime import exists. beforeAll receives no Vitest test context, so record ERR_MODULE_NOT_FOUND here and have each test use its own context to skip cleanly instead of calling a nonexistent suite-hook ctx.skip().
|
||||
*/
|
||||
try {
|
||||
distCoreModule = await vi.importActual<typeof import("@fusion/core")>(distCoreUrl);
|
||||
vi.resetModules();
|
||||
const distCoreIndex = resolve(__dirname, "../../../core/dist/index.js");
|
||||
const distCoreUrl = pathToFileURL(distCoreIndex).href;
|
||||
const distCoreModule = await vi.importActual<typeof import("@fusion/core")>(distCoreUrl);
|
||||
vi.doMock("@fusion/core", () => distCoreModule);
|
||||
|
||||
const runtimeModule = await import("../extension.js?fn6535-runtime-core-dist");
|
||||
closeRuntimeCachedStores = runtimeModule.closeCachedStores;
|
||||
const runtimeApi = createMockAPI();
|
||||
runtimeModule.default(runtimeApi);
|
||||
runtimeModule.__setCachedStoreForTesting(resolve(tmpDir), fixtureStore);
|
||||
listTool = runtimeApi.tools.get("fn_task_list")!;
|
||||
} catch (error) {
|
||||
const code = error instanceof Error && "code" in error ? (error as Error & { code?: string }).code : undefined;
|
||||
const code = error instanceof Error && "code" in error
|
||||
? (error as Error & { code?: string }).code
|
||||
: undefined;
|
||||
if (code === "ERR_MODULE_NOT_FOUND") {
|
||||
runtimeDistArtifactUnavailable = true;
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
vi.doMock("@fusion/core", () => distCoreModule);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
const { default: runtimeCoreExtension } = await import("../extension.js?fn6535-runtime-core-dist");
|
||||
const runtimeApi = createMockAPI();
|
||||
runtimeCoreExtension(runtimeApi);
|
||||
const listTool = runtimeApi.tools.get("fn_task_list")!;
|
||||
|
||||
const broadResult = await listTool.execute(
|
||||
"list-runtime-dist-broad",
|
||||
{ limit: 20 },
|
||||
undefined,
|
||||
undefined,
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
const broadText = broadResult.content[0].text;
|
||||
expect(broadResult.content).toHaveLength(1);
|
||||
expect(broadResult.content[0].type).toBe("text");
|
||||
expect(broadText.length).toBeLessThanOrEqual(MAX_TASK_LIST_TEXT_CHARS);
|
||||
expect(broadText).toContain("Todo (20):");
|
||||
expect(broadText).toContain("truncated to fit; narrow with column/limit");
|
||||
|
||||
const todoResult = await listTool.execute(
|
||||
"list-runtime-dist-todo",
|
||||
{ column: "todo", limit: 20 },
|
||||
undefined,
|
||||
undefined,
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
const todoText = todoResult.content[0].text;
|
||||
expect(todoResult.content).toHaveLength(1);
|
||||
expect(todoResult.content[0].type).toBe("text");
|
||||
expect(todoText.length).toBeLessThanOrEqual(MAX_TASK_LIST_TEXT_CHARS);
|
||||
expect(todoText).toContain("Todo (20):");
|
||||
expect(todoText).toContain("FN-001");
|
||||
expect(todoText).toContain("[deps: FN-001]");
|
||||
expect(todoText).toContain("truncated to fit; narrow with column/limit");
|
||||
expect(todoResult.details.count).toBe(20);
|
||||
await closeRuntimeCachedStores?.();
|
||||
await fixtureStore?.close();
|
||||
if (tmpDir) {
|
||||
await removeDirWithRetries(tmpDir);
|
||||
}
|
||||
} finally {
|
||||
await fixtureHarness?.teardown();
|
||||
vi.doUnmock("@fusion/core");
|
||||
vi.resetModules();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
FNXC:TaskListOutput 2026-06-17-02:37:
|
||||
FN-6535 reproduces the heartbeat failure at the actual CLI tool surface while forcing @fusion/core to resolve through the built dist barrel. The normal CLI suite aliases @fusion/core to source, so this targeted mock is the regression guard for stale exports.import dist artifacts.
|
||||
|
||||
FNXC:CoreTests 2026-06-18-01:35:
|
||||
FN-6627 aligns the skip gate with every built @fusion/core dist artifact this runtime-dist mock loads, so a partial stale dist skips cleanly while a complete dist still exercises the heartbeat fn_task_list surface.
|
||||
|
||||
FNXC:CliTests 2026-06-19-11:17:
|
||||
FN-6734 keeps this guard in the default 5s lane by preserving the runtime-dist truncation invariant with fewer fixture writes instead of appeasing timeouts or reducing workers.
|
||||
|
||||
FNXC:CliTests 2026-06-19-13:16:
|
||||
The full CLI affected lane runs this file beside many module-mocking suites; verify the built barrel is importable in the executing worker before installing the mock, then skip like the partial-dist gate if a concurrent lane observes stale dist artifacts.
|
||||
|
||||
FNXC:CliTests 2026-07-04-13:50:
|
||||
FN-7530 moved this case out of extension.test.ts unchanged (same assertions, same dist-resolution invariant, same skip gate). The sibling source-@fusion/core test "bounds large column-filtered listings as a single plain-text block" in extension.test.ts covers the identical truncation invariant against source; this test's only marginal coverage is that the built dist barrel resolves/executes identically, which is why it stays a dedicated, narrowly-scoped file rather than being deleted.
|
||||
*/
|
||||
it("lists the built-dist barrel fixture broadly within the text budget", async (ctx) => {
|
||||
if (runtimeDistArtifactUnavailable) return ctx.skip();
|
||||
|
||||
const broadResult = await listTool.execute(
|
||||
"list-runtime-dist-broad",
|
||||
{ limit: 20 },
|
||||
undefined,
|
||||
undefined,
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
const broadText = broadResult.content[0].text;
|
||||
expect(broadResult.content).toHaveLength(1);
|
||||
expect(broadResult.content[0].type).toBe("text");
|
||||
expect(broadText.length).toBeLessThanOrEqual(MAX_TASK_LIST_TEXT_CHARS);
|
||||
expect(broadText).toContain("Todo (20):");
|
||||
expect(broadText).toContain("truncated to fit; narrow with column/limit");
|
||||
});
|
||||
|
||||
it("lists the built-dist barrel todo column within the text budget", async (ctx) => {
|
||||
if (runtimeDistArtifactUnavailable) return ctx.skip();
|
||||
|
||||
const todoResult = await listTool.execute(
|
||||
"list-runtime-dist-todo",
|
||||
{ column: "todo", limit: 20 },
|
||||
undefined,
|
||||
undefined,
|
||||
makeCtx(tmpDir),
|
||||
);
|
||||
const todoText = todoResult.content[0].text;
|
||||
expect(todoResult.content).toHaveLength(1);
|
||||
expect(todoResult.content[0].type).toBe("text");
|
||||
expect(todoText.length).toBeLessThanOrEqual(MAX_TASK_LIST_TEXT_CHARS);
|
||||
expect(todoText).toContain("Todo (20):");
|
||||
expect(todoText).toContain("FN-001");
|
||||
expect(todoText).toContain("[deps: FN-001]");
|
||||
expect(todoText).toContain("truncated to fit; narrow with column/limit");
|
||||
expect(todoResult.details.count).toBe(20);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -85,13 +85,9 @@ const quarantinedCliTests: string[] = [
|
||||
FNXC:CliTests 2026-06-27-10:05:
|
||||
FN-7119 re-ran extension.test.ts twice with the exclude removed and the fn_delegate_task null-target symptom no longer reproduces at HEAD. Keep this list empty so delegate-task validation coverage stays active in the package lane.
|
||||
|
||||
FNXC:CliTests 2026-07-04-10:40:
|
||||
FN-7447 re-quarantines extension.test.ts after its built-dist-barrel fn_task_list test (line ~3084) timed out at 5000ms in full-suite shard 4/4 (run 28697507894) while passing locally at ~1.2s and in 3 of the 4 surrounding CI runs. The root-cause invariant is the loaded-lane signature: in-test dist-barrel recompilation (vi.resetModules + vi.importActual of the full @fusion/core dist barrel + a fresh dynamic import of extension.js) inside the default 5s timeout is CPU-bound and degrades non-linearly under 4-shard CI contention. This is the same signature rescued in FN-6483/FN-6705/FN-6795/FN-6839; widening the timeout is forbidden by the flaky-test rule and removing the recompilation removes the test's only purpose, so the file is excluded per the deletion ratchet rather than re-attempting a fifth fixture rescue. Mirrors scripts/lib/test-quarantine.json; collateral is the ~68 otherwise-stable tests in this file, recoverable via rescue before the 2026-07-18 deletion deadline.
|
||||
|
||||
FNXC:CliTests 2026-07-04-13:50:
|
||||
FN-7530 resolved the FN-7447 entry: RESCUE-by-split, not delete. The single dist-barrel recompilation test (unchanged assertions) moved to packages/cli/src/__tests__/extension-dist-barrel.test.ts; extension.test.ts is back in the default lane and its ~68 stable tests run again. The isolated file still stays quarantined here under its OWN fresh entry, because the root cause is loaded-lane CPU contention during vi.resetModules()/vi.importActual(dist barrel)/dynamic import() -- a property of that operation under 4-shard CI, not of file layout -- so splitting the file does not by itself make it safe to re-admit, and with only one test in the file there is no second call site to amortize a module-top-level rescue against. No testTimeout widening, retries, or worker/concurrency changes were made. Mirrors scripts/lib/test-quarantine.json; this isolated file's own 14-day deletion clock is due 2026-07-18.
|
||||
FNXC:CliTests 2026-07-16-06:27:
|
||||
FN-8093 rescues the isolated dist-barrel test before its deletion deadline. Its entire CPU-bound recompilation unit and fixture seeding run once in suite-scoped beforeAll, while each default-5s test body only executes an already-injected fn_task_list tool. The exclusion and matching ledger entry were removed in lockstep after loaded-lane verification; do not re-add either unless a new root cause is quarantined under the deletion ratchet.
|
||||
*/
|
||||
"src/__tests__/extension-dist-barrel.test.ts",
|
||||
/*
|
||||
FNXC:CliTests 2026-07-16-09:00:
|
||||
FN-8077 removed project-context.test.ts from this list and the ledger in lockstep. Its CentralCore coverage now uses the external PostgreSQL test harness under pgDescribe rather than launching an embedded postmaster for each test in forked loaded lanes; pure formatting coverage remains ungated.
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
{
|
||||
"$comment": "Flaky-test quarantine ledger (deletion ratchet — see AGENTS.md 'Flaky tests: quarantine on sight' and docs/testing.md 'Quarantine ledger and the deletion ratchet'). A test observed failing without a corresponding real bug is quarantined ON SIGHT: add an entry here AND a matching one-line `exclude` entry in that package's vitest config, in the same commit. Every entry needs a non-empty `reason` (link the failing run) and a `quarantinedAt` date — the entry expires 14 days later, at which point the test file is DELETED unless someone rescues it with evidence it catches real regressions plus a root-cause fix (never appeasement). There is deliberately no loader module and no automation around this file: it is a dated record, the vitest config is the enforcement.",
|
||||
"entries": [
|
||||
{
|
||||
"file": "packages/cli/src/__tests__/extension-dist-barrel.test.ts",
|
||||
"reason": "FN-7530 RESCUE-by-split of the prior extension.test.ts entry: the dist-barrel fn_task_list test timed out at 5000ms in the full-suite shard 4/4 (run https://github.com/Runfusion/Fusion/actions/runs/28697507894) while passing locally in ~1.2s and in 3 of the 4 surrounding CI runs. Root-cause invariant: the test does in-test module recompilation (vi.resetModules + vi.importActual of the full @fusion/core dist barrel + a fresh dynamic import of extension.js) inside the default 5s test timeout; that work is CPU-bound and degrades non-linearly under 4-shard CI contention (same loaded-lane signature as FN-6483/FN-6705/FN-6795/FN-6839). Widening the timeout is forbidden by the flaky-test rule and removing the recompilation removes the test's only point, so the file is quarantined pending a split into smaller compilation units.",
|
||||
"quarantinedAt": "2026-07-04"
|
||||
},
|
||||
{
|
||||
"file": "packages/engine/src/__tests__/backlog-pressure-reporter.test.ts",
|
||||
"reason": "VAL-REMOVAL-005 PG migration: fails due to SQLite removal or sync API incompatibility in backend mode. Failing run: https://github.com/Runfusion/Fusion/actions/runs/29344576232. Mirrored in packages/engine/vitest.config.ts.",
|
||||
|
||||
Reference in New Issue
Block a user