feat(FN-3470): prefer source aliases for runtime plugins and add test artif

Merges FN-3470 in two steps: first, runtime plugins now prefer source path aliases over build artifacts, with hardening tests for vitest alias resolution and plugin view registry updates; second, a new `ensure-test-artifacts.mjs` bootstrap script guarantees required test files exist before test runs

Fusion-Task-Id: FN-3470
This commit is contained in:
Fusion
2026-05-05 13:19:16 -07:00
committed by gsxdsm
parent 2e8fb88c44
commit 61bf81d6b8
10 changed files with 146 additions and 5 deletions

View File

@@ -0,0 +1,33 @@
import test from "node:test";
import assert from "node:assert/strict";
import { detectMissingArtifacts, ensureTestArtifacts } from "../ensure-test-artifacts.mjs";
test("detectMissingArtifacts returns missing package list", () => {
const missing = detectMissingArtifacts("/repo", () => false);
assert.ok(missing.length >= 5);
assert.equal(missing[0].name, "@fusion/core");
});
test("ensureTestArtifacts skips build when nothing is missing", () => {
let called = false;
const built = ensureTestArtifacts("/repo", () => {
called = true;
}, () => true);
assert.equal(called, false);
assert.deepEqual(built, []);
});
test("ensureTestArtifacts builds only missing packages", () => {
const calls = [];
const built = ensureTestArtifacts(
"/repo",
(cmd, args, cwd) => calls.push({ cmd, args, cwd }),
(fullPath) => !fullPath.includes("fusion-plugin-openclaw-runtime"),
);
assert.deepEqual(built, ["@fusion-plugin-examples/openclaw-runtime"]);
assert.equal(calls.length, 1);
assert.equal(calls[0].cmd, "pnpm");
assert.deepEqual(calls[0].args, ["--filter", "@fusion-plugin-examples/openclaw-runtime", "build"]);
});

View File

@@ -0,0 +1,41 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { URL } from "node:url";
function read(path) {
return readFileSync(new URL(`../../${path}`, import.meta.url), "utf8");
}
test("dashboard vitest config aliases runtime plugins to src", () => {
const content = read("packages/dashboard/vitest.config.ts");
assert.match(content, /@fusion-plugin-examples\/hermes-runtime/);
assert.match(content, /@fusion-plugin-examples\/openclaw-runtime/);
assert.match(content, /@fusion-plugin-examples\/paperclip-runtime/);
assert.match(content, /plugins\/fusion-plugin-hermes-runtime\/src\/index\.ts/);
assert.match(content, /plugins\/fusion-plugin-openclaw-runtime\/src\/index\.ts/);
assert.match(content, /plugins\/fusion-plugin-paperclip-runtime\/src\/index\.ts/);
});
test("cli vitest config aliases runtime plugins to src", () => {
const content = read("packages/cli/vitest.config.ts");
assert.ok(content.includes("@fusion-plugin-examples\\/droid-runtime"));
assert.ok(content.includes("@fusion-plugin-examples\\/hermes-runtime"));
assert.ok(content.includes("@fusion-plugin-examples\\/openclaw-runtime"));
assert.ok(content.includes("@fusion-plugin-examples\\/paperclip-runtime"));
assert.match(content, /plugins\/fusion-plugin-hermes-runtime\/src\/index\.ts/);
assert.match(content, /plugins\/fusion-plugin-openclaw-runtime\/src\/index\.ts/);
assert.match(content, /plugins\/fusion-plugin-paperclip-runtime\/src\/index\.ts/);
});
test("engine and plugin-sdk vitest configs keep source aliases", () => {
const engine = read("packages/engine/vitest.config.ts");
const sdk = read("packages/plugin-sdk/vitest.config.ts");
assert.match(engine, /@fusion\/core/);
assert.match(engine, /\.\.\/core\/src\/index\.ts/);
assert.match(engine, /@fusion\/plugin-sdk/);
assert.match(sdk, /@fusion\/core/);
assert.match(sdk, /\.\.\/core\/src\/index\.ts/);
});

View File

@@ -3,6 +3,7 @@
import { spawnSync } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { ensureTestArtifacts } from "./ensure-test-artifacts.mjs";
const DEFAULT_TEST_PACKAGES = [
"@fusion/core",
@@ -74,6 +75,7 @@ export function main(argv = process.argv.slice(2), env = process.env) {
};
run("pnpm", ["sync:fusion-skill:check"], { env: shardEnv });
ensureTestArtifacts(process.cwd());
const filters = shardPackages.flatMap((pkg) => ["--filter", pkg]);
run("pnpm", [...filters, "test"], { env: shardEnv });
}

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env node
import { existsSync } from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
export const REQUIRED_BUILD_PACKAGES = [
{ name: "@fusion/core", distEntry: "packages/core/dist/index.js" },
{ name: "@fusion/plugin-sdk", distEntry: "packages/plugin-sdk/dist/index.js" },
{ name: "@fusion-plugin-examples/hermes-runtime", distEntry: "plugins/fusion-plugin-hermes-runtime/dist/index.js" },
{ name: "@fusion-plugin-examples/openclaw-runtime", distEntry: "plugins/fusion-plugin-openclaw-runtime/dist/index.js" },
{ name: "@fusion-plugin-examples/paperclip-runtime", distEntry: "plugins/fusion-plugin-paperclip-runtime/dist/index.js" },
];
export function detectMissingArtifacts(rootDir = process.cwd(), existsFn = existsSync) {
return REQUIRED_BUILD_PACKAGES.filter((pkg) => !existsFn(path.join(rootDir, pkg.distEntry)));
}
function run(command, args, cwd) {
const result = spawnSync(command, args, { cwd, stdio: "inherit" });
if (result.status !== 0) {
process.exit(result.status ?? 1);
}
}
export function ensureTestArtifacts(rootDir = process.cwd(), runFn = run, existsFn = existsSync) {
const missing = detectMissingArtifacts(rootDir, existsFn);
if (missing.length === 0) return [];
const names = missing.map((pkg) => pkg.name);
console.log(`[test-bootstrap] building missing dist artifacts: ${names.join(", ")}`);
runFn("pnpm", [...names.flatMap((name) => ["--filter", name]), "build"], rootDir);
return names;
}
if (import.meta.url === `file://${process.argv[1]}`) {
ensureTestArtifacts();
}

View File

@@ -5,6 +5,7 @@ import path from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import { createHash } from "node:crypto";
import { ensureTestArtifacts } from "./ensure-test-artifacts.mjs";
const rootDir = process.env.FUSION_PROJECT_DIR
? path.resolve(process.env.FUSION_PROJECT_DIR)
@@ -447,6 +448,7 @@ export function main(argv = process.argv.slice(2)) {
const forwardedArgs = argv.filter((arg) => arg !== "--full" && arg !== "--no-cache");
run("pnpm", ["sync:fusion-skill:check"]);
ensureTestArtifacts(rootDir);
const baseBranch = getBaseBranch();
const comparisonBase = detectComparisonBase(baseBranch);