The Grok stale-dist bug was possible because the dev/build path never refreshed plugin dist: - The `client` prebuild (default `pnpm dev dashboard`) rebuilt only @fusion/core + @fusion/engine + @fusion/dashboard, never plugins. - The FN-6638 stale-dist startup warning only scanned packages/, never plugins/, so a source-ahead plugin dist ran phantom-old with no warning. Changes: - build-workspace.mjs: add `--plugins-only` to plan/build just the plugins that changed, reusing the existing content-hash skip cache (cheap no-op when unchanged). - scripts/dev-prebuild-client.mjs: new orchestrator — fast core/engine/ dashboard build, then incremental changed-plugin rebuild. The `client` prebuild now runs this single cross-platform command. - dist-freshness.mjs: scan plugin roots (plugins/, plugins/examples/) so a stale plugin dist is warned like a stale package dist; the warning names the plugin dir. Verified: --plugins-only plans only plugins, skips unchanged on the second run, and re-plans exactly the one plugin whose source changed. All script and CLI lib tests pass. Fusion-Task-Id: FN-7779 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.9 KiB
JavaScript
44 lines
1.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/*
|
|
FNXC:DevWorkflow 2026-07-10-15:40:
|
|
FN-7779 stale-plugin-dist: the `client` prebuild for `pnpm dev dashboard`.
|
|
|
|
Runs in two ordered steps so a dev restart never runs phantom-old code:
|
|
1. The FN-6638 fast path — rebuild @fusion/core + @fusion/engine +
|
|
@fusion/dashboard dist (NOT the full workspace) so landed engine/core/UI
|
|
fixes take effect.
|
|
2. Incrementally rebuild ONLY changed plugins via build-workspace's
|
|
content-hash skip cache (`--plugins-only`). Plugins load their built
|
|
dist/ at runtime, so a source-only plugin fix (e.g. the Grok CLI-flag fix
|
|
that caused "messages aren't sending") was silently stale until this step
|
|
existed — the old client prebuild rebuilt the three app packages but never
|
|
the plugins.
|
|
|
|
Unchanged plugins are a cheap content-hash no-op, so step 2 stays fast. Node
|
|
(not a shell `&&`) sequences the steps for cross-platform correctness.
|
|
*/
|
|
import { spawnSync } from "node:child_process";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
// Windows resolves `pnpm` to a `.cmd` shim Node can't spawn without a shell
|
|
// (ENOENT since CVE-2024-27980); these args carry no shell metacharacters.
|
|
const useShell = process.platform === "win32";
|
|
|
|
function run(command, args, options = {}) {
|
|
const result = spawnSync(command, args, { cwd: repoRoot, stdio: "inherit", ...options });
|
|
return result.status ?? 1;
|
|
}
|
|
|
|
// Step 1: fast app-package build (core -> engine -> dashboard, dependency order).
|
|
const appStatus = run(
|
|
"pnpm",
|
|
["--filter", "@fusion/core", "--filter", "@fusion/engine", "--filter", "@fusion/dashboard", "build"],
|
|
{ shell: useShell },
|
|
);
|
|
if (appStatus !== 0) process.exit(appStatus);
|
|
|
|
// Step 2: incremental changed-plugin rebuild.
|
|
process.exit(run("node", ["scripts/build-workspace.mjs", "--plugins-only"]));
|