singularity-forge/scripts/check-circular-deps.mjs
Mikael Hugo 0b5fa75c0d fix(lint): fix all pre-existing lint failures
- check-sf-extension-inventory.mjs: expand parseDirectRegisteredCommands()
  scan to include 7 more files (guards/inturn.js, notifications/notify.js,
  permissions/index.js, ui/usage-bar.js, commands/legacy/audit.js,
  commands/legacy/create-extension.js, commands/legacy/create-slash-command.js)
  and filter results by BASE_RUNTIME_COMMAND_NAMES to exclude doc-string false
  positives ("name" in create-slash-command.js template text)

- extension-manifest.json: remove 'clear' (subcommand of logs/notifications,
  never a top-level pi.registerCommand)

- packages/pi-agent-core/src/db/sf-db.ts: fix 23 noVoidTypeReturn errors
  - openDatabase: void → boolean (caller uses return value at line 5625)
  - claimEscalationOverride: void → boolean (caller checks at escalation.js:243)
  - resolveSelfFeedbackEntry: void → boolean (caller checks at self-feedback.js:387)
  - copyWorktreeDb: void → boolean (caller checks at reconcileWorktreeDb)
  - compactUokMessages: void → {before,after} (caller returns value at message-bus.js:238)
  - insertSessionTurn: void → bigint|null (caller uses id at session-recorder.js:104)
  - expireStaleMemories: void → number (caller uses count at auto-start.js:1047)
  - deleteMemorySourceRow: void → boolean (caller returns value at memory-source-store.js:107)
  - deleteMemoryEmbedding: void → boolean (caller returns value at memory-embeddings.js:328)
  - updateBacklogItemStatus: remove dead return expression (callers discard value)
  - removeBacklogItem: remove dead return expression (callers discard value)
  - updateGateCircuitBreaker: remove dead return {total,avgMs,...} (wrong-type
    code accidentally merged from getGateLatencyStats, never reachable)
  - markUokMessageRead: remove dead return true/false (callers discard value)

- Auto-fix formatting and organizeImports in ~30 source files (biome --write)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 04:02:31 +02:00

65 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 { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import madge from "madge";
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);