- Remove stale .sf/milestones/M001/ and M002/ (not in DB, were blocking dispatch) - dispatch-guard.js: import findMilestoneIds from milestone-ids.js directly (not via guided-flow.js, which is in the circular-dep cluster) - auto.js: normalize 'Cannot dispatch' → prior-slice-blocker, 'SF resources updated' → resources-stale, 'Stuck:' → stuck in telemetry (was silently bucketing as 'other') Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
62 lines
1.7 KiB
JavaScript
62 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* check-circular-deps.mjs — detect circular imports across the SF codebase.
|
|
*
|
|
* Usage:
|
|
* npm run check:circular # scan src/ + packages/
|
|
* npm run check:circular -- --ext # scan extension source only
|
|
* node scripts/check-circular-deps.mjs [--ext] [--json]
|
|
*
|
|
* Exit 0 = no cycles found. Exit 1 = cycles detected (or scan error).
|
|
*/
|
|
|
|
import madge from "madge";
|
|
import { resolve, dirname } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = resolve(__dirname, "..");
|
|
|
|
const args = process.argv.slice(2);
|
|
const extOnly = args.includes("--ext");
|
|
const jsonOut = args.includes("--json");
|
|
|
|
const entries = extOnly
|
|
? [resolve(root, "src/resources/extensions/sf")]
|
|
: [resolve(root, "src"), resolve(root, "packages")];
|
|
|
|
console.error(`Scanning: ${entries.map((e) => e.replace(root + "/", "")).join(", ")}`);
|
|
|
|
let result;
|
|
try {
|
|
result = await madge(entries, {
|
|
fileExtensions: ["js", "mjs", "ts"],
|
|
excludeRegExp: [
|
|
/node_modules/,
|
|
/\.test\.(js|mjs|ts)$/,
|
|
/\/dist\//,
|
|
/\/tests?\//,
|
|
],
|
|
detectiveOptions: {
|
|
es6: { mixedImports: true, skipAsyncImports: true },
|
|
},
|
|
});
|
|
} catch (err) {
|
|
console.error(`Scan failed: ${err.message}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const cycles = result.circular();
|
|
|
|
if (jsonOut) {
|
|
console.log(JSON.stringify({ cycles, count: cycles.length }, null, 2));
|
|
} else if (cycles.length === 0) {
|
|
console.log("✅ No circular dependencies found.");
|
|
} else {
|
|
console.log(`❌ ${cycles.length} circular dependency chain(s) found:\n`);
|
|
for (const [i, chain] of cycles.entries()) {
|
|
console.log(` ${i + 1}. ${chain.join(" → ")} → ${chain[0]}`);
|
|
}
|
|
}
|
|
|
|
process.exit(cycles.length > 0 ? 1 : 0);
|