chiasmus 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +24 -0
  2. package/dist/formalize/validate.js +78 -11
  3. package/dist/formalize/validate.js.map +1 -1
  4. package/dist/graph/analyses.d.ts +1 -1
  5. package/dist/graph/analyses.d.ts.map +1 -1
  6. package/dist/graph/analyses.js +78 -8
  7. package/dist/graph/analyses.js.map +1 -1
  8. package/dist/graph/extractor.d.ts.map +1 -1
  9. package/dist/graph/extractor.js +108 -56
  10. package/dist/graph/extractor.js.map +1 -1
  11. package/dist/graph/facts.d.ts +2 -0
  12. package/dist/graph/facts.d.ts.map +1 -1
  13. package/dist/graph/facts.js +20 -6
  14. package/dist/graph/facts.js.map +1 -1
  15. package/dist/graph/mermaid.d.ts.map +1 -1
  16. package/dist/graph/mermaid.js +3 -7
  17. package/dist/graph/mermaid.js.map +1 -1
  18. package/dist/graph/parser.d.ts.map +1 -1
  19. package/dist/graph/parser.js +19 -5
  20. package/dist/graph/parser.js.map +1 -1
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/llm/anthropic.d.ts.map +1 -1
  26. package/dist/llm/anthropic.js +2 -0
  27. package/dist/llm/anthropic.js.map +1 -1
  28. package/dist/llm/openai-compatible.d.ts.map +1 -1
  29. package/dist/llm/openai-compatible.js +2 -0
  30. package/dist/llm/openai-compatible.js.map +1 -1
  31. package/dist/mcp-server.d.ts.map +1 -1
  32. package/dist/mcp-server.js +91 -3
  33. package/dist/mcp-server.js.map +1 -1
  34. package/dist/review.d.ts +43 -0
  35. package/dist/review.d.ts.map +1 -0
  36. package/dist/review.js +338 -0
  37. package/dist/review.js.map +1 -0
  38. package/dist/skills/bm25.d.ts +4 -0
  39. package/dist/skills/bm25.d.ts.map +1 -1
  40. package/dist/skills/bm25.js +41 -0
  41. package/dist/skills/bm25.js.map +1 -1
  42. package/dist/skills/library.d.ts +1 -0
  43. package/dist/skills/library.d.ts.map +1 -1
  44. package/dist/skills/library.js +52 -21
  45. package/dist/skills/library.js.map +1 -1
  46. package/dist/skills/relationships.d.ts.map +1 -1
  47. package/dist/skills/relationships.js +25 -0
  48. package/dist/skills/relationships.js.map +1 -1
  49. package/dist/skills/starters.d.ts.map +1 -1
  50. package/dist/skills/starters.js +449 -0
  51. package/dist/skills/starters.js.map +1 -1
  52. package/dist/solvers/correction-loop.d.ts.map +1 -1
  53. package/dist/solvers/correction-loop.js +8 -16
  54. package/dist/solvers/correction-loop.js.map +1 -1
  55. package/dist/solvers/prolog-solver.d.ts.map +1 -1
  56. package/dist/solvers/prolog-solver.js +58 -46
  57. package/dist/solvers/prolog-solver.js.map +1 -1
  58. package/dist/solvers/types.d.ts +6 -0
  59. package/dist/solvers/types.d.ts.map +1 -1
  60. package/dist/solvers/z3-solver.d.ts +5 -0
  61. package/dist/solvers/z3-solver.d.ts.map +1 -1
  62. package/dist/solvers/z3-solver.js +30 -7
  63. package/dist/solvers/z3-solver.js.map +1 -1
  64. package/package.json +1 -1
package/README.md CHANGED
@@ -11,6 +11,7 @@ MCP server that gives LLMs access to formal verification via Z3 (SMT solver) and
11
11
  - **"Does our workflow have dead-end or unreachable states?"** → Prolog checks reachability from the initial state, identifies orphaned and terminal nodes
12
12
  - **"What's the dead code in this module?"** → tree-sitter parses source files, Prolog finds functions unreachable from any entry point
13
13
  - **"What breaks if I change this function?"** → call graph impact analysis shows all transitive callers
14
+ - **"Do a full code review of these files"** → `chiasmus_review` returns a phased recipe of graph analyses + verification templates, and you execute it step-by-step
14
15
 
15
16
  ## Setup
16
17
 
@@ -142,6 +143,29 @@ chiasmus_craft name="api-rate-limit" domain="configuration" solver="z3"
142
143
 
143
144
  After creation, the template appears in `chiasmus_skills` searches and `chiasmus_formalize`.
144
145
 
146
+ **`chiasmus_review`** — Returns a phased code-review recipe: which chiasmus tools and templates to run, in what order, and what to look for. No side effects — pure scaffolding. Execute phases sequentially using the named tools, then produce a final report per the `reporting` section.
147
+
148
+ ```
149
+ chiasmus_review files=["src/handler.ts", "src/db.ts"] focus="all"
150
+ → {
151
+ phases: [
152
+ { phase: "1. Structural overview", actions: [{tool: "chiasmus_graph", args: {analysis: "summary"}, interpret: "..."}] },
153
+ { phase: "2. Architecture health", actions: [dead-code, cycles, layer-violation] },
154
+ { phase: "3. Security — data flow and taint", actions: [facts + chiasmus_formalize taint-propagation] },
155
+ { phase: "4. Resource safety", actions: [association-rule-check] },
156
+ { phase: "5. Authorization", actions: [policy-contradiction] },
157
+ { phase: "6. Correctness — invariants, boundaries, state machines", actions: [...] },
158
+ { phase: "7. Impact analysis on flagged functions", actions: [chiasmus_graph impact] },
159
+ ],
160
+ suggestedTemplates: [...],
161
+ reporting: { format: "Numbered issue list with severity", severityLevels: ["CRITICAL","HIGH","MEDIUM","LOW","INFO"] }
162
+ }
163
+ ```
164
+
165
+ Focus modes subset the phases: `all` (default, 7 phases), `quick` (overview + architecture), `architecture` (structural defects + impact), `security` (taint + resource pairing + auth), `correctness` (invariants + boundaries + state machines).
166
+
167
+ Each action carries an `interpret` field describing how to score the result. After all phases, emit a numbered issue list with severity labels and file:line references.
168
+
145
169
  **`chiasmus_learn`** — Extract a reusable template from a verified solution. Candidates get promoted after 3+ successful reuses.
146
170
 
147
171
  **`chiasmus_lint`** — Fast structural validation of specs without running the solver.
@@ -92,17 +92,12 @@ function lintSmtlib(spec, fixes, errors) {
92
92
  }
93
93
  return { spec: cleaned };
94
94
  }
95
- function lintProlog(spec, fixes, errors) {
96
- let cleaned = spec;
97
- // Auto-fix: remove ?- query line (we extract it separately)
98
- // Don't report this as a fix since buildSolverInput handles it
99
- // Strip comments and strings for structural analysis
100
- const stripped = cleaned
101
- .replace(/%.*$/gm, "")
102
- .replace(/\/\*[\s\S]*?\*\//g, "")
103
- .replace(/"[^"]*"/g, '""')
104
- .replace(/'[^']*'/g, "''")
105
- .trim();
95
+ function lintProlog(spec, _fixes, errors) {
96
+ const cleaned = spec;
97
+ // Context-aware strip of comments and quoted literals. Naive regex
98
+ // stripping misparses `%` inside atoms as line comments, and `''` inside
99
+ // atoms as quote open/close both cause false-positive errors.
100
+ const stripped = stripPrologNoise(cleaned).trim();
106
101
  if (!stripped)
107
102
  return { spec: cleaned };
108
103
  // Check: at least one clause ending with a period
@@ -126,4 +121,76 @@ function lintProlog(spec, fixes, errors) {
126
121
  }
127
122
  return { spec: cleaned };
128
123
  }
124
+ /**
125
+ * Remove Prolog comments and quoted literal contents without breaking inside
126
+ * strings/atoms. Replaces quoted literals with an empty placeholder (`''` or
127
+ * `""`) so paren-balance checks still work on the surrounding structure.
128
+ */
129
+ function stripPrologNoise(src) {
130
+ let out = "";
131
+ let i = 0;
132
+ const n = src.length;
133
+ while (i < n) {
134
+ const ch = src[i];
135
+ // Line comment — only outside quotes
136
+ if (ch === "%") {
137
+ while (i < n && src[i] !== "\n")
138
+ i++;
139
+ continue;
140
+ }
141
+ // Block comment — only outside quotes
142
+ if (ch === "/" && src[i + 1] === "*") {
143
+ i += 2;
144
+ while (i < n && !(src[i] === "*" && src[i + 1] === "/"))
145
+ i++;
146
+ i += 2;
147
+ continue;
148
+ }
149
+ // Single-quoted atom
150
+ if (ch === "'") {
151
+ i++;
152
+ while (i < n) {
153
+ if (src[i] === "\\" && i + 1 < n) {
154
+ i += 2;
155
+ continue;
156
+ }
157
+ if (src[i] === "'" && src[i + 1] === "'") {
158
+ i += 2;
159
+ continue;
160
+ }
161
+ if (src[i] === "'") {
162
+ i++;
163
+ break;
164
+ }
165
+ i++;
166
+ }
167
+ out += "''";
168
+ continue;
169
+ }
170
+ // Double-quoted string
171
+ if (ch === '"') {
172
+ i++;
173
+ while (i < n) {
174
+ if (src[i] === "\\" && i + 1 < n) {
175
+ i += 2;
176
+ continue;
177
+ }
178
+ if (src[i] === '"' && src[i + 1] === '"') {
179
+ i += 2;
180
+ continue;
181
+ }
182
+ if (src[i] === '"') {
183
+ i++;
184
+ break;
185
+ }
186
+ i++;
187
+ }
188
+ out += '""';
189
+ continue;
190
+ }
191
+ out += ch;
192
+ i++;
193
+ }
194
+ return out;
195
+ }
129
196
  //# sourceMappingURL=validate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/formalize/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/formalize/validate.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { CodeGraph } from "./types.js";
2
- export type AnalysisType = "summary" | "callers" | "callees" | "reachability" | "dead-code" | "cycles" | "path" | "impact" | "facts";
2
+ export type AnalysisType = "summary" | "callers" | "callees" | "reachability" | "dead-code" | "cycles" | "path" | "impact" | "facts" | "layer-violation";
3
3
  export interface AnalysisRequest {
4
4
  analysis: AnalysisType;
5
5
  target?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"analyses.d.ts","sourceRoot":"","sources":["../../src/graph/analyses.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,YAAY,GACpB,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,cAAc,GAClD,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qDAAqD;AACrD,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAiCzB;AAED,yEAAyE;AACzE,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAuBzB"}
1
+ {"version":3,"file":"analyses.d.ts","sourceRoot":"","sources":["../../src/graph/analyses.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C,MAAM,MAAM,YAAY,GACpB,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,cAAc,GAClD,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GACpD,iBAAiB,CAAC;AAEtB,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qDAAqD;AACrD,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAgDzB;AAED,yEAAyE;AACzE,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CA2BzB"}
@@ -1,14 +1,29 @@
1
- import { readFileSync } from "node:fs";
1
+ import { readFileSync, statSync } from "node:fs";
2
2
  import { extractGraph } from "./extractor.js";
3
3
  import { graphToProlog, escapeAtom } from "./facts.js";
4
4
  import { createPrologSolver } from "../solvers/prolog-solver.js";
5
+ const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
6
+ // Graph analyses run system-generated Prolog (not user input) and walk
7
+ // cycle-safe reachability rules that are O(n²) per step. The default
8
+ // 100 000 inference budget gets exhausted on mid-size codebases (a few
9
+ // hundred functions), so we raise it for analyses.
10
+ const GRAPH_MAX_INFERENCES = 5_000_000;
5
11
  /** Run a graph analysis on the given source files */
6
12
  export async function runAnalysis(filePaths, request) {
7
- // Read files from disk
8
- const files = filePaths.map((p) => ({
9
- path: p,
10
- content: readFileSync(p, "utf-8"),
11
- }));
13
+ // Read files from disk with size check
14
+ const files = [];
15
+ for (const p of filePaths) {
16
+ try {
17
+ const stat = statSync(p);
18
+ if (stat.size > MAX_FILE_SIZE) {
19
+ continue; // skip oversized files
20
+ }
21
+ files.push({ path: p, content: readFileSync(p, "utf-8") });
22
+ }
23
+ catch {
24
+ continue; // skip unreadable files
25
+ }
26
+ }
12
27
  const graph = await extractGraph(files);
13
28
  const program = graphToProlog(graph, request.entryPoints);
14
29
  if (request.analysis === "facts") {
@@ -20,13 +35,19 @@ export async function runAnalysis(filePaths, request) {
20
35
  result: buildSummary(graph),
21
36
  };
22
37
  }
38
+ if (request.analysis === "layer-violation") {
39
+ return {
40
+ analysis: "layer-violation",
41
+ result: findLayerViolations(graph),
42
+ };
43
+ }
23
44
  const query = buildQuery(request);
24
45
  if (!query) {
25
46
  return { analysis: request.analysis, result: { error: "Missing required parameters" } };
26
47
  }
27
48
  const solver = createPrologSolver();
28
49
  try {
29
- const solverResult = await solver.solve({ type: "prolog", program, query });
50
+ const solverResult = await solver.solve({ type: "prolog", program, query, maxInferences: GRAPH_MAX_INFERENCES });
30
51
  return { analysis: request.analysis, result: formatResult(request.analysis, solverResult) };
31
52
  }
32
53
  finally {
@@ -42,19 +63,68 @@ export async function runAnalysisFromGraph(graph, request) {
42
63
  if (request.analysis === "summary") {
43
64
  return { analysis: "summary", result: buildSummary(graph) };
44
65
  }
66
+ if (request.analysis === "layer-violation") {
67
+ return { analysis: "layer-violation", result: findLayerViolations(graph) };
68
+ }
45
69
  const query = buildQuery(request);
46
70
  if (!query) {
47
71
  return { analysis: request.analysis, result: { error: "Missing required parameters" } };
48
72
  }
49
73
  const solver = createPrologSolver();
50
74
  try {
51
- const solverResult = await solver.solve({ type: "prolog", program, query });
75
+ const solverResult = await solver.solve({ type: "prolog", program, query, maxInferences: GRAPH_MAX_INFERENCES });
52
76
  return { analysis: request.analysis, result: formatResult(request.analysis, solverResult) };
53
77
  }
54
78
  finally {
55
79
  solver.dispose();
56
80
  }
57
81
  }
82
+ const LAYER_ORDER = {
83
+ handlers: 0,
84
+ routes: 0,
85
+ controllers: 0,
86
+ services: 1,
87
+ repositories: 2,
88
+ db: 3,
89
+ models: 3,
90
+ };
91
+ function extractLayer(filePath) {
92
+ const normalized = filePath.replace(/\\/g, "/");
93
+ const segments = normalized.split("/");
94
+ for (const seg of segments) {
95
+ if (seg in LAYER_ORDER)
96
+ return seg;
97
+ }
98
+ return null;
99
+ }
100
+ function findLayerViolations(graph) {
101
+ const funcLayers = new Map();
102
+ for (const d of graph.defines) {
103
+ const layer = extractLayer(d.file);
104
+ if (layer)
105
+ funcLayers.set(d.name, layer);
106
+ }
107
+ const violations = [];
108
+ for (const c of graph.calls) {
109
+ const callerLayer = funcLayers.get(c.caller);
110
+ const calleeLayer = funcLayers.get(c.callee);
111
+ if (!callerLayer || !calleeLayer)
112
+ continue;
113
+ if (callerLayer === calleeLayer)
114
+ continue;
115
+ const callerOrder = LAYER_ORDER[callerLayer] ?? 0;
116
+ const calleeOrder = LAYER_ORDER[calleeLayer] ?? 0;
117
+ if (calleeOrder - callerOrder > 1) {
118
+ violations.push({
119
+ caller: c.caller,
120
+ callee: c.callee,
121
+ callerLayer,
122
+ calleeLayer,
123
+ });
124
+ }
125
+ }
126
+ return violations;
127
+ }
58
128
  function buildSummary(graph) {
59
129
  const files = new Set(graph.defines.map((d) => d.file));
60
130
  const functions = graph.defines.filter((d) => d.kind === "function" || d.kind === "method").length;
@@ -1 +1 @@
1
- {"version":3,"file":"analyses.js","sourceRoot":"","sources":["../../src/graph/analyses.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyses.js","sourceRoot":"","sources":["../../src/graph/analyses.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/graph/extractor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAkE,MAAM,YAAY,CAAC;AAE5G,8DAA8D;AAC9D,wBAAsB,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CA2CtG"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/graph/extractor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAkE,MAAM,YAAY,CAAC;AAE5G,8DAA8D;AAC9D,wBAAsB,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAkBtG"}
@@ -2,57 +2,80 @@ import { parseSource, parseSourceAsync, getLanguageForFile } from "./parser.js";
2
2
  import { getAdapter } from "./adapter-registry.js";
3
3
  /** Extract a unified call graph from multiple source files */
4
4
  export async function extractGraph(files) {
5
+ const partials = await Promise.all(files.map((file) => extractFileGraph(file)));
5
6
  const defines = [];
6
7
  const calls = [];
7
8
  const imports = [];
8
9
  const exports = [];
9
10
  const contains = [];
10
- for (const file of files) {
11
- const callSet = new Set(); // deduplicate caller→callee per file
12
- const lang = getLanguageForFile(file.path);
13
- if (!lang)
14
- continue;
15
- // Try sync first (CJS grammars), fall back to async (ESM grammars)
16
- const tree = parseSource(file.content, file.path)
17
- ?? await parseSourceAsync(file.content, file.path);
18
- if (!tree)
19
- continue;
20
- // Check for a registered adapter first
21
- const adapter = getAdapter(lang);
22
- if (adapter) {
23
- const partial = adapter.extract(tree.rootNode, file.path);
24
- for (const d of partial.defines)
25
- defines.push(d);
26
- for (const c of partial.calls) {
27
- const key = `${c.caller}->${c.callee}`;
28
- if (!callSet.has(key)) {
29
- callSet.add(key);
30
- calls.push(c);
31
- }
11
+ for (const p of partials) {
12
+ defines.push(...p.defines);
13
+ calls.push(...p.calls);
14
+ imports.push(...p.imports);
15
+ exports.push(...p.exports);
16
+ contains.push(...p.contains);
17
+ }
18
+ return { defines, calls, imports, exports, contains };
19
+ }
20
+ async function extractFileGraph(file) {
21
+ const defines = [];
22
+ const calls = [];
23
+ const imports = [];
24
+ const exports = [];
25
+ const contains = [];
26
+ const callSet = new Set();
27
+ const lang = getLanguageForFile(file.path);
28
+ if (!lang)
29
+ return { defines, calls, imports, exports, contains };
30
+ const tree = parseSource(file.content, file.path)
31
+ ?? await parseSourceAsync(file.content, file.path);
32
+ if (!tree)
33
+ return { defines, calls, imports, exports, contains };
34
+ try {
35
+ extractFromTree(tree, file.path, lang, defines, calls, imports, exports, contains, callSet);
36
+ }
37
+ finally {
38
+ // web-tree-sitter (WASM) trees must be explicitly freed or WASM memory
39
+ // grows monotonically. Native tree-sitter trees have no delete method
40
+ // and are GC'd normally — guard with optional chaining.
41
+ tree.delete?.();
42
+ }
43
+ return { defines, calls, imports, exports, contains };
44
+ }
45
+ function extractFromTree(tree, filePath, lang, defines, calls, imports, exports, contains, callSet) {
46
+ const adapter = getAdapter(lang);
47
+ if (adapter) {
48
+ const partial = adapter.extract(tree.rootNode, filePath);
49
+ for (const d of partial.defines)
50
+ defines.push(d);
51
+ for (const c of partial.calls) {
52
+ const key = `${c.caller}->${c.callee}`;
53
+ if (!callSet.has(key)) {
54
+ callSet.add(key);
55
+ calls.push(c);
32
56
  }
33
- for (const i of partial.imports)
34
- imports.push(i);
35
- for (const e of partial.exports)
36
- exports.push(e);
37
- for (const c of partial.contains ?? [])
38
- contains.push(c);
39
- }
40
- else if (lang === "clojure") {
41
- walkClojure(tree.rootNode, file.path, defines, calls, imports, exports, callSet);
42
- }
43
- else if (lang === "python") {
44
- const scopeStack = [];
45
- walkPython(tree.rootNode, file.path, scopeStack, defines, calls, imports, exports, contains, callSet);
46
- }
47
- else if (lang === "go") {
48
- walkGo(tree.rootNode, file.path, defines, calls, imports, exports, contains, callSet);
49
- }
50
- else {
51
- const scopeStack = [];
52
- walkNode(tree.rootNode, file.path, lang, scopeStack, defines, calls, imports, exports, contains, callSet);
53
57
  }
58
+ for (const i of partial.imports)
59
+ imports.push(i);
60
+ for (const e of partial.exports)
61
+ exports.push(e);
62
+ for (const c of partial.contains ?? [])
63
+ contains.push(c);
64
+ }
65
+ else if (lang === "clojure") {
66
+ walkClojure(tree.rootNode, filePath, defines, calls, imports, exports, callSet);
67
+ }
68
+ else if (lang === "python") {
69
+ const scopeStack = [];
70
+ walkPython(tree.rootNode, filePath, scopeStack, defines, calls, imports, exports, contains, callSet);
71
+ }
72
+ else if (lang === "go") {
73
+ walkGo(tree.rootNode, filePath, defines, calls, imports, exports, contains, callSet);
74
+ }
75
+ else {
76
+ const scopeStack = [];
77
+ walkNode(tree.rootNode, filePath, lang, scopeStack, defines, calls, imports, exports, contains, callSet);
54
78
  }
55
- return { defines, calls, imports, exports, contains };
56
79
  }
57
80
  function walkNode(node, filePath, language, scopeStack, defines, calls, imports, exports, contains, callSet) {
58
81
  const type = node.type;
@@ -219,12 +242,12 @@ function resolveCallee(callNode) {
219
242
  const property = fnNode.childForFieldName("property");
220
243
  return property?.text ?? null;
221
244
  }
222
- // Dynamic calls like obj[x]() — not statically resolvable
223
- case "subscript_expression":
224
- return null;
225
245
  default:
226
- // For other cases (e.g., IIFE, template literals), try the text if short
227
- return fnNode.text.length <= 50 ? fnNode.text : null;
246
+ // Dynamic/compound calls (subscript, IIFE, logical-or, tagged template,
247
+ // parenthesized expressions) can't be resolved statically. Emitting the
248
+ // raw text like "(a || b)" or "() => 1" just produces noise in the
249
+ // downstream facts, so drop them.
250
+ return null;
228
251
  }
229
252
  }
230
253
  /** Find the enclosing class name for a method node */
@@ -400,7 +423,7 @@ function resolvePythonCallee(callNode) {
400
423
  return attr?.text ?? null;
401
424
  }
402
425
  default:
403
- return fnNode.text.length <= 50 ? fnNode.text : null;
426
+ return null;
404
427
  }
405
428
  }
406
429
  /** Find the enclosing class name for a Python method node */
@@ -534,7 +557,7 @@ function resolveGoCallee(callNode) {
534
557
  return field?.text ?? null;
535
558
  }
536
559
  default:
537
- return fnNode.text.length <= 50 ? fnNode.text : null;
560
+ return null;
538
561
  }
539
562
  }
540
563
  /** Extract the receiver type name from a Go method receiver */
@@ -605,7 +628,7 @@ function cljDefnName(listNode) {
605
628
  return null;
606
629
  }
607
630
  /** Extract ns form: (ns foo.bar (:require [baz.qux :as q] [x.y :refer [z]])) */
608
- function cljExtractNs(listNode, filePath, imports, exports) {
631
+ function cljExtractNs(listNode, filePath, imports) {
609
632
  let symIdx = -1;
610
633
  for (let i = 0; i < listNode.childCount; i++) {
611
634
  if (listNode.child(i).type === "sym_lit") {
@@ -670,7 +693,7 @@ function walkClojure(rootNode, filePath, defines, calls, imports, exports, callS
670
693
  if (child.type !== "list_lit")
671
694
  continue;
672
695
  // Check for ns form
673
- const nsName = cljExtractNs(child, filePath, imports, exports);
696
+ const nsName = cljExtractNs(child, filePath, imports);
674
697
  if (nsName)
675
698
  continue;
676
699
  // Check for defn/defn-
@@ -700,6 +723,33 @@ function walkClojure(rootNode, filePath, defines, calls, imports, exports, callS
700
723
  cljExtractCalls(child, defn.name, calls, callSet);
701
724
  }
702
725
  }
726
+ /**
727
+ * Clojure special forms and core macros that look like function calls in
728
+ * the AST (first position of a list_lit) but are not real call edges.
729
+ * Filtering these removes ~80% of the noise from cljExtractCalls output.
730
+ */
731
+ const CLJ_SPECIAL_FORMS = new Set([
732
+ // Core special forms
733
+ "def", "do", "fn", "fn*", "if", "let", "let*", "letfn", "letfn*",
734
+ "loop", "loop*", "monitor-enter", "monitor-exit", "new", "quote",
735
+ "recur", "set!", "throw", "try", "catch", "finally", "var",
736
+ // Definition macros
737
+ "defn", "defn-", "defmacro", "defmulti", "defmethod", "defprotocol",
738
+ "defrecord", "deftype", "definterface", "defonce", "defstruct",
739
+ // Control-flow / binding macros
740
+ "when", "when-not", "when-let", "when-some", "when-first",
741
+ "if-let", "if-some", "if-not",
742
+ "cond", "condp", "case",
743
+ "and", "or", "not",
744
+ "do", "doto", "dotimes", "doseq", "dorun", "doall",
745
+ "for", "while",
746
+ // Threading macros
747
+ "->", "->>", "as->", "some->", "some->>", "cond->", "cond->>",
748
+ // Misc
749
+ "declare", "comment", "assert", "lazy-seq", "delay", "force",
750
+ "binding", "locking", "sync", "with-open", "with-local-vars",
751
+ "with-meta", "with-redefs", "with-redefs-fn",
752
+ ]);
703
753
  /** Recursively extract function calls from a Clojure form */
704
754
  function cljExtractCalls(node, enclosingFn, calls, callSet) {
705
755
  for (let i = 0; i < node.childCount; i++) {
@@ -715,10 +765,12 @@ function cljExtractCalls(node, enclosingFn, calls, callSet) {
715
765
  if (callee.includes("/")) {
716
766
  callee = callee.split("/").pop();
717
767
  }
718
- const key = `${enclosingFn}->${callee}`;
719
- if (!callSet.has(key)) {
720
- callSet.add(key);
721
- calls.push({ caller: enclosingFn, callee });
768
+ if (!CLJ_SPECIAL_FORMS.has(callee)) {
769
+ const key = `${enclosingFn}->${callee}`;
770
+ if (!callSet.has(key)) {
771
+ callSet.add(key);
772
+ calls.push({ caller: enclosingFn, callee });
773
+ }
722
774
  }
723
775
  }
724
776
  break;