claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
169 lines (153 loc) • 6.95 kB
JavaScript
/**
* Regression guard for ruvnet/ruflo#1880.
*
* The 12-hour scheduled witness verification runs `verify.mjs` in a
* source-only checkout (no `npm ci`, no `npm run build`) and conflates
* two completely different failure modes:
*
* 1. `@noble/ed25519` not installed → precondition (install needed)
* 2. dist files referenced by manifest → precondition (build needed)
* not present on disk
* 3. signature actually doesn't verify → real failure
* 4. specific dist file regressed → real failure
*
* Before this guard, all four exited with code 1, so the scheduled
* runner filed a duplicate "verification failed" issue every 12 hours
* even though nothing was actually wrong with the manifest.
*
* verify.mjs now reserves exit 2 for preconditions (cases 1 and 2) and
* keeps exit 1 strictly for real failures (cases 3 and 4). This smoke
* drives both shapes through the script and asserts the contract holds.
*
* Fails CI if any of:
* - missing @noble/ed25519 exit code is anything other than 2
* - all-files-missing manifest exit code is anything other than 2
* - precondition output missing the operator-facing fix hint
* - precondition output missing the machine-parseable `reason` / `precondition` field
*/
import { spawnSync } from 'node:child_process';
import { existsSync, mkdirSync, mkdtempSync, writeFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
const REPO_ROOT = process.cwd();
const VERIFY = resolve(REPO_ROOT, 'plugins/ruflo-core/scripts/witness/verify.mjs');
const REAL_MANIFEST = resolve(REPO_ROOT, 'verification/macos/manifest.md.json');
if (!existsSync(VERIFY)) {
console.error(`smoke: not found: ${VERIFY}`);
process.exit(1);
}
if (!existsSync(REAL_MANIFEST)) {
console.error(`smoke: not found: ${REAL_MANIFEST}`);
process.exit(1);
}
const failures = [];
function record(name, condition, detail) {
if (condition) {
console.log(` PASS ${name}`);
} else {
console.log(` FAIL ${name}`);
if (detail) console.log(` ${detail}`);
failures.push(name);
}
}
// ── Case 1: @noble/ed25519 missing → exit 2 (precondition) ──────────
// Drop verify.mjs into an empty root with no node_modules anywhere up
// the tree, so the ed25519 probe fails on every candidate.
console.log('\nCase 1: @noble/ed25519 not installed (source-only)');
{
const tmp = mkdtempSync(join(tmpdir(), 'witness-smoke-nodep-'));
// verify.mjs's probes use createRequire(join(root, 'noop.js')) which
// walks up from `root`. Putting `root` deep under tmp ensures Node
// walks /tmp/.../node_modules (absent) then /tmp/node_modules (absent)
// then /node_modules (absent on CI) — no resolution.
const isolatedRoot = join(tmp, 'isolated', 'repo');
mkdirSync(isolatedRoot, { recursive: true });
// Stub node_modules to mask any system-level @noble/ed25519 install.
mkdirSync(join(isolatedRoot, 'node_modules'), { recursive: true });
const out = spawnSync('node', [VERIFY, '--manifest', REAL_MANIFEST, '--root', isolatedRoot, '--json'], {
encoding: 'utf8',
env: { ...process.env, NODE_PATH: '' },
});
record(
'exit code is 2 (precondition), not 1',
out.status === 2,
`got exit=${out.status}, stdout=${out.stdout?.slice(0, 200)}, stderr=${out.stderr?.slice(0, 200)}`,
);
record(
'stderr names @noble/ed25519 and the fix command',
/@noble\/ed25519/.test(out.stderr) && /npm (ci|install)/.test(out.stderr),
`stderr=${out.stderr?.slice(0, 400)}`,
);
record(
'JSON output carries machine-parseable precondition tag',
/noble-ed25519-not-installed/.test(out.stdout),
`stdout=${out.stdout?.slice(0, 200)}`,
);
rmSync(tmp, { recursive: true, force: true });
}
// ── Case 2: all manifest files missing → exit 2 (precondition) ──────
// Point verify.mjs at an isolated root that DOES have @noble/ed25519
// reachable (symlinked from the real install) but has none of the
// manifest's dist/ files — mimicking a clean clone with no build run.
console.log('\nCase 2: all manifest files missing (source-only, deps installed)');
{
const tmp = mkdtempSync(join(tmpdir(), 'witness-smoke-nobuild-'));
// Make @noble/ed25519 reachable by symlinking node_modules.
const realNodeModules = resolve(REPO_ROOT, 'node_modules');
if (existsSync(join(realNodeModules, '@noble', 'ed25519'))) {
mkdirSync(join(tmp, 'node_modules', '@noble'), { recursive: true });
// Use a relative symlink that survives the spawn.
const src = join(realNodeModules, '@noble', 'ed25519');
const dst = join(tmp, 'node_modules', '@noble', 'ed25519');
try {
// fs.symlinkSync via spawnSync to avoid extra import for the rare-path branch.
spawnSync('ln', ['-s', src, dst]);
} catch { /* best-effort */ }
}
const out = spawnSync('node', [VERIFY, '--manifest', REAL_MANIFEST, '--root', tmp, '--json'], {
encoding: 'utf8',
});
// We accept either:
// - exit 2 with precondition=dist-not-built (the new behavior)
// - exit 2 with precondition=noble-ed25519-not-installed (if the
// symlink trick didn't satisfy the probe on this runner — also a
// precondition, still not a real failure)
// We do NOT accept exit 1 — that's the bug this guard exists to catch.
record(
'exit code is 2 (precondition), not 1',
out.status === 2,
`got exit=${out.status}, stdout head=${out.stdout?.slice(0, 200)}, stderr head=${out.stderr?.slice(0, 200)}`,
);
record(
'output carries a precondition tag',
/noble-ed25519-not-installed|dist-not-built/.test(out.stdout + out.stderr),
`combined output=${(out.stdout + out.stderr).slice(0, 400)}`,
);
rmSync(tmp, { recursive: true, force: true });
}
// ── Case 3: built tree → never exit 2 (precondition is one-way) ─────
// On a built tree the verifier may produce 0 (clean) or 1 (some real
// regression caught) — both mean verification actually ran. What it
// must NEVER produce here is exit 2, because that would mean a built
// tree was mis-classified as "needs install/build" and the scheduled
// runner would silently skip filing real regressions.
console.log('\nCase 3: built tree never reports precondition');
{
const out = spawnSync('node', [VERIFY, '--manifest', REAL_MANIFEST], {
encoding: 'utf8',
cwd: REPO_ROOT,
});
record(
'exit code is NOT 2 (built tree should never be flagged as a precondition miss)',
out.status !== 2,
`got exit=${out.status}, tail=${(out.stdout + out.stderr).slice(-300)}`,
);
}
console.log('');
if (failures.length > 0) {
console.error(`smoke-witness-verify-precondition: ${failures.length} check(s) failed:`);
for (const f of failures) console.error(` - ${f}`);
process.exit(1);
}
console.log('smoke-witness-verify-precondition: all checks passed');