FN-6627: guard dist-barrel tests on complete core dist
Align dist-barrel regression guards so partial @fusion/core dist artifacts skip instead of failing mismatched dependency checks. - Add a shared @fusion/test-utils predicate for complete built core dist barrels. - Use the predicate in CLI and core dist-barrel regression tests before importing runtime dist modules. - Cover absent and partial dist directories with focused predicate tests. Files changed: packages/cli/src/__tests__/extension.test.ts | 9 +++-- .../src/__test-utils__/__tests__/core-dist.test.ts | 46 ++++++++++++++++++++++ packages/core/src/__test-utils__/workspace.ts | 11 ++++++ .../core/src/__tests__/task-list-format.test.ts | 17 ++++---- 4 files changed, 72 insertions(+), 11 deletions(-) Fusion-Task-Id: FN-6627 Fusion-Task-Lineage: a05ad009-229d-44c2-a49d-2d9b3f3d6094
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { existsSync } from "node:fs";
|
||||
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
@@ -27,6 +26,7 @@ import kbExtension, { resolveTaskListFormatter } from "../extension.js";
|
||||
import { TaskStore, AgentStore, MANUAL_RETRY_RESET_COUNTER_KEYS, RESEARCH_RUN_STATUSES, MAX_TASK_LIST_TEXT_CHARS, formatTaskListText } from "@fusion/core";
|
||||
import type { WorkflowIr } from "@fusion/core";
|
||||
import { isGhAvailable, isGhAuthenticated, runGhJsonAsync } from "@fusion/core/gh-cli";
|
||||
import { hasBuiltCoreDistBarrel } from "@fusion/test-utils";
|
||||
import { runTaskPlan } from "../commands/task.js";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
@@ -2694,13 +2694,14 @@ describe("fn pi extension (runnable structured-output regression slice)", () =>
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
it.skipIf(!existsSync(resolve(__dirname, "../../../core/dist/index.js")))(
|
||||
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 distTaskListFormat = resolve(__dirname, "../../../core/dist/task-list-format.js");
|
||||
expect(existsSync(distTaskListFormat)).toBe(true);
|
||||
|
||||
const store = new TaskStore(tmpDir);
|
||||
await store.init();
|
||||
|
||||
46
packages/core/src/__test-utils__/__tests__/core-dist.test.ts
Normal file
46
packages/core/src/__test-utils__/__tests__/core-dist.test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { hasBuiltCoreDistBarrel, requiredCoreDistFiles, tempWorkspace } from "../workspace.js";
|
||||
|
||||
describe("hasBuiltCoreDistBarrel", () => {
|
||||
function makeDistDir() {
|
||||
const root = tempWorkspace("fusion-core-dist-predicate-");
|
||||
const distDir = join(root, "dist");
|
||||
mkdirSync(distDir, { recursive: true });
|
||||
return distDir;
|
||||
}
|
||||
|
||||
function touchDistFile(distDir: string, file: (typeof requiredCoreDistFiles)[number]) {
|
||||
writeFileSync(join(distDir, file), "export {};\n");
|
||||
}
|
||||
|
||||
it("returns false when the dist barrel is absent", () => {
|
||||
const distDir = makeDistDir();
|
||||
|
||||
expect(hasBuiltCoreDistBarrel(distDir)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when index.js exists without task-list-format.js", () => {
|
||||
const distDir = makeDistDir();
|
||||
touchDistFile(distDir, "index.js");
|
||||
|
||||
expect(hasBuiltCoreDistBarrel(distDir)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when task-list-format.js exists without index.js", () => {
|
||||
const distDir = makeDistDir();
|
||||
touchDistFile(distDir, "task-list-format.js");
|
||||
|
||||
expect(hasBuiltCoreDistBarrel(distDir)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true only when all required core dist files exist", () => {
|
||||
const distDir = makeDistDir();
|
||||
for (const file of requiredCoreDistFiles) {
|
||||
touchDistFile(distDir, file);
|
||||
}
|
||||
|
||||
expect(hasBuiltCoreDistBarrel(distDir)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -16,6 +16,17 @@ import { join, resolve } from "node:path";
|
||||
import { afterEach } from "vitest";
|
||||
import { assertOutsideRealFusionPath } from "../test-safety.js";
|
||||
|
||||
/**
|
||||
* FNXC:CoreTests 2026-06-18-01:30:
|
||||
* FN-6627 requires built-dist-barrel regression guards to skip cleanly when @fusion/core/dist is absent or partial, and to run with full FN-6515/FN-6535 signal only when the same artifacts loaded by the test are present.
|
||||
* Keep new dist-dependent guards on this predicate instead of checking index.js separately from task-list-format.js body assertions.
|
||||
*/
|
||||
export const requiredCoreDistFiles = ["index.js", "task-list-format.js"] as const;
|
||||
|
||||
export function hasBuiltCoreDistBarrel(distDir: string): boolean {
|
||||
return requiredCoreDistFiles.every((file) => existsSync(resolve(distDir, file)));
|
||||
}
|
||||
|
||||
export function assertOutsideRealFusion(path: string, context = "operation"): void {
|
||||
assertOutsideRealFusionPath(path, context);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { beforeAll, describe, expect, it } from "vitest";
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
MAX_TASK_LIST_TEXT_CHARS as SOURCE_BARREL_MAX_TASK_LIST_TEXT_CHARS,
|
||||
formatTaskListText as sourceBarrelFormatTaskListText,
|
||||
} from "../index.js";
|
||||
import { hasBuiltCoreDistBarrel } from "@fusion/test-utils";
|
||||
import { clampTaskListText, formatTaskListText, MAX_TASK_LIST_TEXT_CHARS } from "../task-list-format.js";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
@@ -78,18 +78,21 @@ function executeRuntimeTaskList(
|
||||
* FN-6535 requires this guard to execute a fn_task_list-shaped runtime call through the built dist module, not just assert the barrel types. The recurring crash was a post-FN-6492 tool call resolving @fusion/core through exports.import to stale dist, so the regression must fail when that dist omits the helper.
|
||||
*/
|
||||
describe("@fusion/core dist barrel export wiring (FN-6515/FN-6535)", () => {
|
||||
const distIndex = resolve(__dirname, "../../dist/index.js");
|
||||
const distTaskListFormat = resolve(__dirname, "../../dist/task-list-format.js");
|
||||
const distDir = resolve(__dirname, "../../dist");
|
||||
const hasCompleteDistBarrel = hasBuiltCoreDistBarrel(distDir);
|
||||
const distIndex = resolve(distDir, "index.js");
|
||||
let builtDistCore: RuntimeCoreTaskListModule | undefined;
|
||||
|
||||
/*
|
||||
FNXC:CoreTests 2026-06-17-13:40:
|
||||
FN-6591 requires the FN-6515/FN-6535 dist-barrel guard to settle under broad @fusion/core suite load without timeout, retry, or worker appeasement.
|
||||
Load the built dist barrel once for every dist assertion so heartbeat fn_task_list coverage still exercises the real runtime export path while avoiding duplicate dynamic-import pressure in the timed test bodies.
|
||||
|
||||
FNXC:CoreTests 2026-06-18-01:35:
|
||||
FN-6627 requires this guard to skip when the built @fusion/core dist barrel is absent or partial, because the runtime import path depends on both index.js and task-list-format.js.
|
||||
*/
|
||||
beforeAll(async () => {
|
||||
if (!existsSync(distIndex)) return;
|
||||
expect(existsSync(distTaskListFormat)).toBe(true);
|
||||
if (!hasCompleteDistBarrel) return;
|
||||
builtDistCore = await import(pathToFileURL(distIndex).href) as RuntimeCoreTaskListModule;
|
||||
});
|
||||
|
||||
@@ -99,7 +102,7 @@ describe("@fusion/core dist barrel export wiring (FN-6515/FN-6535)", () => {
|
||||
expect(typeof SOURCE_BARREL_MAX_TASK_LIST_TEXT_CHARS).toBe("number");
|
||||
});
|
||||
|
||||
it.skipIf(!existsSync(distIndex))("re-exports task-list formatting helpers from the built dist barrel", () => {
|
||||
it.skipIf(!hasCompleteDistBarrel)("re-exports task-list formatting helpers from the built dist barrel", () => {
|
||||
const mod = builtDistCore;
|
||||
|
||||
expect(mod).toBeDefined();
|
||||
@@ -108,7 +111,7 @@ describe("@fusion/core dist barrel export wiring (FN-6515/FN-6535)", () => {
|
||||
expect(typeof mod?.MAX_TASK_LIST_TEXT_CHARS).toBe("number");
|
||||
});
|
||||
|
||||
it.skipIf(!existsSync(distIndex))("executes the fn_task_list surface through the built dist core module", () => {
|
||||
it.skipIf(!hasCompleteDistBarrel)("executes the fn_task_list surface through the built dist core module", () => {
|
||||
const mod = builtDistCore as RuntimeCoreTaskListModule;
|
||||
const todoAnchor: RuntimeTask = {
|
||||
id: "FN-001",
|
||||
|
||||
Reference in New Issue
Block a user