23f7624596
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Blocked by required conditions
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Blocked by required conditions
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Blocked by required conditions
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Blocked by required conditions
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Waiting to run
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Blocked by required conditions
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Blocked by required conditions
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Blocked by required conditions
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Blocked by required conditions
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Waiting to run
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Waiting to run
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Deploy & Release (push) Waiting to run
CI/CD Pipeline / CI Status (push) Waiting to run
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Waiting to run
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Waiting to run
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
🔍 Verification Pipeline / ⚡ Performance Verification (push) Waiting to run
🔍 Verification Pipeline / 📊 Verification Report (push) Waiting to run
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
210 lines
9.3 KiB
JavaScript
210 lines
9.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Plugin package.json install-safety audit (regression guard for #1902/#1903/#1904).
|
|
*
|
|
* Scans v3/plugins/<name>/package.json and fails CI on any of:
|
|
*
|
|
* A. (#1903) A `@claude-flow/*` package referenced as a hard `dependencies`
|
|
* entry, OR as a `peerDependencies` entry that is NOT marked
|
|
* `peerDependenciesMeta[name].optional: true`, that is not in the
|
|
* KNOWN_PUBLISHED allow-list. npm 7+ auto-installs non-optional peers,
|
|
* so an unpublished one (e.g. `@claude-flow/ruvector-upstream`) makes
|
|
* `npm install <plugin>` fail with E404.
|
|
*
|
|
* B. (#1902) A `peerDependencies` range for a `@claude-flow/*` or
|
|
* `@ruvector/*` target that is a "bare stable" range (`>=X.Y.Z`,
|
|
* `^X.Y.Z`, `~X.Y.Z`, `X.Y.Z`) with no prerelease component. Those
|
|
* ranges DON'T satisfy a prerelease publish like `3.0.0-alpha.15`, so
|
|
* npm can't find a matching version. Use `>=X.Y.Z-0` or `*`.
|
|
*
|
|
* C. (#1904, static) Every path in `main` / `module` / `types` / `bin` and
|
|
* every path inside `exports` must live under a directory (or glob) that
|
|
* is included in `files` — otherwise it isn't in the published tarball.
|
|
*
|
|
* D. (#1904, post-build) For any plugin whose `dist/` exists on disk (i.e.
|
|
* it has been built), every `main`/`module`/`types`/`exports` path must
|
|
* exist. This is the real catch for "exports.import → ./dist/index.mjs
|
|
* but the build only emits .cjs". CI builds the plugins before running
|
|
* this script so check D is live there.
|
|
*
|
|
* Usage:
|
|
* node scripts/audit-plugin-packages.mjs # audit, exit 1 on any issue
|
|
* node scripts/audit-plugin-packages.mjs --json # machine-readable report
|
|
*/
|
|
|
|
import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
|
|
import { join, dirname } from 'node:path';
|
|
|
|
const REPO_ROOT = process.cwd();
|
|
const PLUGINS_DIR = join(REPO_ROOT, 'v3', 'plugins');
|
|
const JSON_OUT = process.argv.includes('--json');
|
|
|
|
// @claude-flow/* packages known to be published to the npm registry. A hard
|
|
// dep / non-optional peer on anything @claude-flow/* NOT in this set fails the
|
|
// audit. Refresh with: for n in <pkg>; do npm view @claude-flow/$n version; done
|
|
const KNOWN_PUBLISHED = new Set([
|
|
'@claude-flow/aidefence',
|
|
'@claude-flow/browser',
|
|
'@claude-flow/claims',
|
|
'@claude-flow/cli',
|
|
'@claude-flow/cli-core',
|
|
'@claude-flow/codex',
|
|
'@claude-flow/deployment',
|
|
'@claude-flow/embeddings',
|
|
'@claude-flow/guidance',
|
|
'@claude-flow/hooks',
|
|
'@claude-flow/integration',
|
|
'@claude-flow/mcp',
|
|
'@claude-flow/memory',
|
|
'@claude-flow/neural',
|
|
'@claude-flow/performance',
|
|
'@claude-flow/plugins',
|
|
'@claude-flow/providers',
|
|
'@claude-flow/security',
|
|
'@claude-flow/shared',
|
|
'@claude-flow/swarm',
|
|
'@claude-flow/testing',
|
|
// plugin-* packages publish under @claude-flow/plugin-<name>; the plugin
|
|
// store loads them by tarball, but if one plugin hard-depends on another
|
|
// it must be published. Add entries here if/when that happens.
|
|
]);
|
|
|
|
// A peer-range is "prerelease-safe" if it includes a prerelease tag (`-0`,
|
|
// `-alpha`, …) or is the wildcard `*` / `latest` / a workspace protocol.
|
|
function isPrereleaseSafeRange(range) {
|
|
const r = String(range).trim();
|
|
if (r === '*' || r === 'latest' || r === '' || r.startsWith('workspace:') || r.startsWith('file:') || r.startsWith('link:')) return true;
|
|
if (/-[0-9A-Za-z.]+/.test(r)) return true; // has a prerelease component somewhere
|
|
// bare stable: >=X.Y.Z | ^X.Y.Z | ~X.Y.Z | X.Y.Z | >X.Y.Z (and ranges of those)
|
|
if (/^[\^~]?\d+(\.\d+){0,2}$/.test(r)) return false;
|
|
if (/^>=?\s*\d+(\.\d+){0,2}$/.test(r)) return false;
|
|
// anything else (e.g. "3.x", "1.2 - 2.3", complex composites) — don't flag,
|
|
// too noisy; the two patterns above cover the real-world offenders.
|
|
return true;
|
|
}
|
|
|
|
// Does `files` (array of literal paths / globs) include `relPath`?
|
|
function filesCovers(files, relPath) {
|
|
if (!Array.isArray(files)) return true; // no `files` field → whole dir publishes
|
|
const clean = relPath.replace(/^\.\//, '');
|
|
const topSeg = clean.split('/')[0];
|
|
for (const entry of files) {
|
|
const e = String(entry).replace(/^\.\//, '');
|
|
if (e === clean) return true;
|
|
if (e === topSeg) return true; // "dist" covers "dist/index.js"
|
|
if (e.startsWith(topSeg + '/')) return true; // "dist/**" covers "dist/index.js"
|
|
if (e === topSeg + '/**') return true;
|
|
if (e.includes('*')) {
|
|
// crude glob → regex
|
|
const re = new RegExp('^' + e.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*') + '$');
|
|
if (re.test(clean)) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Collect every file path referenced by package.json export-ish fields.
|
|
function collectExportPaths(pkg) {
|
|
const out = new Set();
|
|
const add = (v) => { if (typeof v === 'string' && v.startsWith('.')) out.add(v); };
|
|
add(pkg.main); add(pkg.module); add(pkg.types); add(pkg.typings);
|
|
if (typeof pkg.bin === 'string') add(pkg.bin);
|
|
else if (pkg.bin && typeof pkg.bin === 'object') Object.values(pkg.bin).forEach(add);
|
|
const walk = (node) => {
|
|
if (typeof node === 'string') return add(node);
|
|
if (Array.isArray(node)) return node.forEach(walk);
|
|
if (node && typeof node === 'object') return Object.values(node).forEach(walk);
|
|
};
|
|
if (pkg.exports) walk(pkg.exports);
|
|
return [...out];
|
|
}
|
|
|
|
const plugins = existsSync(PLUGINS_DIR)
|
|
? readdirSync(PLUGINS_DIR).filter((d) => {
|
|
const p = join(PLUGINS_DIR, d);
|
|
return statSync(p).isDirectory() && existsSync(join(p, 'package.json'));
|
|
})
|
|
: [];
|
|
|
|
const issues = [];
|
|
const note = (plugin, code, message) => issues.push({ plugin, code, message });
|
|
|
|
for (const dir of plugins) {
|
|
const pkgPath = join(PLUGINS_DIR, dir, 'package.json');
|
|
let pkg;
|
|
try { pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')); }
|
|
catch (e) { note(dir, 'PARSE', `package.json is not valid JSON: ${e.message}`); continue; }
|
|
|
|
const deps = pkg.dependencies || {};
|
|
const peers = pkg.peerDependencies || {};
|
|
const peerMeta = pkg.peerDependenciesMeta || {};
|
|
|
|
// --- Check A: unpublished @claude-flow/* as hard dep / non-optional peer
|
|
for (const [name] of Object.entries(deps)) {
|
|
if (name.startsWith('@claude-flow/') && !KNOWN_PUBLISHED.has(name)) {
|
|
note(dir, 'A', `"${name}" is a hard dependency but not a published @claude-flow package — \`npm install\` will E404. Make it an optional peerDependency or remove it (the runtime should fall back when absent).`);
|
|
}
|
|
}
|
|
for (const [name] of Object.entries(peers)) {
|
|
const optional = peerMeta[name] && peerMeta[name].optional === true;
|
|
if (name.startsWith('@claude-flow/') && !KNOWN_PUBLISHED.has(name) && !optional) {
|
|
note(dir, 'A', `"${name}" is a non-optional peerDependency but not a published @claude-flow package — npm 7+ auto-installs peers and will E404. Add \`peerDependenciesMeta["${name}"].optional: true\`.`);
|
|
}
|
|
}
|
|
|
|
// --- Check B: bare-stable peer ranges for prerelease @claude-flow targets.
|
|
// All @claude-flow packages currently publish as 3.x prereleases, so a bare
|
|
// ">=3.0.0" can never resolve. We only flag @claude-flow/* here (and only
|
|
// when non-optional, or optional-but-@claude-flow since the project always
|
|
// ships those as prereleases). Optional @ruvector/* WASM peers are exempt —
|
|
// a bare range there at worst means the optional dep doesn't get installed.
|
|
for (const [name, range] of Object.entries(peers)) {
|
|
if (!name.startsWith('@claude-flow/')) continue;
|
|
if (isPrereleaseSafeRange(range)) continue;
|
|
note(dir, 'B', `peerDependency "${name}": "${range}" can't resolve any @claude-flow publish — they're all 3.x prereleases. Use ">=${String(range).replace(/^[\^~>=\s]+/, '')}-0" or "*".`);
|
|
}
|
|
|
|
// --- Check C: export-ish paths must be covered by `files`
|
|
const exportPaths = collectExportPaths(pkg);
|
|
for (const rel of exportPaths) {
|
|
if (!filesCovers(pkg.files, rel)) {
|
|
note(dir, 'C', `"${rel}" is referenced (main/module/exports) but not covered by "files" ${JSON.stringify(pkg.files)} — it won't be in the published tarball.`);
|
|
}
|
|
}
|
|
|
|
// --- Check D: if built, export-ish paths must exist on disk
|
|
const distDir = join(PLUGINS_DIR, dir, 'dist');
|
|
if (existsSync(distDir)) {
|
|
for (const rel of exportPaths) {
|
|
const abs = join(PLUGINS_DIR, dir, rel.replace(/^\.\//, ''));
|
|
if (!existsSync(abs)) {
|
|
note(dir, 'D', `"${rel}" is referenced (main/module/exports) but does not exist after build — the build emits a different filename/extension. (e.g. tsup may emit .cjs/.js, not .mjs)`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const report = {
|
|
scannedPlugins: plugins.length,
|
|
issueCount: issues.length,
|
|
byCode: issues.reduce((m, i) => ((m[i.code] = (m[i.code] || 0) + 1), m), {}),
|
|
issues,
|
|
};
|
|
|
|
if (JSON_OUT) {
|
|
console.log(JSON.stringify(report, null, 2));
|
|
} else {
|
|
console.log(`plugin package audit — scanned ${plugins.length} plugin(s)`);
|
|
if (issues.length === 0) {
|
|
console.log(' ✓ no install-safety issues');
|
|
} else {
|
|
const labels = { A: 'unpublished @claude-flow dep', B: 'prerelease-unsafe peer range', C: 'export not in files', D: 'export missing after build', PARSE: 'invalid package.json' };
|
|
for (const i of issues) {
|
|
console.log(` ✗ [${i.code}] ${i.plugin}: ${i.message}`);
|
|
}
|
|
console.log(`\n${issues.length} issue(s) across codes: ${Object.entries(report.byCode).map(([c, n]) => `${c}=${n} (${labels[c] || c})`).join(', ')}`);
|
|
}
|
|
}
|
|
|
|
process.exit(issues.length > 0 ? 1 : 0);
|