pi-shazam 0.1.0

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 (121) hide show
  1. package/dist/core/cache.d.ts +50 -0
  2. package/dist/core/cache.d.ts.map +1 -0
  3. package/dist/core/cache.js +116 -0
  4. package/dist/core/cache.js.map +1 -0
  5. package/dist/core/encoding.d.ts +25 -0
  6. package/dist/core/encoding.d.ts.map +1 -0
  7. package/dist/core/encoding.js +109 -0
  8. package/dist/core/encoding.js.map +1 -0
  9. package/dist/core/graph.d.ts +146 -0
  10. package/dist/core/graph.d.ts.map +1 -0
  11. package/dist/core/graph.js +224 -0
  12. package/dist/core/graph.js.map +1 -0
  13. package/dist/core/pagerank.d.ts +19 -0
  14. package/dist/core/pagerank.d.ts.map +1 -0
  15. package/dist/core/pagerank.js +106 -0
  16. package/dist/core/pagerank.js.map +1 -0
  17. package/dist/core/scanner.d.ts +19 -0
  18. package/dist/core/scanner.d.ts.map +1 -0
  19. package/dist/core/scanner.js +266 -0
  20. package/dist/core/scanner.js.map +1 -0
  21. package/dist/core/treesitter-queries.d.ts +19 -0
  22. package/dist/core/treesitter-queries.d.ts.map +1 -0
  23. package/dist/core/treesitter-queries.js +222 -0
  24. package/dist/core/treesitter-queries.js.map +1 -0
  25. package/dist/core/treesitter.d.ts +67 -0
  26. package/dist/core/treesitter.d.ts.map +1 -0
  27. package/dist/core/treesitter.js +624 -0
  28. package/dist/core/treesitter.js.map +1 -0
  29. package/dist/hooks/after-write.d.ts +32 -0
  30. package/dist/hooks/after-write.d.ts.map +1 -0
  31. package/dist/hooks/after-write.js +111 -0
  32. package/dist/hooks/after-write.js.map +1 -0
  33. package/dist/hooks/before-start.d.ts +23 -0
  34. package/dist/hooks/before-start.d.ts.map +1 -0
  35. package/dist/hooks/before-start.js +43 -0
  36. package/dist/hooks/before-start.js.map +1 -0
  37. package/dist/index.d.ts +13 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +106 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/lsp/client.d.ts +77 -0
  42. package/dist/lsp/client.d.ts.map +1 -0
  43. package/dist/lsp/client.js +355 -0
  44. package/dist/lsp/client.js.map +1 -0
  45. package/dist/lsp/manager.d.ts +85 -0
  46. package/dist/lsp/manager.d.ts.map +1 -0
  47. package/dist/lsp/manager.js +362 -0
  48. package/dist/lsp/manager.js.map +1 -0
  49. package/dist/lsp/servers.d.ts +43 -0
  50. package/dist/lsp/servers.d.ts.map +1 -0
  51. package/dist/lsp/servers.js +140 -0
  52. package/dist/lsp/servers.js.map +1 -0
  53. package/dist/lsp/setup.d.ts +24 -0
  54. package/dist/lsp/setup.d.ts.map +1 -0
  55. package/dist/lsp/setup.js +140 -0
  56. package/dist/lsp/setup.js.map +1 -0
  57. package/dist/tools/call_chain.d.ts +9 -0
  58. package/dist/tools/call_chain.d.ts.map +1 -0
  59. package/dist/tools/call_chain.js +151 -0
  60. package/dist/tools/call_chain.js.map +1 -0
  61. package/dist/tools/check.d.ts +18 -0
  62. package/dist/tools/check.d.ts.map +1 -0
  63. package/dist/tools/check.js +141 -0
  64. package/dist/tools/check.js.map +1 -0
  65. package/dist/tools/codequery.d.ts +19 -0
  66. package/dist/tools/codequery.d.ts.map +1 -0
  67. package/dist/tools/codequery.js +128 -0
  68. package/dist/tools/codequery.js.map +1 -0
  69. package/dist/tools/codesearch.d.ts +8 -0
  70. package/dist/tools/codesearch.d.ts.map +1 -0
  71. package/dist/tools/codesearch.js +101 -0
  72. package/dist/tools/codesearch.js.map +1 -0
  73. package/dist/tools/file_detail.d.ts +9 -0
  74. package/dist/tools/file_detail.d.ts.map +1 -0
  75. package/dist/tools/file_detail.js +125 -0
  76. package/dist/tools/file_detail.js.map +1 -0
  77. package/dist/tools/fix.d.ts +25 -0
  78. package/dist/tools/fix.d.ts.map +1 -0
  79. package/dist/tools/fix.js +257 -0
  80. package/dist/tools/fix.js.map +1 -0
  81. package/dist/tools/hotspots.d.ts +9 -0
  82. package/dist/tools/hotspots.d.ts.map +1 -0
  83. package/dist/tools/hotspots.js +107 -0
  84. package/dist/tools/hotspots.js.map +1 -0
  85. package/dist/tools/impact.d.ts +14 -0
  86. package/dist/tools/impact.d.ts.map +1 -0
  87. package/dist/tools/impact.js +160 -0
  88. package/dist/tools/impact.js.map +1 -0
  89. package/dist/tools/orphan.d.ts +9 -0
  90. package/dist/tools/orphan.d.ts.map +1 -0
  91. package/dist/tools/orphan.js +124 -0
  92. package/dist/tools/orphan.js.map +1 -0
  93. package/dist/tools/overview.d.ts +9 -0
  94. package/dist/tools/overview.d.ts.map +1 -0
  95. package/dist/tools/overview.js +137 -0
  96. package/dist/tools/overview.js.map +1 -0
  97. package/dist/tools/ready.d.ts +18 -0
  98. package/dist/tools/ready.d.ts.map +1 -0
  99. package/dist/tools/ready.js +145 -0
  100. package/dist/tools/ready.js.map +1 -0
  101. package/dist/tools/refs.d.ts +9 -0
  102. package/dist/tools/refs.d.ts.map +1 -0
  103. package/dist/tools/refs.js +129 -0
  104. package/dist/tools/refs.js.map +1 -0
  105. package/dist/tools/routes.d.ts +8 -0
  106. package/dist/tools/routes.d.ts.map +1 -0
  107. package/dist/tools/routes.js +83 -0
  108. package/dist/tools/routes.js.map +1 -0
  109. package/dist/tools/state_map.d.ts +8 -0
  110. package/dist/tools/state_map.d.ts.map +1 -0
  111. package/dist/tools/state_map.js +95 -0
  112. package/dist/tools/state_map.js.map +1 -0
  113. package/dist/tools/symbol.d.ts +9 -0
  114. package/dist/tools/symbol.d.ts.map +1 -0
  115. package/dist/tools/symbol.js +84 -0
  116. package/dist/tools/symbol.js.map +1 -0
  117. package/dist/tools/verify.d.ts +24 -0
  118. package/dist/tools/verify.d.ts.map +1 -0
  119. package/dist/tools/verify.js +212 -0
  120. package/dist/tools/verify.js.map +1 -0
  121. package/package.json +70 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * pi-shazam core/graph — Symbol dependency graph data model.
3
+ *
4
+ * Ported from repomap/src/__init__.py (Symbol, Edge, RepoGraph dataclasses).
5
+ * All other core/ modules depend on these types.
6
+ */
7
+ // ── Factory ──────────────────────────────────────────────────────────────────
8
+ export function createRepoGraph() {
9
+ return {
10
+ symbols: new Map(),
11
+ outgoing: new Map(),
12
+ incoming: new Map(),
13
+ fileSymbols: new Map(),
14
+ fileImports: new Map(),
15
+ fileCalls: new Map(),
16
+ fileImportBindings: new Map(),
17
+ fileExports: new Map(),
18
+ };
19
+ }
20
+ // ── Symbol factory ───────────────────────────────────────────────────────────
21
+ export function createSymbol(id, name, kind, file, line, overrides = {}) {
22
+ return {
23
+ id,
24
+ name,
25
+ kind,
26
+ file,
27
+ line,
28
+ endLine: overrides.endLine ?? line,
29
+ col: overrides.col ?? 0,
30
+ visibility: overrides.visibility ?? "public",
31
+ docstring: overrides.docstring ?? "",
32
+ signature: overrides.signature ?? "",
33
+ returnType: overrides.returnType ?? "",
34
+ params: overrides.params ?? "",
35
+ pagerank: overrides.pagerank ?? 0.0,
36
+ };
37
+ }
38
+ // ── Edge factory ─────────────────────────────────────────────────────────────
39
+ export function createEdge(source, target, weight, kind, confidence = 1.0) {
40
+ return { source, target, weight, kind, confidence };
41
+ }
42
+ export function serializeSymbol(sym) {
43
+ return {
44
+ id: sym.id,
45
+ name: sym.name,
46
+ kind: sym.kind,
47
+ file: sym.file,
48
+ line: sym.line,
49
+ endLine: sym.endLine,
50
+ col: sym.col,
51
+ visibility: sym.visibility,
52
+ signature: sym.signature,
53
+ returnType: sym.returnType,
54
+ params: sym.params,
55
+ docstring: sym.docstring,
56
+ pagerank: sym.pagerank,
57
+ };
58
+ }
59
+ export function serializeEdge(edge) {
60
+ return {
61
+ source: edge.source,
62
+ target: edge.target,
63
+ weight: edge.weight,
64
+ kind: edge.kind,
65
+ };
66
+ }
67
+ export function serializeGraph(graph) {
68
+ const symbols = [];
69
+ for (const sym of graph.symbols.values()) {
70
+ symbols.push(serializeSymbol(sym));
71
+ }
72
+ const edges = [];
73
+ for (const [, edgeList] of graph.outgoing) {
74
+ for (const edge of edgeList) {
75
+ edges.push(serializeEdge(edge));
76
+ }
77
+ }
78
+ return {
79
+ symbols,
80
+ edges,
81
+ version: 1,
82
+ timestamp: Date.now(),
83
+ };
84
+ }
85
+ function edgeIdentity(edge) {
86
+ return `${edge.source}|${edge.target}|${edge.kind}`;
87
+ }
88
+ function edgeIdentityFromRow(row) {
89
+ return `${row.source}|${row.target}|${row.kind}`;
90
+ }
91
+ function stableKey(sym) {
92
+ return `${sym.file}::${sym.name}::${sym.kind}`;
93
+ }
94
+ export function compareGraphSnapshots(currentSymbols, currentEdges, previousSymbols, previousEdges) {
95
+ const currentSymMap = new Map(currentSymbols.map((s) => [s.id, s]));
96
+ const prevSymMap = new Map(previousSymbols.map((s) => [s.id, s]));
97
+ const currentIds = new Set(currentSymMap.keys());
98
+ const prevIds = new Set(prevSymMap.keys());
99
+ let addedIds = [...currentIds].filter((id) => !prevIds.has(id));
100
+ let removedIds = [...prevIds].filter((id) => !currentIds.has(id));
101
+ // Stable key matching for line-drift reconciliation
102
+ const addedByKey = new Map();
103
+ for (const sid of addedIds) {
104
+ const s = currentSymMap.get(sid);
105
+ const key = stableKey(s);
106
+ const arr = addedByKey.get(key) || [];
107
+ arr.push(sid);
108
+ addedByKey.set(key, arr);
109
+ }
110
+ const removedByKey = new Map();
111
+ for (const sid of removedIds) {
112
+ const s = prevSymMap.get(sid);
113
+ const key = stableKey(s);
114
+ const arr = removedByKey.get(key) || [];
115
+ arr.push(sid);
116
+ removedByKey.set(key, arr);
117
+ }
118
+ const reconciledPairs = [];
119
+ for (const [key, adds] of addedByKey) {
120
+ const rems = removedByKey.get(key) || [];
121
+ for (let i = 0; i < Math.min(adds.length, rems.length); i++) {
122
+ reconciledPairs.push([rems[i], adds[i]]);
123
+ }
124
+ }
125
+ const reconciledAdded = new Set(reconciledPairs.map((p) => p[1]));
126
+ const reconciledRemoved = new Set(reconciledPairs.map((p) => p[0]));
127
+ addedIds = addedIds.filter((id) => !reconciledAdded.has(id));
128
+ removedIds = removedIds.filter((id) => !reconciledRemoved.has(id));
129
+ // Modified: same ID, signature or location changed
130
+ const commonIds = [...currentIds].filter((id) => prevIds.has(id));
131
+ const modifiedSymbols = [];
132
+ for (const id of commonIds) {
133
+ const cur = currentSymMap.get(id);
134
+ const prev = prevSymMap.get(id);
135
+ const sigChanged = cur.signature !== prev.signature;
136
+ const locChanged = cur.line !== prev.line ||
137
+ cur.endLine !== prev.endLine ||
138
+ cur.file !== prev.file;
139
+ if (sigChanged || locChanged) {
140
+ modifiedSymbols.push({
141
+ id: cur.id,
142
+ name: cur.name,
143
+ file: cur.file,
144
+ visibility: cur.visibility,
145
+ kind: cur.kind,
146
+ lineChange: `${prev.line} -> ${cur.line}`,
147
+ oldSignature: prev.signature,
148
+ newSignature: cur.signature,
149
+ signatureChanged: sigChanged,
150
+ risk: sigChanged ? "HIGH" : "LOW",
151
+ });
152
+ }
153
+ }
154
+ // Reconciled pairs as modified
155
+ for (const [prevId, curId] of reconciledPairs) {
156
+ const cur = currentSymMap.get(curId);
157
+ const prev = prevSymMap.get(prevId);
158
+ const sigChanged = cur.signature !== prev.signature;
159
+ modifiedSymbols.push({
160
+ id: cur.id,
161
+ name: cur.name,
162
+ file: cur.file,
163
+ visibility: cur.visibility,
164
+ kind: cur.kind,
165
+ lineChange: `${prev.line} -> ${cur.line}`,
166
+ oldSignature: prev.signature,
167
+ newSignature: cur.signature,
168
+ signatureChanged: sigChanged,
169
+ risk: sigChanged ? "HIGH" : "LOW",
170
+ });
171
+ }
172
+ // Edge changes
173
+ const currentEdgeSet = new Set(currentEdges.map(edgeIdentity));
174
+ const prevEdgeSet = new Set(previousEdges.map(edgeIdentityFromRow));
175
+ const edgesAdded = [...currentEdgeSet].filter((e) => !prevEdgeSet.has(e));
176
+ const edgesRemoved = [...prevEdgeSet].filter((e) => !currentEdgeSet.has(e));
177
+ return {
178
+ summary: {
179
+ added: addedIds.length,
180
+ removed: removedIds.length,
181
+ modified: modifiedSymbols.length,
182
+ edgesAdded: edgesAdded.length,
183
+ edgesRemoved: edgesRemoved.length,
184
+ },
185
+ addedSymbols: addedIds.map((id) => {
186
+ const s = currentSymMap.get(id);
187
+ return { id: s.id, name: s.name, file: s.file, line: s.line };
188
+ }),
189
+ removedSymbols: removedIds.map((id) => {
190
+ const s = prevSymMap.get(id);
191
+ return { id: s.id, name: s.name, file: s.file, line: s.line };
192
+ }),
193
+ modifiedSymbols,
194
+ callChainChanges: {
195
+ newCalls: edgesAdded.slice(0, 20).map((e) => {
196
+ const [from, to, kind] = e.split("|");
197
+ return { from, to, kind };
198
+ }),
199
+ removedCalls: edgesRemoved.slice(0, 20).map((e) => {
200
+ const [from, to, kind] = e.split("|");
201
+ return { from, to, kind };
202
+ }),
203
+ },
204
+ };
205
+ }
206
+ // ── Constants ────────────────────────────────────────────────────────────────
207
+ export const LOW_SIGNAL_KINDS = new Set([
208
+ "element",
209
+ "selector",
210
+ "class_selector",
211
+ "id_selector",
212
+ "json_key",
213
+ ]);
214
+ export const BOILERPLATE_NAMES = new Set(["__init__", "__main__"]);
215
+ export function signalWeightForSymbol(kind, name, visibility) {
216
+ if (LOW_SIGNAL_KINDS.has(kind))
217
+ return 0.002;
218
+ if (BOILERPLATE_NAMES.has(name))
219
+ return 0.35;
220
+ if (name.startsWith("_") && visibility === "private")
221
+ return 0.85;
222
+ return 1.0;
223
+ }
224
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../core/graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4DH,gFAAgF;AAEhF,MAAM,UAAU,eAAe;IAC9B,OAAO;QACN,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,WAAW,EAAE,IAAI,GAAG,EAAE;QACtB,WAAW,EAAE,IAAI,GAAG,EAAE;QACtB,SAAS,EAAE,IAAI,GAAG,EAAE;QACpB,kBAAkB,EAAE,IAAI,GAAG,EAAE;QAC7B,WAAW,EAAE,IAAI,GAAG,EAAE;KACtB,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,YAAY,CAC3B,EAAU,EACV,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,YAA6B,EAAE;IAE/B,OAAO;QACN,EAAE;QACF,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,IAAI;QAClC,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC;QACvB,UAAU,EAAE,SAAS,CAAC,UAAU,IAAI,QAAQ;QAC5C,SAAS,EAAE,SAAS,CAAC,SAAS,IAAI,EAAE;QACpC,SAAS,EAAE,SAAS,CAAC,SAAS,IAAI,EAAE;QACpC,UAAU,EAAE,SAAS,CAAC,UAAU,IAAI,EAAE;QACtC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,EAAE;QAC9B,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,GAAG;KACnC,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,UAAU,CACzB,MAAc,EACd,MAAc,EACd,MAAc,EACd,IAAY,EACZ,aAAqB,GAAG;IAExB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AACrD,CAAC;AAkCD,MAAM,UAAU,eAAe,CAAC,GAAW;IAC1C,OAAO;QACN,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACtB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAU;IACvC,OAAO;QACN,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;KACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC9C,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,KAAK,GAAqB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IACD,OAAO;QACN,OAAO;QACP,KAAK;QACL,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;AACH,CAAC;AAoCD,SAAS,YAAY,CAAC,IAAU;IAC/B,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAmB;IAC/C,OAAO,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,SAAS,CAAC,GAAiD;IACnE,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,qBAAqB,CACpC,cAAwB,EACxB,YAAoB,EACpB,eAAmC,EACnC,aAA+B;IAE/B,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAElE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAE3C,IAAI,QAAQ,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,IAAI,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAElE,oDAAoD;IACpD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC/C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAClC,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACtC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;IACjD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACd,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,eAAe,GAAuB,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7D,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IACD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnE,mDAAmD;IACnD,MAAM,SAAS,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,eAAe,GAAqB,EAAE,CAAC;IAC7C,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;QACnC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;QACjC,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC;QACpD,MAAM,UAAU,GACf,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;YACtB,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;YAC5B,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;QACxB,IAAI,UAAU,IAAI,UAAU,EAAE,CAAC;YAC9B,eAAe,CAAC,IAAI,CAAC;gBACpB,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,UAAU,EAAE,GAAG,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,EAAE;gBACzC,YAAY,EAAE,IAAI,CAAC,SAAS;gBAC5B,YAAY,EAAE,GAAG,CAAC,SAAS;gBAC3B,gBAAgB,EAAE,UAAU;gBAC5B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;aACjC,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,+BAA+B;IAC/B,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,eAAe,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC;QACtC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;QACrC,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC;QACpD,eAAe,CAAC,IAAI,CAAC;YACpB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,UAAU,EAAE,GAAG,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,EAAE;YACzC,YAAY,EAAE,IAAI,CAAC,SAAS;YAC5B,YAAY,EAAE,GAAG,CAAC,SAAS;YAC3B,gBAAgB,EAAE,UAAU;YAC5B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;SACjC,CAAC,CAAC;IACJ,CAAC;IAED,eAAe;IACf,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAEpE,MAAM,UAAU,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,YAAY,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5E,OAAO;QACN,OAAO,EAAE;YACR,KAAK,EAAE,QAAQ,CAAC,MAAM;YACtB,OAAO,EAAE,UAAU,CAAC,MAAM;YAC1B,QAAQ,EAAE,eAAe,CAAC,MAAM;YAChC,UAAU,EAAE,UAAU,CAAC,MAAM;YAC7B,YAAY,EAAE,YAAY,CAAC,MAAM;SACjC;QACD,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YACjC,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,CAAC,CAAC;QACF,cAAc,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YACrC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YAC9B,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,CAAC,CAAC;QACF,eAAe;QACf,gBAAgB,EAAE;YACjB,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC3C,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC,CAAC;YACF,YAAY,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACjD,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC,CAAC;SACF;KACD,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IACvC,SAAS;IACT,UAAU;IACV,gBAAgB;IAChB,aAAa;IACb,UAAU;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAEnE,MAAM,UAAU,qBAAqB,CACpC,IAAY,EACZ,IAAY,EACZ,UAAkB;IAElB,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAClE,OAAO,GAAG,CAAC;AACZ,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * pi-shazam core/pagerank — PageRank importance scoring on RepoGraph.
3
+ *
4
+ * Ported from repomap/src/ranking.py (GraphAnalyzer.calculate_pagerank).
5
+ *
6
+ * The algorithm is pure iterative PageRank with convergence detection.
7
+ * No external dependencies beyond the graph data model.
8
+ */
9
+ import type { RepoGraph } from "./graph.js";
10
+ /**
11
+ * Calculate PageRank scores for all symbols in the graph.
12
+ * Scores are stored directly on each symbol's `.pagerank` field.
13
+ *
14
+ * Damping factor: 0.85 (standard PageRank)
15
+ * Max iterations: 50
16
+ * Convergence tolerance: 1e-6
17
+ */
18
+ export declare function calculatePageRank(graph: RepoGraph, damping?: number, maxIter?: number, tol?: number): void;
19
+ //# sourceMappingURL=pagerank.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagerank.d.ts","sourceRoot":"","sources":["../../core/pagerank.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,MAAa,EACtB,OAAO,GAAE,MAAW,EACpB,GAAG,GAAE,MAAa,GAChB,IAAI,CAgGN"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * pi-shazam core/pagerank — PageRank importance scoring on RepoGraph.
3
+ *
4
+ * Ported from repomap/src/ranking.py (GraphAnalyzer.calculate_pagerank).
5
+ *
6
+ * The algorithm is pure iterative PageRank with convergence detection.
7
+ * No external dependencies beyond the graph data model.
8
+ */
9
+ /**
10
+ * Calculate PageRank scores for all symbols in the graph.
11
+ * Scores are stored directly on each symbol's `.pagerank` field.
12
+ *
13
+ * Damping factor: 0.85 (standard PageRank)
14
+ * Max iterations: 50
15
+ * Convergence tolerance: 1e-6
16
+ */
17
+ export function calculatePageRank(graph, damping = 0.85, maxIter = 50, tol = 1e-6) {
18
+ const ids = [...graph.symbols.keys()];
19
+ const n = ids.length;
20
+ if (n === 0)
21
+ return;
22
+ // Initial uniform distribution
23
+ const pr = new Map();
24
+ for (const id of ids) {
25
+ pr.set(id, 1.0 / n);
26
+ }
27
+ // Compute outgoing weight sums
28
+ const outW = new Map();
29
+ for (const id of ids) {
30
+ const edges = graph.outgoing.get(id);
31
+ if (!edges || edges.length === 0) {
32
+ outW.set(id, 0);
33
+ continue;
34
+ }
35
+ let sum = 0;
36
+ for (const e of edges) {
37
+ sum += e.weight;
38
+ }
39
+ outW.set(id, sum);
40
+ }
41
+ // Active sources: nodes with positive outgoing weight
42
+ const activeSrcs = new Set();
43
+ for (const id of ids) {
44
+ const w = outW.get(id) || 0;
45
+ if (w > 0 && !isNaN(w) && isFinite(w)) {
46
+ activeSrcs.add(id);
47
+ }
48
+ }
49
+ // Build incoming index: tgt -> [(src, weight), ...]
50
+ const inc = new Map();
51
+ for (const [src, edges] of graph.outgoing) {
52
+ if (!activeSrcs.has(src))
53
+ continue;
54
+ for (const e of edges) {
55
+ const arr = inc.get(e.target) || [];
56
+ arr.push([src, e.weight]);
57
+ inc.set(e.target, arr);
58
+ }
59
+ }
60
+ const base = (1 - damping) / n;
61
+ for (let iter = 0; iter < maxIter; iter++) {
62
+ const newPr = new Map();
63
+ for (const id of ids) {
64
+ let score = base;
65
+ const incoming = inc.get(id);
66
+ if (incoming) {
67
+ for (const [src, w] of incoming) {
68
+ const srcPr = pr.get(src) || 0;
69
+ const srcOutW = outW.get(src) || 1;
70
+ score += (damping * srcPr * w) / srcOutW;
71
+ }
72
+ }
73
+ newPr.set(id, score);
74
+ }
75
+ // Normalize
76
+ let total = 0;
77
+ for (const score of newPr.values()) {
78
+ total += score;
79
+ }
80
+ total = total || 1.0;
81
+ for (const [id, score] of newPr) {
82
+ newPr.set(id, score / total);
83
+ }
84
+ // Convergence check
85
+ let delta = 0;
86
+ for (const id of ids) {
87
+ const oldScore = pr.get(id) || 0;
88
+ const newScore = newPr.get(id) || 0;
89
+ delta = Math.max(delta, Math.abs(newScore - oldScore));
90
+ }
91
+ // Update pr for next iteration
92
+ for (const [id, score] of newPr) {
93
+ pr.set(id, score);
94
+ }
95
+ if (delta < tol)
96
+ break;
97
+ }
98
+ // Store scores back on symbols
99
+ for (const [id, score] of pr) {
100
+ const sym = graph.symbols.get(id);
101
+ if (sym) {
102
+ sym.pagerank = score;
103
+ }
104
+ }
105
+ }
106
+ //# sourceMappingURL=pagerank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagerank.js","sourceRoot":"","sources":["../../core/pagerank.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * pi-shazam core/scanner — Project scanning + graph building.
3
+ *
4
+ * Walks project directories, parses source files with tree-sitter,
5
+ * extracts symbols/imports/calls, and builds the full RepoGraph.
6
+ *
7
+ * This is the main entry point that all tools compose from.
8
+ */
9
+ import type { RepoGraph } from "./graph.js";
10
+ /**
11
+ * Scan a project directory, parse all source files, build the dependency graph,
12
+ * and compute PageRank scores.
13
+ *
14
+ * @param projectPath - Absolute or relative path to the project root
15
+ * @param log - Optional logger
16
+ * @returns The fully built RepoGraph with PageRank scores set
17
+ */
18
+ export declare function scanProject(projectPath: string, log?: (msg: string) => void): RepoGraph;
19
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../core/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,YAAY,CAAC;AAgC1D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAC1B,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACzB,SAAS,CAuIX"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * pi-shazam core/scanner — Project scanning + graph building.
3
+ *
4
+ * Walks project directories, parses source files with tree-sitter,
5
+ * extracts symbols/imports/calls, and builds the full RepoGraph.
6
+ *
7
+ * This is the main entry point that all tools compose from.
8
+ */
9
+ import { readdirSync } from "node:fs";
10
+ import { join, relative, resolve } from "node:path";
11
+ import { TreeSitterAdapter, EXT_TO_LANG } from "./treesitter.js";
12
+ import { createRepoGraph, createEdge, } from "./graph.js";
13
+ import { calculatePageRank } from "./pagerank.js";
14
+ import { readFileAdaptive } from "./encoding.js";
15
+ // ── Constants ────────────────────────────────────────────────────────────────
16
+ /** Directories to skip during project scan */
17
+ const SKIP_DIRS = new Set([
18
+ "node_modules",
19
+ "dist",
20
+ ".git",
21
+ ".worktrees",
22
+ ".cache",
23
+ ".pi-shazam",
24
+ ".qoder",
25
+ "__pycache__",
26
+ "target", // Rust
27
+ ".venv",
28
+ "venv",
29
+ ".tox",
30
+ "coverage",
31
+ ".nyc_output",
32
+ ]);
33
+ /** Maximum files to scan (safety limit) */
34
+ const MAX_FILES = 20_000;
35
+ /** File extensions to scan */
36
+ const SOURCE_EXTS = new Set(Object.keys(EXT_TO_LANG));
37
+ // ── Scanner ──────────────────────────────────────────────────────────────────
38
+ /**
39
+ * Scan a project directory, parse all source files, build the dependency graph,
40
+ * and compute PageRank scores.
41
+ *
42
+ * @param projectPath - Absolute or relative path to the project root
43
+ * @param log - Optional logger
44
+ * @returns The fully built RepoGraph with PageRank scores set
45
+ */
46
+ export function scanProject(projectPath, log) {
47
+ const root = resolve(projectPath);
48
+ const logger = log ?? (() => { });
49
+ const adapter = new TreeSitterAdapter(logger);
50
+ const graph = createRepoGraph();
51
+ // Collect all source files
52
+ const files = collectSourceFiles(root, MAX_FILES);
53
+ logger(`Scanned ${files.length} source files`);
54
+ // Phase 1: Extract symbols from all files
55
+ const fileSymbolMap = new Map();
56
+ for (const relPath of files) {
57
+ const absPath = join(root, relPath);
58
+ const ext = relPath.slice(relPath.lastIndexOf(".")).toLowerCase();
59
+ const lang = EXT_TO_LANG[ext];
60
+ if (!lang)
61
+ continue;
62
+ try {
63
+ const source = readFileAdaptive(absPath);
64
+ const tree = adapter.parse(source, lang);
65
+ if (!tree)
66
+ continue;
67
+ const symbols = adapter.extractSymbols(tree, lang, relPath);
68
+ fileSymbolMap.set(relPath, symbols);
69
+ for (const sym of symbols) {
70
+ graph.symbols.set(sym.id, sym);
71
+ const fileSyms = graph.fileSymbols.get(relPath) || [];
72
+ fileSyms.push(sym.id);
73
+ graph.fileSymbols.set(relPath, fileSyms);
74
+ }
75
+ }
76
+ catch {
77
+ // Skip unparseable files
78
+ }
79
+ }
80
+ logger(`Extracted ${graph.symbols.size} symbols`);
81
+ // Phase 2: Extract imports and calls, build edges
82
+ for (const relPath of files) {
83
+ const absPath = join(root, relPath);
84
+ const ext = relPath.slice(relPath.lastIndexOf(".")).toLowerCase();
85
+ const lang = EXT_TO_LANG[ext];
86
+ if (!lang)
87
+ continue;
88
+ try {
89
+ const source = readFileAdaptive(absPath);
90
+ const tree = adapter.parse(source, lang);
91
+ if (!tree)
92
+ continue;
93
+ // Import edges: file-level imports → link imported symbols to files
94
+ const imports = adapter.extractImports(tree, lang);
95
+ if (imports.length > 0) {
96
+ graph.fileImports.set(relPath, imports.map(([m]) => m));
97
+ // Create edges from this file's symbols to symbols in imported files
98
+ const thisFileSyms = graph.fileSymbols.get(relPath) || [];
99
+ for (const [importedModule] of imports) {
100
+ const resolvedImport = resolveImport(importedModule, relPath);
101
+ const targetFileSyms = graph.fileSymbols.get(resolvedImport) || [];
102
+ for (const srcId of thisFileSyms) {
103
+ for (const tgtId of targetFileSyms) {
104
+ addEdge(graph, createEdge(srcId, tgtId, 0.3, "import", 0.5));
105
+ }
106
+ }
107
+ }
108
+ }
109
+ // Call edges: function calls → link caller to callee
110
+ const calls = adapter.extractCalls(tree, lang);
111
+ if (calls.length > 0) {
112
+ graph.fileCalls.set(relPath, calls);
113
+ const thisFileSyms = graph.fileSymbols.get(relPath) || [];
114
+ for (const [calledName, callLine] of calls) {
115
+ // Find the most specific symbol in this file that could be the caller
116
+ // (the symbol definition that contains this call line)
117
+ const callerSyms = findCallerSymbols(thisFileSyms, graph.symbols, callLine);
118
+ // Find callee symbols across the entire project
119
+ const calleeSyms = findCalleeSymbols(calledName, graph.symbols);
120
+ for (const caller of callerSyms) {
121
+ for (const callee of calleeSyms) {
122
+ if (caller.id !== callee.id) {
123
+ addEdge(graph, createEdge(caller.id, callee.id, 1.0, "call", 0.9));
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ // JS/TS import bindings (precise symbol-level imports)
130
+ const jsImports = adapter.extractJsTsImportBindings(tree, lang);
131
+ if (jsImports.length > 0) {
132
+ graph.fileImportBindings.set(relPath, jsImports);
133
+ for (const binding of jsImports) {
134
+ // Find the local symbol that represents this import binding
135
+ const localSym = findSymbolByNameInFile(binding.localName, relPath, graph.symbols);
136
+ if (!localSym)
137
+ continue;
138
+ // Find the source symbol in the imported module
139
+ const resolvedModule = resolveImport(binding.module, relPath);
140
+ const sourceSym = findSymbolByNameInFile(binding.importedName, resolvedModule, graph.symbols);
141
+ if (sourceSym) {
142
+ addEdge(graph, createEdge(localSym.id, sourceSym.id, 0.8, "import-binding", 1.0));
143
+ }
144
+ }
145
+ }
146
+ }
147
+ catch {
148
+ // Skip unparseable files
149
+ }
150
+ }
151
+ // Phase 3: Compute PageRank
152
+ calculatePageRank(graph);
153
+ return graph;
154
+ }
155
+ // ── File collection ──────────────────────────────────────────────────────────
156
+ function collectSourceFiles(root, maxFiles) {
157
+ const files = [];
158
+ function walk(dir) {
159
+ if (files.length >= maxFiles)
160
+ return;
161
+ let entries;
162
+ try {
163
+ entries = readdirSync(dir, { withFileTypes: true });
164
+ }
165
+ catch {
166
+ return;
167
+ }
168
+ for (const entry of entries) {
169
+ if (files.length >= maxFiles)
170
+ return;
171
+ const relPath = relative(root, join(dir, entry.name));
172
+ if (entry.isDirectory()) {
173
+ if (SKIP_DIRS.has(entry.name))
174
+ continue;
175
+ if (entry.name.startsWith(".") && !SKIP_DIRS.has(entry.name))
176
+ continue;
177
+ walk(join(dir, entry.name));
178
+ }
179
+ else if (entry.isFile()) {
180
+ const ext = entry.name.slice(entry.name.lastIndexOf(".")).toLowerCase();
181
+ if (SOURCE_EXTS.has(ext)) {
182
+ files.push(relPath);
183
+ }
184
+ }
185
+ }
186
+ }
187
+ walk(root);
188
+ return files;
189
+ }
190
+ // ── Edge helpers ─────────────────────────────────────────────────────────────
191
+ function addEdge(graph, edge) {
192
+ const outgoing = graph.outgoing.get(edge.source) || [];
193
+ outgoing.push(edge);
194
+ graph.outgoing.set(edge.source, outgoing);
195
+ const incoming = graph.incoming.get(edge.target) || [];
196
+ incoming.push(edge);
197
+ graph.incoming.set(edge.target, incoming);
198
+ }
199
+ // ── Import resolution ─────────────────────────────────────────────────────────
200
+ /**
201
+ * Resolve a relative import path to a file path that matches the fileSymbols keys.
202
+ * Handles extensionless imports (e.g., "./foo" → "./foo.ts" or "./foo/index.ts").
203
+ */
204
+ function resolveImport(importPath, fromFile) {
205
+ // If it's a relative import, resolve against the fromFile's directory
206
+ if (importPath.startsWith(".")) {
207
+ const fromDir = fromFile.includes("/")
208
+ ? fromFile.slice(0, fromFile.lastIndexOf("/"))
209
+ : ".";
210
+ let resolved = join(fromDir, importPath);
211
+ // Try common extensions and index files
212
+ const candidates = [
213
+ resolved,
214
+ `${resolved}.ts`,
215
+ `${resolved}.tsx`,
216
+ `${resolved}.js`,
217
+ `${resolved}.jsx`,
218
+ `${resolved}/index.ts`,
219
+ `${resolved}/index.tsx`,
220
+ `${resolved}/index.js`,
221
+ ];
222
+ return candidates[0];
223
+ }
224
+ // For bare module imports (e.g., "react", "lodash"), we can't resolve
225
+ // them to project files, so we return the import path as-is
226
+ return importPath;
227
+ }
228
+ // ── Symbol lookup helpers ────────────────────────────────────────────────────
229
+ function findCallerSymbols(fileSymIds, symbols, callLine) {
230
+ // Find symbols in the file that contain this call line within their range
231
+ const candidates = [];
232
+ for (const id of fileSymIds) {
233
+ const sym = symbols.get(id);
234
+ if (!sym)
235
+ continue;
236
+ if (sym.line <= callLine && callLine <= sym.endLine) {
237
+ candidates.push(sym);
238
+ }
239
+ }
240
+ // Return the most specific (narrowest range) match first
241
+ candidates.sort((a, b) => {
242
+ const aRange = a.endLine - a.line;
243
+ const bRange = b.endLine - b.line;
244
+ return aRange - bRange || a.line - b.line;
245
+ });
246
+ // Return the most specific one
247
+ return candidates.length > 0 ? [candidates[0]] : [];
248
+ }
249
+ function findCalleeSymbols(name, symbols) {
250
+ const results = [];
251
+ for (const sym of symbols.values()) {
252
+ if (sym.name === name) {
253
+ results.push(sym);
254
+ }
255
+ }
256
+ return results;
257
+ }
258
+ function findSymbolByNameInFile(name, file, symbols) {
259
+ for (const sym of symbols.values()) {
260
+ if (sym.file === file && sym.name === name) {
261
+ return sym;
262
+ }
263
+ }
264
+ return undefined;
265
+ }
266
+ //# sourceMappingURL=scanner.js.map