ghagga-core 3.2.0 → 3.4.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 (139) hide show
  1. package/dist/acp/adapter.d.ts.map +1 -1
  2. package/dist/acp/adapter.js +8 -1
  3. package/dist/acp/adapter.js.map +1 -1
  4. package/dist/agents/consensus.d.ts +2 -2
  5. package/dist/agents/consensus.d.ts.map +1 -1
  6. package/dist/agents/consensus.js +13 -5
  7. package/dist/agents/consensus.js.map +1 -1
  8. package/dist/agents/fan-out-lenses.d.ts +33 -2
  9. package/dist/agents/fan-out-lenses.d.ts.map +1 -1
  10. package/dist/agents/fan-out-lenses.js +245 -8
  11. package/dist/agents/fan-out-lenses.js.map +1 -1
  12. package/dist/agents/issue-code-discovery.d.ts +58 -0
  13. package/dist/agents/issue-code-discovery.d.ts.map +1 -0
  14. package/dist/agents/issue-code-discovery.js +144 -0
  15. package/dist/agents/issue-code-discovery.js.map +1 -0
  16. package/dist/agents/issue-triage.d.ts +153 -0
  17. package/dist/agents/issue-triage.d.ts.map +1 -0
  18. package/dist/agents/issue-triage.js +279 -0
  19. package/dist/agents/issue-triage.js.map +1 -0
  20. package/dist/agents/prompts.d.ts +50 -1
  21. package/dist/agents/prompts.d.ts.map +1 -1
  22. package/dist/agents/prompts.js +142 -2
  23. package/dist/agents/prompts.js.map +1 -1
  24. package/dist/agents/simple.d.ts.map +1 -1
  25. package/dist/agents/simple.js +1 -1
  26. package/dist/agents/simple.js.map +1 -1
  27. package/dist/agents/voice-validation.d.ts +34 -0
  28. package/dist/agents/voice-validation.d.ts.map +1 -0
  29. package/dist/agents/voice-validation.js +64 -0
  30. package/dist/agents/voice-validation.js.map +1 -0
  31. package/dist/agents/workflow.d.ts.map +1 -1
  32. package/dist/agents/workflow.js +8 -0
  33. package/dist/agents/workflow.js.map +1 -1
  34. package/dist/critique/critique.js +1 -1
  35. package/dist/critique/critique.js.map +1 -1
  36. package/dist/critique/prompts.d.ts +1 -1
  37. package/dist/critique/prompts.d.ts.map +1 -1
  38. package/dist/critique/prompts.js +1 -1
  39. package/dist/enhance/prompt.d.ts +1 -1
  40. package/dist/enhance/prompt.d.ts.map +1 -1
  41. package/dist/explanation.d.ts +69 -0
  42. package/dist/explanation.d.ts.map +1 -0
  43. package/dist/explanation.js +16 -0
  44. package/dist/explanation.js.map +1 -0
  45. package/dist/format.d.ts.map +1 -1
  46. package/dist/format.js +1 -0
  47. package/dist/format.js.map +1 -1
  48. package/dist/graph/builder.d.ts +13 -1
  49. package/dist/graph/builder.d.ts.map +1 -1
  50. package/dist/graph/builder.js +305 -6
  51. package/dist/graph/builder.js.map +1 -1
  52. package/dist/graph/call-chain.d.ts +27 -0
  53. package/dist/graph/call-chain.d.ts.map +1 -1
  54. package/dist/graph/call-chain.js +113 -18
  55. package/dist/graph/call-chain.js.map +1 -1
  56. package/dist/graph/changed-symbols.d.ts +57 -0
  57. package/dist/graph/changed-symbols.d.ts.map +1 -0
  58. package/dist/graph/changed-symbols.js +123 -0
  59. package/dist/graph/changed-symbols.js.map +1 -0
  60. package/dist/graph/extractors/index.d.ts +3 -3
  61. package/dist/graph/extractors/index.d.ts.map +1 -1
  62. package/dist/graph/extractors/index.js +2 -2
  63. package/dist/graph/extractors/index.js.map +1 -1
  64. package/dist/graph/extractors/javascript.d.ts.map +1 -1
  65. package/dist/graph/extractors/javascript.js +89 -3
  66. package/dist/graph/extractors/javascript.js.map +1 -1
  67. package/dist/graph/extractors/rust.d.ts.map +1 -1
  68. package/dist/graph/extractors/rust.js +7 -2
  69. package/dist/graph/extractors/rust.js.map +1 -1
  70. package/dist/graph/extractors/types.d.ts +7 -1
  71. package/dist/graph/extractors/types.d.ts.map +1 -1
  72. package/dist/graph/extractors/typescript.d.ts.map +1 -1
  73. package/dist/graph/extractors/typescript.js +95 -4
  74. package/dist/graph/extractors/typescript.js.map +1 -1
  75. package/dist/graph/index.d.ts +8 -3
  76. package/dist/graph/index.d.ts.map +1 -1
  77. package/dist/graph/index.js +4 -2
  78. package/dist/graph/index.js.map +1 -1
  79. package/dist/graph/loader.d.ts +29 -0
  80. package/dist/graph/loader.d.ts.map +1 -1
  81. package/dist/graph/loader.js +70 -1
  82. package/dist/graph/loader.js.map +1 -1
  83. package/dist/graph/narrow-symbols.d.ts +73 -0
  84. package/dist/graph/narrow-symbols.d.ts.map +1 -0
  85. package/dist/graph/narrow-symbols.js +195 -0
  86. package/dist/graph/narrow-symbols.js.map +1 -0
  87. package/dist/graph/schema.d.ts +117 -4
  88. package/dist/graph/schema.d.ts.map +1 -1
  89. package/dist/graph/schema.js +67 -3
  90. package/dist/graph/schema.js.map +1 -1
  91. package/dist/graph/scip/builder.d.ts +64 -0
  92. package/dist/graph/scip/builder.d.ts.map +1 -0
  93. package/dist/graph/scip/builder.js +268 -0
  94. package/dist/graph/scip/builder.js.map +1 -0
  95. package/dist/graph/scip/merge.d.ts +66 -0
  96. package/dist/graph/scip/merge.d.ts.map +1 -0
  97. package/dist/graph/scip/merge.js +98 -0
  98. package/dist/graph/scip/merge.js.map +1 -0
  99. package/dist/index.d.ts +16 -6
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +17 -4
  102. package/dist/index.js.map +1 -1
  103. package/dist/memory/decay.d.ts +40 -0
  104. package/dist/memory/decay.d.ts.map +1 -1
  105. package/dist/memory/decay.js +57 -0
  106. package/dist/memory/decay.js.map +1 -1
  107. package/dist/memory/engram.d.ts.map +1 -1
  108. package/dist/memory/engram.js +15 -3
  109. package/dist/memory/engram.js.map +1 -1
  110. package/dist/memory/search.d.ts +157 -0
  111. package/dist/memory/search.d.ts.map +1 -1
  112. package/dist/memory/search.js +420 -0
  113. package/dist/memory/search.js.map +1 -1
  114. package/dist/memory/sqlite.d.ts.map +1 -1
  115. package/dist/memory/sqlite.js +11 -3
  116. package/dist/memory/sqlite.js.map +1 -1
  117. package/dist/pipeline/execute.d.ts.map +1 -1
  118. package/dist/pipeline/execute.js +14 -0
  119. package/dist/pipeline/execute.js.map +1 -1
  120. package/dist/pipeline/prepare-graph.d.ts +23 -1
  121. package/dist/pipeline/prepare-graph.d.ts.map +1 -1
  122. package/dist/pipeline/prepare-graph.js +119 -3
  123. package/dist/pipeline/prepare-graph.js.map +1 -1
  124. package/dist/pipeline/prepare.d.ts.map +1 -1
  125. package/dist/pipeline/prepare.js +2 -0
  126. package/dist/pipeline/prepare.js.map +1 -1
  127. package/dist/providers/cli-bridge.d.ts +13 -11
  128. package/dist/providers/cli-bridge.d.ts.map +1 -1
  129. package/dist/providers/cli-bridge.js +156 -40
  130. package/dist/providers/cli-bridge.js.map +1 -1
  131. package/dist/providers/explanation-generate-fn.d.ts +28 -0
  132. package/dist/providers/explanation-generate-fn.d.ts.map +1 -0
  133. package/dist/providers/explanation-generate-fn.js +122 -0
  134. package/dist/providers/explanation-generate-fn.js.map +1 -0
  135. package/dist/types.d.ts +64 -2
  136. package/dist/types.d.ts.map +1 -1
  137. package/dist/types.js +8 -0
  138. package/dist/types.js.map +1 -1
  139. package/package.json +15 -13
@@ -34,6 +34,125 @@ export function isExcludedPath(filePath) {
34
34
  function hashContent(content) {
35
35
  return createHash('sha256').update(content).digest('hex');
36
36
  }
37
+ /**
38
+ * Move one directory level up from a repo-relative dir path (`''`/`'.'` at
39
+ * the root, never past it). Used by the Python resolver below to walk
40
+ * package levels (relative-import dot count) and ancestor dirs (absolute
41
+ * import heuristic).
42
+ */
43
+ function dirUp(dir) {
44
+ if (dir === '' || dir === '.')
45
+ return '';
46
+ const parent = path.posix.dirname(dir);
47
+ return parent === '.' ? '' : parent;
48
+ }
49
+ /**
50
+ * Try resolving a dotless, repo-relative Python module TARGET (already
51
+ * dot-converted to `/`) against `availableFiles`: as a `.py`/`.pyi` module
52
+ * file, then as a PACKAGE via its `__init__.py`/`__init__.pyi` barrel
53
+ * (BL-SCIP-BARREL-PYTHON-RUST — the gap this fixes: `__init__.py` was
54
+ * missing from index-file resolution entirely, on top of the dotted-import
55
+ * mishandling below), then as an exact match (rare). Returns `undefined`
56
+ * when nothing matches — the caller must NOT fabricate a path.
57
+ */
58
+ function tryPythonTarget(target, availableFiles) {
59
+ // Root-level target ('' — e.g. `from . import x` at the repo root): the
60
+ // barrel candidate is `__init__.py`, NOT `/__init__.py` (a leading slash
61
+ // never matches a repo-relative path, so this case silently fell through
62
+ // before this fix).
63
+ const barrelPrefix = target ? `${target}/` : '';
64
+ if (target && availableFiles.has(`${target}.py`))
65
+ return `${target}.py`;
66
+ if (target && availableFiles.has(`${target}.pyi`))
67
+ return `${target}.pyi`;
68
+ if (availableFiles.has(`${barrelPrefix}__init__.py`))
69
+ return `${barrelPrefix}__init__.py`;
70
+ if (availableFiles.has(`${barrelPrefix}__init__.pyi`))
71
+ return `${barrelPrefix}__init__.pyi`;
72
+ if (target && availableFiles.has(target))
73
+ return target;
74
+ return undefined;
75
+ }
76
+ /**
77
+ * Count how many distinct real files in `availableFiles` could satisfy an
78
+ * ABSOLUTE Python import target (root-relative `target`, already
79
+ * dot-converted to `/`) — either as `target` itself resolved via
80
+ * `tryPythonTarget` (root-relative), OR as `target` resolved relative to
81
+ * ANY ancestor directory anywhere in the repo (i.e. some OTHER file tree
82
+ * also has a same-named package/module at `target`'s tail). Used to detect
83
+ * package-name collisions (R3-001): a `utils` package that exists under
84
+ * BOTH `services/billing/` and `shared/` must never be silently resolved to
85
+ * whichever one happens to be nearest — that is a WRONG edge, worse than no
86
+ * edge at all.
87
+ */
88
+ function countPythonAbsoluteCandidates(target, availableFiles) {
89
+ const candidates = new Set();
90
+ const rootResolved = tryPythonTarget(target, availableFiles);
91
+ if (rootResolved)
92
+ candidates.add(rootResolved);
93
+ const suffixes = target
94
+ ? [`/${target}.py`, `/${target}.pyi`, `/${target}/__init__.py`, `/${target}/__init__.pyi`]
95
+ : [];
96
+ for (const f of availableFiles) {
97
+ if (suffixes.some((suffix) => f.endsWith(suffix))) {
98
+ candidates.add(f);
99
+ }
100
+ }
101
+ return candidates;
102
+ }
103
+ /**
104
+ * Resolve a Python import specifier to a repo-relative file path.
105
+ *
106
+ * Two forms, both mishandled before this fix:
107
+ *
108
+ * - RELATIVE (`from .sub import X`, `from ..sub import Y`): the leading dot
109
+ * COUNT is significant — one dot means "the importer's own containing
110
+ * package" (its dirname, whether the importer is `__init__.py` or a
111
+ * regular sibling module — both cases the dirname already IS the
112
+ * package), each additional dot climbs one more package level. The
113
+ * previous code passed the specifier through the TS-style `path.join`
114
+ * resolver, which treated `.sub` as a literal path SEGMENT (`pkg/.sub`)
115
+ * rather than "same dir, name sub" — never matching any real file.
116
+ * - ABSOLUTE (`from pkg import X`, `import pkg.sub`): previously short-
117
+ * circuited by the non-relative-imports-return-as-is branch (correct for
118
+ * `lodash`-style external packages in OTHER languages, wrong for Python's
119
+ * dotted own-package imports). Resolved here ONLY when the target is
120
+ * UNAMBIGUOUS — exactly one file anywhere in `availableFiles` can satisfy
121
+ * it (root-relative, or nested under exactly one ancestor tree). A
122
+ * monorepo with duplicate package names (e.g. `services/billing/utils`
123
+ * AND `shared/utils`) must NOT silently guess the nearest one — a WRONG
124
+ * edge is worse than no edge (R3-001). Zero or multiple candidates fall
125
+ * through unresolved and are returned unchanged, same as genuinely
126
+ * external packages (e.g. `numpy`).
127
+ *
128
+ * Relative-import resolution failures (R3-002) return `undefined` — never a
129
+ * fabricated non-existent path — since a relative specifier (`.`, `..sub`)
130
+ * is never a meaningful external reference on its own; callers drop
131
+ * unresolved imports rather than recording a dangling/fabricated edge.
132
+ */
133
+ function resolvePythonImportPath(importerPath, importSpecifier, availableFiles) {
134
+ const dotMatch = importSpecifier.match(/^\.+/);
135
+ const dotCount = dotMatch ? dotMatch[0].length : 0;
136
+ const rest = importSpecifier.slice(dotCount);
137
+ const restPath = rest ? rest.replace(/\./g, '/') : '';
138
+ if (dotCount > 0) {
139
+ let dir = path.posix.dirname(importerPath);
140
+ if (dir === '.')
141
+ dir = '';
142
+ for (let i = 0; i < dotCount - 1; i++) {
143
+ dir = dirUp(dir);
144
+ }
145
+ const target = restPath ? path.posix.join(dir, restPath) : dir;
146
+ return tryPythonTarget(target, availableFiles);
147
+ }
148
+ // Absolute dotted import: resolve ONLY when unambiguous.
149
+ const candidates = countPythonAbsoluteCandidates(restPath, availableFiles);
150
+ if (candidates.size === 1) {
151
+ const [only] = candidates;
152
+ return only;
153
+ }
154
+ return importSpecifier;
155
+ }
37
156
  /**
38
157
  * Resolve a relative import path to an absolute path within the project.
39
158
  *
@@ -41,8 +160,23 @@ function hashContent(content) {
41
160
  * to a project-relative path. Only resolves relative imports (starting
42
161
  * with `.` or `..`). Non-relative imports (e.g., 'lodash') are returned
43
162
  * as-is since they refer to external packages.
163
+ *
164
+ * Python is special-cased (BL-SCIP-BARREL-PYTHON-RUST): both its relative
165
+ * (`.sub`/`..sub`) AND absolute (`pkg`/`pkg.sub`) dotted-module import forms
166
+ * are delegated to `resolvePythonImportPath` — see that function's doc
167
+ * comment for what's actually resolved vs. left as a documented heuristic
168
+ * gap. No other language's resolution changes.
169
+ *
170
+ * Returns `undefined` ONLY for the Python relative-import no-fabrication
171
+ * case (R3-002) — every other path (including unresolved Python absolute
172
+ * imports and non-Python external specifiers) always returns a string.
173
+ * Callers MUST drop `undefined` results rather than substitute a fabricated
174
+ * path.
44
175
  */
45
176
  export function resolveImportPath(importerPath, importSpecifier, availableFiles) {
177
+ if (detectLanguage(importerPath) === 'python') {
178
+ return resolvePythonImportPath(importerPath, importSpecifier, availableFiles);
179
+ }
46
180
  // Non-relative imports → return as-is
47
181
  if (!importSpecifier.startsWith('.')) {
48
182
  return importSpecifier;
@@ -87,6 +221,56 @@ export function resolveImportPath(importerPath, importSpecifier, availableFiles)
87
221
  // Return the original resolved path (without extension)
88
222
  return resolved;
89
223
  }
224
+ /**
225
+ * Resolve a list of raw import specifiers, dropping any that
226
+ * `resolveImportPath` leaves unresolved (R3-002 no-fabrication contract —
227
+ * currently only the Python relative-import case can return `undefined`).
228
+ */
229
+ function resolveImportPathList(importerPath, specifiers, availableFiles) {
230
+ const out = [];
231
+ for (const spec of specifiers) {
232
+ const resolved = resolveImportPath(importerPath, spec, availableFiles);
233
+ if (resolved !== undefined)
234
+ out.push(resolved);
235
+ }
236
+ return out;
237
+ }
238
+ // ─── Export Buckets (D3, D6) ─────────────────────────────────────
239
+ /**
240
+ * Split a file's extracted `ExportInfo[]` into locally-defined exports vs
241
+ * the two re-export buckets (named/type-only symbols, and wildcard
242
+ * sources). Shared by BOTH `buildGraph` and `buildGraphIncremental` (D6
243
+ * parity) — factored out specifically so the barrel split can't drift
244
+ * between the two builder paths the way `extractImports`/`extractExports`
245
+ * calls historically have (see `stageImportSymbols`/`remapImportSymbols`
246
+ * for the analogous import-side precedent).
247
+ *
248
+ * `reExportsAllRaw` sources are UNRESOLVED module specifiers — the caller
249
+ * resolves them via `resolveImportPath` in whichever pass it already
250
+ * resolves `imports` in (Pass 2 for `buildGraph`, inline for
251
+ * `buildGraphIncremental`).
252
+ */
253
+ function deriveExportBuckets(extractedExports) {
254
+ const exports = [];
255
+ const reExportedSymbols = [];
256
+ const reExportsAllRaw = [];
257
+ for (const exp of extractedExports) {
258
+ if (exp.source === undefined) {
259
+ exports.push(exp.name);
260
+ }
261
+ else if (exp.name === '*') {
262
+ reExportsAllRaw.push(exp.source);
263
+ }
264
+ else {
265
+ reExportedSymbols.push(exp.name);
266
+ }
267
+ }
268
+ return {
269
+ exports,
270
+ reExportedSymbols: reExportedSymbols.length > 0 ? reExportedSymbols : undefined,
271
+ reExportsAllRaw: reExportsAllRaw.length > 0 ? reExportsAllRaw : undefined,
272
+ };
273
+ }
90
274
  // ─── Build Graph ────────────────────────────────────────────────
91
275
  /**
92
276
  * Build a complete dependency graph from a map of file paths → file content.
@@ -98,6 +282,16 @@ export function resolveImportPath(importerPath, importSpecifier, availableFiles)
98
282
  export function buildGraph(rootDir, files) {
99
283
  const nodes = {};
100
284
  const availableFiles = new Set(files.keys());
285
+ // Staged rawSource -> symbols per file, keyed BEFORE Pass-2 path
286
+ // resolution (`node.imports` still holds raw specifiers at this point).
287
+ // Remapped to resolved paths in Pass 2, alongside `node.imports` itself,
288
+ // so `importSymbols` ends up keyed in the SAME resolved-path space as
289
+ // `imports` (required for Slice 2 lookups to work).
290
+ const rawSymbolsByFile = new Map();
291
+ // Staged rawSource[] (wildcard re-export sources) per file, BEFORE Pass-2
292
+ // path resolution — resolved into `reExportsAll` alongside `imports` in
293
+ // Pass 2, mirroring `rawSymbolsByFile` above (D6).
294
+ const rawWildcardSourcesByFile = new Map();
101
295
  // Pass 1: Build nodes with raw imports
102
296
  for (const [filePath, content] of files) {
103
297
  // Skip excluded directories
@@ -107,18 +301,28 @@ export function buildGraph(rootDir, files) {
107
301
  const language = detectLanguage(filePath);
108
302
  if (!language)
109
303
  continue;
304
+ // SCIP-only languages (kotlin/csharp/php) have no regex extractor —
305
+ // the regex builder can't index them, so skip (no node, no throw).
306
+ const extractor = getExtractor(language);
307
+ if (!extractor)
308
+ continue;
110
309
  try {
111
- const extractor = getExtractor(language);
112
310
  const extractedImports = extractor.extractImports(content);
113
311
  const extractedExports = extractor.extractExports(content);
312
+ const buckets = deriveExportBuckets(extractedExports);
114
313
  nodes[filePath] = {
115
314
  hash: hashContent(content),
116
315
  language,
117
316
  imports: extractedImports.map((i) => i.source),
118
- exports: extractedExports.map((e) => e.name),
317
+ exports: buckets.exports,
318
+ ...(buckets.reExportedSymbols ? { reExportedSymbols: buckets.reExportedSymbols } : {}),
119
319
  calls: [],
120
320
  isTest: isTestFile(filePath),
121
321
  };
322
+ if (buckets.reExportsAllRaw) {
323
+ rawWildcardSourcesByFile.set(filePath, buckets.reExportsAllRaw);
324
+ }
325
+ stageImportSymbols(rawSymbolsByFile, filePath, extractedImports);
122
326
  }
123
327
  catch {
124
328
  // Parse errors in individual files don't abort the build
@@ -135,7 +339,17 @@ export function buildGraph(rootDir, files) {
135
339
  }
136
340
  // Pass 2: Resolve relative imports to project-relative paths
137
341
  for (const [filePath, node] of Object.entries(nodes)) {
138
- node.imports = node.imports.map((imp) => resolveImportPath(filePath, imp, availableFiles));
342
+ node.imports = resolveImportPathList(filePath, node.imports, availableFiles);
343
+ const rawSymbols = rawSymbolsByFile.get(filePath);
344
+ if (rawSymbols) {
345
+ const resolved = remapImportSymbols(filePath, rawSymbols, availableFiles);
346
+ if (resolved)
347
+ node.importSymbols = resolved;
348
+ }
349
+ const rawWildcardSources = rawWildcardSourcesByFile.get(filePath);
350
+ if (rawWildcardSources) {
351
+ node.reExportsAll = resolveImportPathList(filePath, rawWildcardSources, availableFiles);
352
+ }
139
353
  }
140
354
  return {
141
355
  version: GRAPH_VERSION,
@@ -143,6 +357,61 @@ export function buildGraph(rootDir, files) {
143
357
  nodes,
144
358
  };
145
359
  }
360
+ // ─── importSymbols Helpers ──────────────────────────────────────
361
+ /**
362
+ * Stage `rawSource -> symbols` for a file's extracted imports, BEFORE
363
+ * Pass-2 path resolution. Only sources with at least one named symbol are
364
+ * staged (omit-empty rule) — namespace/default/side-effect imports and
365
+ * extractors without symbol data (Python/Rust, most Go) never populate
366
+ * this map.
367
+ */
368
+ function stageImportSymbols(rawSymbolsByFile, filePath, extractedImports) {
369
+ for (const { source, symbols } of extractedImports) {
370
+ if (symbols.length === 0)
371
+ continue;
372
+ let bySource = rawSymbolsByFile.get(filePath);
373
+ if (!bySource) {
374
+ bySource = new Map();
375
+ rawSymbolsByFile.set(filePath, bySource);
376
+ }
377
+ let set = bySource.get(source);
378
+ if (!set) {
379
+ set = new Set();
380
+ bySource.set(source, set);
381
+ }
382
+ for (const symbol of symbols)
383
+ set.add(symbol);
384
+ }
385
+ }
386
+ /**
387
+ * Remap a file's staged `rawSource -> symbols` map to the SAME resolved
388
+ * path space as `node.imports`, merging symbol sets when multiple raw
389
+ * specifiers resolve to the same target (e.g. `./b` and `./b.ts`).
390
+ * Returns `undefined` when there is nothing to record (omit-empty rule).
391
+ */
392
+ function remapImportSymbols(filePath, rawSymbols, availableFiles) {
393
+ const result = {};
394
+ for (const [rawSource, symbols] of rawSymbols) {
395
+ const resolved = resolveImportPath(filePath, rawSource, availableFiles);
396
+ if (resolved === undefined)
397
+ continue;
398
+ const existing = result[resolved];
399
+ if (existing) {
400
+ for (const s of symbols)
401
+ existing.add(s);
402
+ }
403
+ else {
404
+ result[resolved] = new Set(symbols);
405
+ }
406
+ }
407
+ if (Object.keys(result).length === 0)
408
+ return undefined;
409
+ const out = {};
410
+ for (const [target, symbols] of Object.entries(result)) {
411
+ out[target] = Array.from(symbols);
412
+ }
413
+ return out;
414
+ }
146
415
  // ─── Incremental Build ──────────────────────────────────────────
147
416
  /**
148
417
  * Update a dependency graph incrementally.
@@ -177,18 +446,48 @@ export function buildGraphIncremental(existing, changedFiles, deletedFiles) {
177
446
  const language = detectLanguage(filePath);
178
447
  if (!language)
179
448
  continue;
449
+ // SCIP-only languages (kotlin/csharp/php) have no regex extractor.
450
+ const extractor = getExtractor(language);
451
+ if (!extractor) {
452
+ delete nodes[filePath];
453
+ continue;
454
+ }
180
455
  try {
181
- const extractor = getExtractor(language);
182
456
  const extractedImports = extractor.extractImports(content);
183
457
  const extractedExports = extractor.extractExports(content);
458
+ const buckets = deriveExportBuckets(extractedExports);
184
459
  nodes[filePath] = {
185
460
  hash: hashContent(content),
186
461
  language,
187
- imports: extractedImports.map((i) => resolveImportPath(filePath, i.source, allFiles)),
188
- exports: extractedExports.map((e) => e.name),
462
+ imports: resolveImportPathList(filePath, extractedImports.map((i) => i.source), allFiles),
463
+ exports: buckets.exports,
464
+ ...(buckets.reExportedSymbols ? { reExportedSymbols: buckets.reExportedSymbols } : {}),
465
+ ...(buckets.reExportsAllRaw
466
+ ? {
467
+ reExportsAll: resolveImportPathList(filePath, buckets.reExportsAllRaw, allFiles),
468
+ }
469
+ : {}),
189
470
  calls: [],
190
471
  isTest: isTestFile(filePath),
191
472
  };
473
+ // Resolves inline (no separate Pass 2 in the incremental path) —
474
+ // remap raw source -> symbols directly to the resolved path space,
475
+ // matching `node.imports` above.
476
+ const rawSymbols = new Map();
477
+ for (const { source, symbols } of extractedImports) {
478
+ if (symbols.length === 0)
479
+ continue;
480
+ let set = rawSymbols.get(source);
481
+ if (!set) {
482
+ set = new Set();
483
+ rawSymbols.set(source, set);
484
+ }
485
+ for (const symbol of symbols)
486
+ set.add(symbol);
487
+ }
488
+ const resolvedSymbols = remapImportSymbols(filePath, rawSymbols, allFiles);
489
+ if (resolvedSymbols)
490
+ nodes[filePath].importSymbols = resolvedSymbols;
192
491
  }
193
492
  catch {
194
493
  nodes[filePath] = {
@@ -1 +1 @@
1
- {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/graph/builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/graph/builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAEL,aAAa,EACb,aAAa,EAEb,UAAU,EACV,mBAAmB,GAEpB,MAAM,aAAa,CAAC;AAErB,mEAAmE;AAEnE;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,OAAO,mBAAmB,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACtC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,MAAc,EAAE,cAA2B;IAClE,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,oBAAoB;IACpB,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,IAAI,MAAM,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,MAAM,KAAK,CAAC;IACxE,IAAI,MAAM,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC;QAAE,OAAO,GAAG,MAAM,MAAM,CAAC;IAC1E,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,YAAY,aAAa,CAAC;QAAE,OAAO,GAAG,YAAY,aAAa,CAAC;IAC1F,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,YAAY,cAAc,CAAC;QAAE,OAAO,GAAG,YAAY,cAAc,CAAC;IAC5F,IAAI,MAAM,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACxD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,6BAA6B,CAAC,MAAc,EAAE,cAA2B;IAChF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC7D,IAAI,YAAY;QAAE,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAE/C,MAAM,QAAQ,GAAG,MAAM;QACrB,CAAC,CAAC,CAAC,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,MAAM,EAAE,IAAI,MAAM,cAAc,EAAE,IAAI,MAAM,eAAe,CAAC;QAC1F,CAAC,CAAC,EAAE,CAAC;IACP,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAClD,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,SAAS,uBAAuB,CAC9B,YAAoB,EACpB,eAAuB,EACvB,cAA2B;IAE3B,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtD,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,GAAG,KAAK,GAAG;YAAE,GAAG,GAAG,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/D,OAAO,eAAe,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACjD,CAAC;IAED,yDAAyD;IACzD,MAAM,UAAU,GAAG,6BAA6B,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC3E,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAAoB,EACpB,eAAuB,EACvB,cAA2B;IAE3B,IAAI,cAAc,CAAC,YAAY,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,uBAAuB,CAAC,YAAY,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;IAChF,CAAC;IAED,sCAAsC;IACtC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/C,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;IAEnF,oBAAoB;IACpB,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,wBAAwB;IACxB,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,mCAAmC;IACnC,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACxF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,QAAQ,GAAG,GAAG,EAAE,CAAC;QACpC,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,oDAAoD;IACpD,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACtE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,GAAG,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC7C,IAAI,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,0FAA0F;IAC1F,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,wDAAwD;IACxD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAC5B,YAAoB,EACpB,UAAoB,EACpB,cAA2B;IAE3B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,YAAY,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QACvE,IAAI,QAAQ,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oEAAoE;AAEpE;;;;;;;;;;;;;GAaG;AACH,SAAS,mBAAmB,CAAC,gBAA8B;IAKzD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,iBAAiB,GAAa,EAAE,CAAC;IACvC,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YAC5B,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;QAC/E,eAAe,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC;AACJ,CAAC;AAED,mEAAmE;AAEnE;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,KAA0B;IACpE,MAAM,KAAK,GAA8B,EAAE,CAAC;IAC5C,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAE7C,iEAAiE;IACjE,wEAAwE;IACxE,yEAAyE;IACzE,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAoC,CAAC;IAErE,0EAA0E;IAC1E,wEAAwE;IACxE,mDAAmD;IACnD,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE7D,uCAAuC;IACvC,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;QACxC,4BAA4B;QAC5B,IAAI,cAAc,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEvC,kBAAkB;QAClB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,oEAAoE;QACpE,mEAAmE;QACnE,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzB,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAG,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC3D,MAAM,gBAAgB,GAAG,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;YAEtD,KAAK,CAAC,QAAQ,CAAC,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC1B,QAAQ;gBACR,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC9C,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;aAC7B,CAAC;YAEF,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC5B,wBAAwB,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;YAClE,CAAC;YAED,kBAAkB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;YACzD,+DAA+D;YAC/D,KAAK,CAAC,QAAQ,CAAC,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC1B,QAAQ;gBACR,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;aAC7B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,OAAO,GAAG,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAE7E,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;YAC1E,IAAI,QAAQ;gBAAE,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9C,CAAC;QAED,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClE,IAAI,kBAAkB,EAAE,CAAC;YACvB,IAAI,CAAC,YAAY,GAAG,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,aAAa;QACtB,OAAO;QACP,KAAK;KACN,CAAC;AACJ,CAAC;AAED,mEAAmE;AAEnE;;;;;;GAMG;AACH,SAAS,kBAAkB,CACzB,gBAAuD,EACvD,QAAgB,EAChB,gBAA8D;IAE9D,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,CAAC;QACnD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEnC,IAAI,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;YACrB,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,kBAAkB,CACzB,QAAgB,EAChB,UAAoC,EACpC,cAA2B;IAE3B,MAAM,MAAM,GAAgC,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,UAAU,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;QACxE,IAAI,QAAQ,KAAK,SAAS;YAAE,SAAS;QACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,MAAM,CAAC,IAAI,OAAO;gBAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEvD,MAAM,GAAG,GAA6B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,mEAAmE;AAEnE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAyB,EACzB,YAAiC,EACjC,YAAsB;IAEtB,sCAAsC;IACtC,MAAM,KAAK,GAA8B,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;IAE/D,uBAAuB;IACvB,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,KAAK,MAAM,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;QACpC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,wBAAwB;IACxB,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,YAAY,EAAE,CAAC;QAC/C,IAAI,cAAc,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEvC,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,mEAAmE;QACnE,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAG,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC3D,MAAM,gBAAgB,GAAG,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;YAEtD,KAAK,CAAC,QAAQ,CAAC,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC1B,QAAQ;gBACR,OAAO,EAAE,qBAAqB,CAC5B,QAAQ,EACR,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EACrC,QAAQ,CACT;gBACD,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,GAAG,CAAC,OAAO,CAAC,eAAe;oBACzB,CAAC,CAAC;wBACE,YAAY,EAAE,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC;qBACjF;oBACH,CAAC,CAAC,EAAE,CAAC;gBACP,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;aAC7B,CAAC;YAEF,iEAAiE;YACjE,mEAAmE;YACnE,iCAAiC;YACjC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;YAClD,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,CAAC;gBACnD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBACnC,IAAI,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;oBAChB,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBAC9B,CAAC;gBACD,KAAK,MAAM,MAAM,IAAI,OAAO;oBAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC3E,IAAI,eAAe;gBAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,aAAa,GAAG,eAAe,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,CAAC,QAAQ,CAAC,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC1B,QAAQ;gBACR,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;aAC7B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -24,6 +24,33 @@ export interface CallChainBlastRadius {
24
24
  callChainGraph: CallChainGraph;
25
25
  depth: number;
26
26
  }
27
+ /**
28
+ * Known residual limitations (deliberately not handled — lower-impact than
29
+ * the Go receiver-method case):
30
+ * - `impl Display for MyStruct` currently extracts "Display" (the trait),
31
+ * not "MyStruct" (the type being implemented).
32
+ * - Generic bare declarations like `<T> T process` currently extract "T"
33
+ * (the generic parameter), not "process".
34
+ * Same class of accepted residual as Java's `public static void main` -> "void".
35
+ */
36
+ export declare function extractDeclaredSymbol(text: string): string | undefined;
37
+ /**
38
+ * Extract diff hunk context to find symbols that had +/- lines.
39
+ * Returns the file path and approximate symbol name for each modified hunk.
40
+ *
41
+ * Exported (was module-private) for reuse by the Symbol Impact review
42
+ * context (`pipeline/prepare-graph.ts` step 2.6) — same diff-parsing logic,
43
+ * different consumer.
44
+ *
45
+ * DEPRECATED (scip-symbol-ranges D5): this is a declaration-level LOWER
46
+ * BOUND — it only sees hunk-header context and top-level declaration
47
+ * lines, so a body-only change to a symbol whose signature didn't change
48
+ * is invisible to it. `pipeline/prepare-graph.ts` now prefers
49
+ * `graph/changed-symbols.ts`'s `computeChangedSymbolsComplete` whenever
50
+ * the graph has SCIP `symbolRanges`; this function is kept ONLY as the
51
+ * no-symbolRanges fallback (regex-built graphs, C#/PHP) — do not remove.
52
+ */
53
+ export declare function extractChangedSymbolsFromDiff(unifiedDiff: string): Map<string, Set<string>>;
27
54
  /**
28
55
  * Build a call-chain blast radius from a unified diff and file contents.
29
56
  *
@@ -1 +1 @@
1
- {"version":3,"file":"call-chain.d.ts","sourceRoot":"","sources":["../../src/graph/call-chain.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;CACpD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,aAAa,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AA8OD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,oBAAoB,CA+FtB"}
1
+ {"version":3,"file":"call-chain.d.ts","sourceRoot":"","sources":["../../src/graph/call-chain.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;CACpD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,aAAa,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAsFD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBtE;AAyBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAoD3F;AAqID;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,oBAAoB,CA+FtB"}
@@ -26,11 +26,114 @@ const IMPORT_NAMED_RE = /import\s*\{([^}]+)\}\s*from\s*["'][^"']+["']/g;
26
26
  /** Matches: import X from "..." */
27
27
  const IMPORT_DEFAULT_RE = /import\s+([A-Za-z_$][A-Za-z0-9_$]*)\s+from\s*["'][^"']+["']/g;
28
28
  // ─── Helpers ─────────────────────────────────────────────────────
29
+ /** Leading modifier keywords that precede a declaration but are never the symbol name. */
30
+ const MODIFIER_KEYWORDS = new Set([
31
+ 'export',
32
+ 'default',
33
+ 'public',
34
+ 'private',
35
+ 'protected',
36
+ 'static',
37
+ 'async',
38
+ 'pub',
39
+ 'final',
40
+ 'abstract',
41
+ ]);
42
+ /** Keywords that introduce a declaration — the symbol name is the token AFTER these. */
43
+ const DECLARATION_KEYWORDS = new Set([
44
+ 'function',
45
+ 'func',
46
+ 'fn',
47
+ 'class',
48
+ 'const',
49
+ 'let',
50
+ 'var',
51
+ 'def',
52
+ 'type',
53
+ 'interface',
54
+ 'enum',
55
+ 'impl',
56
+ 'struct',
57
+ 'trait',
58
+ ]);
59
+ /**
60
+ * Extract the declared/referenced symbol name from a snippet of code
61
+ * (e.g. a diff hunk-header context or a bare changed line).
62
+ *
63
+ * Skips leading modifier keywords (export, default, pub, async, ...). If the
64
+ * next token is a declaration keyword (function, class, const, ...), the
65
+ * symbol is the token AFTER it. Otherwise the symbol is the first
66
+ * non-modifier identifier (covers bare context lines like `someMethod(args)`).
67
+ */
68
+ /**
69
+ * Matches the Go/Rust receiver-method declaration form:
70
+ * func (r *Receiver) Method(...)
71
+ * func (t Type) Value(...)
72
+ * The receiver group is skipped as a unit so the method name — not the
73
+ * receiver variable — is captured.
74
+ */
75
+ const GO_RECEIVER_METHOD_RE = /^\s*(?:func|fn)\s*\([^)]*\)\s*([A-Za-z_$][A-Za-z0-9_$]*)/;
76
+ /**
77
+ * Known residual limitations (deliberately not handled — lower-impact than
78
+ * the Go receiver-method case):
79
+ * - `impl Display for MyStruct` currently extracts "Display" (the trait),
80
+ * not "MyStruct" (the type being implemented).
81
+ * - Generic bare declarations like `<T> T process` currently extract "T"
82
+ * (the generic parameter), not "process".
83
+ * Same class of accepted residual as Java's `public static void main` -> "void".
84
+ */
85
+ export function extractDeclaredSymbol(text) {
86
+ const receiverMatch = text.match(GO_RECEIVER_METHOD_RE);
87
+ if (receiverMatch)
88
+ return receiverMatch[1];
89
+ const tokens = text.trim().match(/[A-Za-z_$][A-Za-z0-9_$]*/g);
90
+ if (!tokens || tokens.length === 0)
91
+ return undefined;
92
+ let i = 0;
93
+ while (i < tokens.length && MODIFIER_KEYWORDS.has(tokens[i]))
94
+ i++;
95
+ if (i >= tokens.length)
96
+ return undefined;
97
+ const token = tokens[i];
98
+ if (DECLARATION_KEYWORDS.has(token)) {
99
+ return tokens[i + 1];
100
+ }
101
+ return token;
102
+ }
103
+ /** Regex alternation of DECLARATION_KEYWORDS, built once. */
104
+ const DECLARATION_KEYWORDS_ALT = [...DECLARATION_KEYWORDS].join('|');
105
+ /** Regex alternation of MODIFIER_KEYWORDS, built once. */
106
+ const MODIFIER_KEYWORDS_ALT = [...MODIFIER_KEYWORDS].join('|');
107
+ /**
108
+ * Matches a TOP-LEVEL declaration on a changed diff line: the line must
109
+ * start (no leading whitespace, beyond the +/- diff marker already
110
+ * stripped) with optional modifier keywords followed by a declaration
111
+ * keyword and a symbol name. Deliberately conservative — a `const local = …`
112
+ * indented inside a function body (leading whitespace present) will NOT
113
+ * match, avoiding false positives from mid-expression/nested declarations.
114
+ */
115
+ const TOP_LEVEL_DECL_RE = new RegExp(`^(?:(?:${MODIFIER_KEYWORDS_ALT})\\s+)*(?:${DECLARATION_KEYWORDS_ALT})\\s+([A-Za-z_$][A-Za-z0-9_$]*)`);
116
+ function extractTopLevelDeclaredSymbol(content) {
117
+ const m = content.match(TOP_LEVEL_DECL_RE);
118
+ return m?.[1];
119
+ }
29
120
  /**
30
121
  * Extract diff hunk context to find symbols that had +/- lines.
31
122
  * Returns the file path and approximate symbol name for each modified hunk.
123
+ *
124
+ * Exported (was module-private) for reuse by the Symbol Impact review
125
+ * context (`pipeline/prepare-graph.ts` step 2.6) — same diff-parsing logic,
126
+ * different consumer.
127
+ *
128
+ * DEPRECATED (scip-symbol-ranges D5): this is a declaration-level LOWER
129
+ * BOUND — it only sees hunk-header context and top-level declaration
130
+ * lines, so a body-only change to a symbol whose signature didn't change
131
+ * is invisible to it. `pipeline/prepare-graph.ts` now prefers
132
+ * `graph/changed-symbols.ts`'s `computeChangedSymbolsComplete` whenever
133
+ * the graph has SCIP `symbolRanges`; this function is kept ONLY as the
134
+ * no-symbolRanges fallback (regex-built graphs, C#/PHP) — do not remove.
32
135
  */
33
- function extractChangedSymbolsFromDiff(unifiedDiff) {
136
+ export function extractChangedSymbolsFromDiff(unifiedDiff) {
34
137
  const result = new Map();
35
138
  const lines = unifiedDiff.split('\n');
36
139
  let currentFile = '';
@@ -48,31 +151,23 @@ function extractChangedSymbolsFromDiff(unifiedDiff) {
48
151
  if (line.startsWith('@@')) {
49
152
  const m = line.match(/@@ .* @@ (.+)/);
50
153
  if (m?.[1]) {
51
- const ctx = m[1].trim();
52
- // Extract first identifier from the hunk context
53
- const idMatch = ctx.match(/(?:function|class|const|let|var|async)?\s*([A-Za-z_$][A-Za-z0-9_$]*)/);
54
- if (idMatch?.[1]) {
55
- currentSymbol = idMatch[1];
154
+ const symbol = extractDeclaredSymbol(m[1]);
155
+ if (symbol) {
156
+ currentSymbol = symbol;
56
157
  }
57
158
  }
58
159
  continue;
59
160
  }
60
- // Changed lines (+ or -) that declare a function/class
161
+ // Changed lines (+ or -) that declare a top-level function/class/const/
162
+ // let/var/type/interface/enum.
61
163
  if ((line.startsWith('+') || line.startsWith('-')) &&
62
164
  !line.startsWith('+++') &&
63
165
  !line.startsWith('---')) {
64
166
  const content = line.slice(1);
65
- // Check for function declarations in changed lines
66
- const fnMatch = content.match(/(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*\(/);
67
- if (fnMatch?.[1] && currentFile) {
68
- result.get(currentFile)?.add(fnMatch[1]);
69
- currentSymbol = fnMatch[1];
70
- }
71
- // Check for class declarations
72
- const clsMatch = content.match(/(?:export\s+)?class\s+([A-Za-z_$][A-Za-z0-9_$]*)/);
73
- if (clsMatch?.[1] && currentFile) {
74
- result.get(currentFile)?.add(clsMatch[1]);
75
- currentSymbol = clsMatch[1];
167
+ const declMatch = extractTopLevelDeclaredSymbol(content);
168
+ if (declMatch && currentFile) {
169
+ result.get(currentFile)?.add(declMatch);
170
+ currentSymbol = declMatch;
76
171
  }
77
172
  }
78
173
  }