milens 0.7.1 → 0.7.2

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 (96) hide show
  1. package/.agents/skills/adapters/SKILL.md +16 -11
  2. package/.agents/skills/analyzer/SKILL.md +11 -6
  3. package/.agents/skills/apps/SKILL.md +6 -1
  4. package/.agents/skills/docs/SKILL.md +6 -1
  5. package/.agents/skills/milens/SKILL.md +6 -3
  6. package/.agents/skills/orchestrator/SKILL.md +5 -0
  7. package/.agents/skills/parser/SKILL.md +11 -6
  8. package/.agents/skills/root/SKILL.md +21 -16
  9. package/.agents/skills/scripts/SKILL.md +9 -4
  10. package/.agents/skills/security/SKILL.md +10 -5
  11. package/.agents/skills/server/SKILL.md +18 -11
  12. package/.agents/skills/store/SKILL.md +10 -5
  13. package/.agents/skills/test/SKILL.md +15 -8
  14. package/.agents/skills/ui/SKILL.md +5 -0
  15. package/adapters/claude-code/.claude-plugin/plugin.json +1 -1
  16. package/adapters/claude-code/CLAUDE.md +2 -0
  17. package/adapters/claude-code/hooks/hooks.json +27 -0
  18. package/dist/agents-md.d.ts +1 -0
  19. package/dist/agents-md.js +45 -1
  20. package/dist/agents-md.js.map +1 -1
  21. package/dist/analyzer/config.js +32 -0
  22. package/dist/analyzer/config.js.map +1 -1
  23. package/dist/analyzer/engine.js +26 -2
  24. package/dist/analyzer/engine.js.map +1 -1
  25. package/dist/analyzer/enrich.js +68 -1
  26. package/dist/analyzer/enrich.js.map +1 -1
  27. package/dist/analyzer/resolver.d.ts +4 -1
  28. package/dist/analyzer/resolver.js +241 -38
  29. package/dist/analyzer/resolver.js.map +1 -1
  30. package/dist/analyzer/review.js +32 -2
  31. package/dist/analyzer/review.js.map +1 -1
  32. package/dist/analyzer/scanner.js +3 -0
  33. package/dist/analyzer/scanner.js.map +1 -1
  34. package/dist/analyzer/scope-resolver.js +1 -1
  35. package/dist/analyzer/scope-resolver.js.map +1 -1
  36. package/dist/build-info.d.ts +2 -2
  37. package/dist/build-info.js +2 -2
  38. package/dist/cli.js +84 -15
  39. package/dist/cli.js.map +1 -1
  40. package/dist/orchestrator/orchestrator.d.ts +1 -1
  41. package/dist/orchestrator/orchestrator.js +14 -6
  42. package/dist/orchestrator/orchestrator.js.map +1 -1
  43. package/dist/parser/extract.d.ts +7 -0
  44. package/dist/parser/extract.js +23 -1
  45. package/dist/parser/extract.js.map +1 -1
  46. package/dist/parser/lang-css.js +12 -0
  47. package/dist/parser/lang-css.js.map +1 -1
  48. package/dist/parser/lang-js.js +15 -4
  49. package/dist/parser/lang-js.js.map +1 -1
  50. package/dist/parser/lang-md.js +1 -0
  51. package/dist/parser/lang-md.js.map +1 -1
  52. package/dist/parser/lang-ts.js +40 -6
  53. package/dist/parser/lang-ts.js.map +1 -1
  54. package/dist/parser/lang-vue.js +0 -21
  55. package/dist/parser/lang-vue.js.map +1 -1
  56. package/dist/security/rules.js +22 -23
  57. package/dist/security/rules.js.map +1 -1
  58. package/dist/server/guard-hook.d.ts +10 -0
  59. package/dist/server/guard-hook.js +179 -0
  60. package/dist/server/guard-hook.js.map +1 -0
  61. package/dist/server/hooks.js +2 -1
  62. package/dist/server/hooks.js.map +1 -1
  63. package/dist/server/mcp.js +172 -30
  64. package/dist/server/mcp.js.map +1 -1
  65. package/dist/server/test-plan.d.ts +1 -0
  66. package/dist/server/test-plan.js +25 -7
  67. package/dist/server/test-plan.js.map +1 -1
  68. package/dist/server/tools/findings-report.d.ts +3 -0
  69. package/dist/server/tools/findings-report.js +170 -0
  70. package/dist/server/tools/findings-report.js.map +1 -0
  71. package/dist/server/tools/security.js +61 -5
  72. package/dist/server/tools/security.js.map +1 -1
  73. package/dist/server/tools/session.js +37 -17
  74. package/dist/server/tools/session.js.map +1 -1
  75. package/dist/server/tools/testing.js +58 -11
  76. package/dist/server/tools/testing.js.map +1 -1
  77. package/dist/skills.js +15 -9
  78. package/dist/skills.js.map +1 -1
  79. package/dist/store/annotations.d.ts +5 -0
  80. package/dist/store/annotations.js +45 -9
  81. package/dist/store/annotations.js.map +1 -1
  82. package/dist/store/db.d.ts +13 -0
  83. package/dist/store/db.js +146 -33
  84. package/dist/store/db.js.map +1 -1
  85. package/dist/store/registry.d.ts +1 -0
  86. package/dist/store/registry.js +17 -6
  87. package/dist/store/registry.js.map +1 -1
  88. package/dist/store/schema.sql +2 -1
  89. package/dist/types.d.ts +16 -1
  90. package/dist/uninstall.d.ts +1 -0
  91. package/dist/uninstall.js +33 -10
  92. package/dist/uninstall.js.map +1 -1
  93. package/dist/utils.d.ts +1 -1
  94. package/dist/utils.js +0 -0
  95. package/dist/utils.js.map +1 -1
  96. package/package.json +1 -1
@@ -111,9 +111,32 @@ function computeDomains(symbols, links) {
111
111
  ufRank.set(ra, rankA + 1);
112
112
  }
113
113
  }
114
+ // Widely-shared "hub" files (e.g. a single http-client.ts imported by dozens of
115
+ // otherwise-unrelated feature modules) would otherwise bridge-merge every one of
116
+ // those unrelated modules into one giant cluster via transitive union-find, since
117
+ // each of them independently shares a strong edge with the hub. Detect such hubs
118
+ // by strong-edge degree (distinct files they're strongly linked to) and exclude
119
+ // them from acting as merge bridges — two files still cluster together if they
120
+ // link directly to each other, just not merely by both linking to the same hub.
121
+ const strongEdgesPerFile = new Map();
122
+ for (const [key, weight] of edgeWeights) {
123
+ if (weight < 2)
124
+ continue;
125
+ const [a, b] = key.split('::');
126
+ if (!strongEdgesPerFile.has(a))
127
+ strongEdgesPerFile.set(a, new Set());
128
+ if (!strongEdgesPerFile.has(b))
129
+ strongEdgesPerFile.set(b, new Set());
130
+ strongEdgesPerFile.get(a).add(b);
131
+ strongEdgesPerFile.get(b).add(a);
132
+ }
133
+ const HUB_DEGREE_THRESHOLD = 8;
134
+ const isHub = (f) => (strongEdgesPerFile.get(f)?.size ?? 0) > HUB_DEGREE_THRESHOLD;
114
135
  for (const [key, weight] of edgeWeights) {
115
136
  if (weight >= 2) {
116
137
  const [a, b] = key.split('::');
138
+ if (isHub(a) || isHub(b))
139
+ continue;
117
140
  union(a, b);
118
141
  }
119
142
  }
@@ -125,9 +148,31 @@ function computeDomains(symbols, links) {
125
148
  arr.push(file);
126
149
  clusters.set(root, arr);
127
150
  }
128
- // Name each cluster by most common directory segment
151
+ // Name each cluster by most common directory segment.
152
+ // For generic leaf names (hooks, utils, etc.), prefer the parent segment when
153
+ // there's meaningful diversity — prevents collapsing unrelated feature modules.
154
+ const GENERIC_LEAVES = new Set(['hooks', 'utils', 'components', 'services', 'types', 'dto', 'models', 'controllers', 'gateways', 'routes', 'helpers', 'constants']);
155
+ // A cluster can still balloon to span most of the codebase via a long chain of
156
+ // pairwise-strong links through common infrastructure (shared guards, base
157
+ // modules, decorators) even when no single file is a high-degree hub — hub
158
+ // suppression alone doesn't catch chained over-merging. As a size-based safety
159
+ // net, refuse to treat an implausibly large cluster as one cohesive domain and
160
+ // fall back to naming each of its files independently by its own directory.
161
+ const MAX_CLUSTER_ABS = 40;
162
+ const MAX_CLUSTER_FRACTION = 0.15;
163
+ const oversizedThreshold = Math.max(MAX_CLUSTER_ABS, Math.floor(allFiles.size * MAX_CLUSTER_FRACTION));
129
164
  const zones = new Map();
130
165
  for (const [, clusterFiles] of clusters) {
166
+ if (clusterFiles.length > oversizedThreshold) {
167
+ for (const f of clusterFiles) {
168
+ const dir = dirname(f).replace(/\\/g, '/');
169
+ const parts = dir.split('/').filter(Boolean);
170
+ const leaf = parts.length > 0 ? parts[parts.length - 1] : 'root';
171
+ const name = GENERIC_LEAVES.has(leaf) && parts.length >= 2 ? `${parts[parts.length - 2]}/${leaf}` : leaf;
172
+ zones.set(f, name);
173
+ }
174
+ continue;
175
+ }
131
176
  const dirCounts = new Map();
132
177
  for (const f of clusterFiles) {
133
178
  const dir = dirname(f).replace(/\\/g, '/');
@@ -143,6 +188,28 @@ function computeDomains(symbols, links) {
143
188
  bestCount = count;
144
189
  }
145
190
  }
191
+ if (GENERIC_LEAVES.has(bestName) && clusterFiles.length > 1) {
192
+ const parentCounts = new Map();
193
+ for (const f of clusterFiles) {
194
+ const dir = dirname(f).replace(/\\/g, '/');
195
+ const parts = dir.split('/').filter(Boolean);
196
+ if (parts.length >= 2 && parts[parts.length - 1] === bestName) {
197
+ const parentSeg = parts[parts.length - 2];
198
+ parentCounts.set(parentSeg, (parentCounts.get(parentSeg) ?? 0) + 1);
199
+ }
200
+ }
201
+ let bestParent = '';
202
+ let bestParentCount = 0;
203
+ for (const [p, c] of parentCounts) {
204
+ if (c > bestParentCount) {
205
+ bestParent = p;
206
+ bestParentCount = c;
207
+ }
208
+ }
209
+ if (bestParent) {
210
+ bestName = `${bestParent}/${bestName}`;
211
+ }
212
+ }
146
213
  for (const f of clusterFiles) {
147
214
  zones.set(f, bestName);
148
215
  }
@@ -1 +1 @@
1
- {"version":3,"file":"enrich.js","sourceRoot":"","sources":["../../src/analyzer/enrich.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"enrich.js","sourceRoot":"","sources":["../../src/analyzer/enrich.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { CodeSymbol, SymbolLink, RawImport, RawCall, RawHeritage, RawReExport, RawTypeBinding, RawAssignmentBinding, RawReturnType, RawCallResultBinding } from '../types.js';
1
+ import type { CodeSymbol, SymbolLink, RawImport, RawCall, RawHeritage, RawReExport, RawTypeBinding, RawAssignmentBinding, RawReturnType, RawCallResultBinding, RawLocalBinding } from '../types.js';
2
2
  interface ResolutionInput {
3
3
  symbolsByFile: Map<string, CodeSymbol[]>;
4
4
  allSymbols: CodeSymbol[];
@@ -10,6 +10,7 @@ interface ResolutionInput {
10
10
  assignmentBindings?: RawAssignmentBinding[];
11
11
  returnTypes?: RawReturnType[];
12
12
  callResultBindings?: RawCallResultBinding[];
13
+ localBindings?: RawLocalBinding[];
13
14
  resolvedImportPaths: Map<string, string>;
14
15
  perFileImportSemantics?: Map<string, 'named' | 'wildcard-leaf' | 'wildcard-transitive' | 'namespace'>;
15
16
  perFileMroStrategy?: Map<string, 'first-wins' | 'c3' | 'ruby-mixin' | 'none'>;
@@ -20,6 +21,8 @@ export interface ResolutionResult {
20
21
  unresolvedCalls: number;
21
22
  externalImports: number;
22
23
  externalCalls: number;
24
+ /** External heritage parents (symbols not defined in project, e.g. `Error`, `CanActivate`) */
25
+ externalSymbols: CodeSymbol[];
23
26
  }
24
27
  export declare function resolveLinks(input: ResolutionInput): SymbolLink[];
25
28
  export declare function resolveLinksWithStats(input: ResolutionInput): ResolutionResult;
@@ -2,12 +2,26 @@ import { dirname } from 'node:path';
2
2
  // Minimum confidence to create a link — below this, classify as unresolved
3
3
  // "No link is better than a wrong link"
4
4
  const MIN_LINK_CONFIDENCE = 0.5;
5
+ // Common JS/TS built-in types and globals — extend/implements these means external heritage
6
+ const BUILTIN_TYPES = new Set([
7
+ 'Error', 'TypeError', 'RangeError', 'SyntaxError', 'ReferenceError',
8
+ 'Array', 'Map', 'Set', 'WeakMap', 'WeakSet', 'Promise', 'Date', 'RegExp',
9
+ 'String', 'Number', 'Boolean', 'Object', 'Function', 'Symbol', 'BigInt',
10
+ 'ArrayBuffer', 'DataView', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray',
11
+ 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', 'Float32Array',
12
+ 'Float64Array', 'BigInt64Array', 'BigUint64Array',
13
+ 'EventTarget', 'AbortController', 'AbortSignal',
14
+ 'URL', 'URLSearchParams', 'FormData', 'Blob', 'File', 'Response', 'Request',
15
+ 'Headers', 'ReadableStream', 'WritableStream', 'TransformStream',
16
+ 'TextEncoder', 'TextDecoder', 'EventEmitter',
17
+ ]);
5
18
  export function resolveLinks(input) {
6
19
  const result = resolveLinksWithStats(input);
7
20
  return result.links;
8
21
  }
9
22
  export function resolveLinksWithStats(input) {
10
23
  const links = [];
24
+ const externalSymbols = [];
11
25
  const symbolByName = buildNameIndex(input.allSymbols);
12
26
  const symbolById = buildIdIndex(input.allSymbols);
13
27
  let unresolvedImports = 0;
@@ -16,6 +30,19 @@ export function resolveLinksWithStats(input) {
16
30
  let externalCalls = 0;
17
31
  // Track names imported from external (non-local) modules per file
18
32
  const externalNamesPerFile = new Map();
33
+ // Names declared purely locally (params, const/let/var, destructuring) per enclosing
34
+ // scope — these can never be project symbols/imports/globals, so a bare call to one
35
+ // is neither a real link target nor a resolution failure; see RawLocalBinding.
36
+ const localNamesPerScope = new Map();
37
+ for (const lb of input.localBindings ?? []) {
38
+ let names = localNamesPerScope.get(lb.scope);
39
+ if (!names) {
40
+ names = new Set();
41
+ localNamesPerScope.set(lb.scope, names);
42
+ }
43
+ names.add(lb.name);
44
+ }
45
+ const isKnownLocal = (call) => localNamesPerScope.get(call.enclosingSymbolId)?.has(call.calleeName) ?? false;
19
46
  // Build re-export map: file → (name → sourceFile)
20
47
  const reExportMap = buildReExportMap(input.reExports ?? [], input.resolvedImportPaths);
21
48
  // Build imported names per file: file → (name → targetFile)
@@ -264,31 +291,52 @@ export function resolveLinksWithStats(input) {
264
291
  const extNames = externalNamesPerFile.get(call.filePath);
265
292
  if (call.receiver ||
266
293
  BUILTIN_GLOBALS.has(call.calleeName) ||
294
+ TEST_FRAMEWORK_GLOBALS.has(call.calleeName) ||
295
+ WEB_DOM_GLOBALS.has(call.calleeName) ||
267
296
  extNames?.has(call.calleeName)) {
268
297
  externalCalls++;
269
298
  }
270
- else {
299
+ else if (!call.isArgumentRef && !isKnownLocal(call)) {
300
+ // isArgumentRef identifiers with zero project-symbol candidates are almost
301
+ // always plain data values passed as arguments (e.g. `getChannel(workspaceId)`),
302
+ // not genuine callee references — the extraction query captures argument-position
303
+ // identifiers broadly to catch real callback refs (`onMounted(handler)`), but when
304
+ // no project symbol shares the name, there's nothing that "should have" resolved.
305
+ // Likewise, a bare call to a name that's a known local declaration in this exact
306
+ // scope (a useState setter, a destructured callback prop) can never be a project
307
+ // symbol by construction — see RawLocalBinding.
271
308
  unresolvedCalls++;
272
309
  }
310
+ tryLinkReceiverReference(call, symbolByName, importedNamesPerFile, links);
273
311
  continue;
274
312
  }
275
313
  // Fast path: unique name globally.
276
314
  // Skip this shortcut when:
315
+ // - the call has a receiver AND the only candidate is a standalone
316
+ // function (not a method) AND the caller file is a dynamically-typed
317
+ // language (Python, PHP, Ruby) — this prevents linking
318
+ // `self.x.func()` to an unrelated top-level `def func()` that
319
+ // happens to share the same name, when the receiver's type cannot
320
+ // be statically determined.
277
321
  // - the call has a receiver AND the name is a common built-in prototype method
278
322
  // (`pattern.exec()`, `fileSet.add()`) — those must go through receiver-aware
279
323
  // narrowing below instead of being linked by bare name to an unrelated project
280
- // symbol that merely happens to share the name. Receiver calls to any other
281
- // (non-built-in) method name still take the fast path, since that's what
282
- // correctly resolves single-candidate methods like `self.save()` in
283
- // Python/Go/Rust fixtures — narrowing isn't reliable for those receiver types.
324
+ // symbol that merely happens to share the name.
284
325
  // - the identifier was captured from an argument position, not an actual
285
326
  // invocation (`onMounted(handler)`, decorator args) — it may just be a plain
286
327
  // local variable (e.g. `resolve(root, file)`), not a function reference. Let it
287
328
  // fall through to same-file/imported/proximity-scored matching below instead of
288
329
  // blindly linking to a same-named symbol anywhere in the repo.
330
+ // - the call has no receiver AND the name is a known local declaration in this
331
+ // scope (e.g. `const { t } = useTranslation(); t('key')`) — even a *globally
332
+ // unique* same-named project symbol must lose to a local binding, by real
333
+ // lexical scoping rules. Let it fall through to the same-file/imported/local
334
+ // chain below, which checks local-binding shadowing before any cross-file guess.
289
335
  if (candidates.length === 1 &&
290
336
  !(call.receiver && BUILTIN_METHOD_NAMES.has(call.calleeName)) &&
291
- !call.isArgumentRef) {
337
+ !(call.receiver && candidates[0].kind === 'function' && isDynamicLang(call.filePath)) &&
338
+ !call.isArgumentRef &&
339
+ !(!call.receiver && isKnownLocal(call))) {
292
340
  // Check if the caller imported this name from an external module, or it's a builtin global
293
341
  const fileExtNames = externalNamesPerFile.get(call.filePath);
294
342
  if (BUILTIN_GLOBALS.has(call.calleeName) || fileExtNames?.has(call.calleeName)) {
@@ -301,27 +349,47 @@ export function resolveLinksWithStats(input) {
301
349
  // ── Receiver-aware narrowing (highest priority for member calls) ──
302
350
  if (call.receiver) {
303
351
  const narrowed = narrowByReceiver(call, candidates, symbolById, symbolByName, importedNamesPerFile, input.symbolsByFile, typeBindingsPerFile, heritageAncestors);
352
+ // Was this receiver's OWN declared type imported from an external module
353
+ // (e.g. `this.configService: ConfigService` where ConfigService comes from
354
+ // '@nestjs/config')? Existing classification below only checked the callee
355
+ // method NAME against external names — never the receiver's type origin —
356
+ // so calls like `configService.get(...)` were misclassified as unresolved
357
+ // even though the receiver is provably external. Checking method-name
358
+ // candidates first (via narrowByReceiver above) still takes priority, since
359
+ // a receiver's declared type can be narrower than its runtime type.
360
+ const receiverIsExternallyTyped = isReceiverExternallyTyped(call, typeBindingsPerFile, symbolById, externalNamesPerFile);
304
361
  if (narrowed) {
305
362
  if (narrowed.confidence >= MIN_LINK_CONFIDENCE) {
306
363
  links.push(makeLink(call.enclosingSymbolId, narrowed.symbol.id, 'calls', narrowed.confidence, call.line));
307
364
  }
365
+ else if (receiverIsExternallyTyped) {
366
+ externalCalls++;
367
+ tryLinkReceiverReference(call, symbolByName, importedNamesPerFile, links);
368
+ }
308
369
  else {
309
370
  unresolvedCalls++;
371
+ tryLinkReceiverReference(call, symbolByName, importedNamesPerFile, links);
310
372
  }
311
373
  continue;
312
374
  }
313
375
  // Receiver didn't resolve to a known type — treat as external call
314
376
  // Don't fall through to name-only matching which would link to unrelated symbols
315
377
  const extNames = externalNamesPerFile.get(call.filePath);
316
- if (BUILTIN_GLOBALS.has(call.calleeName) || extNames?.has(call.calleeName)) {
378
+ if (BUILTIN_GLOBALS.has(call.calleeName) || extNames?.has(call.calleeName) || receiverIsExternallyTyped) {
317
379
  externalCalls++;
318
380
  }
319
381
  else {
320
382
  unresolvedCalls++;
321
383
  }
384
+ tryLinkReceiverReference(call, symbolByName, importedNamesPerFile, links);
322
385
  continue;
323
386
  }
324
387
  // ── Same file match ──
388
+ // Takes priority over the local-binding check below: the local-declaration extraction
389
+ // captures ANY variable_declarator regardless of nesting (including module-level ones
390
+ // that ARE real project symbols), so a name appearing in localNamesPerScope does not
391
+ // by itself rule out a legitimate same-file target — only cross-file candidates are at
392
+ // real risk of the "t() shadows an unrelated file's symbol" mis-link this guards against.
325
393
  const sameFile = candidates.filter(s => s.filePath === call.filePath);
326
394
  if (sameFile.length > 0) {
327
395
  links.push(makeLink(call.enclosingSymbolId, sameFile[0].id, 'calls', 0.9, call.line));
@@ -337,13 +405,29 @@ export function resolveLinksWithStats(input) {
337
405
  continue;
338
406
  }
339
407
  }
408
+ // ── Local declaration shadowing ──
409
+ // No same-file or imported candidate — the only remaining option is cross-file
410
+ // proximity scoring, which is exactly the risky case: a bare call whose name is a
411
+ // known local declaration in this scope (e.g. `const { t } = useTranslation(); t('key')`
412
+ // where some unrelated file also happens to export a project symbol literally named
413
+ // `t`) should never be linked to that unrelated symbol, by real lexical scoping rules
414
+ // (the local binding always wins). Short-circuiting here — instead of letting proximity
415
+ // scoring possibly cross the confidence threshold — prevents that wrong link and avoids
416
+ // counting it as unresolved; it was never truly ambiguous, milens just didn't know the
417
+ // name was locally bound.
418
+ if (isKnownLocal(call)) {
419
+ continue;
420
+ }
340
421
  // ── Proximity scoring fallback (replaces blind candidates[0]) ──
341
422
  const best = scoreCandidates(call, candidates, directImportsPerFile);
342
423
  if (best.confidence >= MIN_LINK_CONFIDENCE) {
343
424
  links.push(makeLink(call.enclosingSymbolId, best.symbol.id, 'calls', best.confidence, call.line));
344
425
  }
345
- else {
346
- // Below threshold — "no link is better than a wrong link"
426
+ else if (!call.isArgumentRef) {
427
+ // Below threshold — "no link is better than a wrong link". For isArgumentRef
428
+ // identifiers this is frequently a plain local value that only coincidentally
429
+ // shares a name with unrelated project symbols (see the no-candidates branch
430
+ // above for the full rationale) — declining to link is correct, not a failure.
347
431
  unresolvedCalls++;
348
432
  }
349
433
  }
@@ -398,16 +482,39 @@ export function resolveLinksWithStats(input) {
398
482
  for (const h of input.heritage) {
399
483
  const children = symbolByName.get(h.childName);
400
484
  const parents = symbolByName.get(h.parentName);
401
- if (!children || !parents)
485
+ if (!children)
402
486
  continue;
403
487
  const child = children.find(s => s.filePath === h.filePath) ?? children[0];
404
- // Prefer imported parent > same-file parent > first match
405
- const importedFile = importedNamesPerFile.get(h.filePath)?.get(h.parentName);
406
- const parent = (importedFile ? parents.find(s => s.filePath === importedFile) : undefined)
407
- ?? parents.find(s => s.filePath === h.filePath)
408
- ?? parents[0];
409
- if (child && parent) {
410
- links.push(makeLink(child.id, parent.id, h.type, 0.95, h.line));
488
+ if (!child)
489
+ continue;
490
+ if (parents && parents.length > 0) {
491
+ // Prefer imported parent > same-file parent > first match
492
+ const importedFile = importedNamesPerFile.get(h.filePath)?.get(h.parentName);
493
+ const parent = (importedFile ? parents.find(s => s.filePath === importedFile) : undefined)
494
+ ?? parents.find(s => s.filePath === h.filePath)
495
+ ?? parents[0];
496
+ if (parent) {
497
+ links.push(makeLink(child.id, parent.id, h.type, 0.95, h.line));
498
+ }
499
+ }
500
+ else {
501
+ // Parent not found in project symbols — check if it comes from an external import
502
+ const extNames = externalNamesPerFile.get(h.filePath);
503
+ const isExternal = extNames?.has(h.parentName) || BUILTIN_TYPES.has(h.parentName);
504
+ if (isExternal) {
505
+ const extId = `#external:${h.parentName}`;
506
+ const parentKind = h.type === 'implements' ? 'interface' : 'class';
507
+ externalSymbols.push({
508
+ id: extId,
509
+ name: h.parentName,
510
+ kind: parentKind,
511
+ filePath: '(external)',
512
+ startLine: 0,
513
+ endLine: 0,
514
+ exported: true,
515
+ });
516
+ links.push(makeLink(child.id, extId, h.type, 0.7, h.line));
517
+ }
411
518
  }
412
519
  }
413
520
  // ── Containment links (method → class) ──
@@ -447,7 +554,7 @@ export function resolveLinksWithStats(input) {
447
554
  }
448
555
  }
449
556
  }
450
- return { links: deduplicateLinks(links), unresolvedImports, unresolvedCalls, externalImports, externalCalls };
557
+ return { links: deduplicateLinks(links), unresolvedImports, unresolvedCalls, externalImports, externalCalls, externalSymbols };
451
558
  }
452
559
  // ── Receiver-aware call narrowing ──
453
560
  function narrowByReceiver(call, candidates, symbolById, symbolByName, importedNamesPerFile, symbolsByFile, typeBindingsPerFile, heritageAncestors) {
@@ -514,37 +621,58 @@ function narrowByReceiver(call, candidates, symbolById, symbolByName, importedNa
514
621
  return null;
515
622
  }
516
623
  // ── Type binding lookup: variable → type → method candidate (scope-aware) ──
517
- function narrowByTypeBinding(varName, filePath, candidates, symbolById, typeBindingsPerFile, callEnclosingId, heritageAncestors) {
624
+ /** Resolve the declared type name of a variable from extracted type bindings,
625
+ * preferring a binding scoped to the call site (or its parent scope) over a
626
+ * module-level/first-seen fallback. Shared by narrowByTypeBinding (method
627
+ * resolution) and the receiver-external-type classification check below —
628
+ * both need "what type is this receiver bound to," just for different purposes. */
629
+ function resolveTypeNameForVar(varName, filePath, typeBindingsPerFile, symbolById, callEnclosingId) {
518
630
  const fileBindings = typeBindingsPerFile.get(filePath);
519
631
  if (!fileBindings)
520
- return null;
632
+ return undefined;
521
633
  const entries = fileBindings.get(varName);
522
634
  if (!entries || entries.length === 0)
523
- return null;
635
+ return undefined;
524
636
  // Scope-aware: prefer binding from same enclosing scope as the call
525
- let typeName;
526
637
  if (callEnclosingId && entries.length > 1) {
527
638
  // First try exact scope match
528
639
  const scopedEntry = entries.find(e => e.scope === callEnclosingId);
529
- if (scopedEntry) {
530
- typeName = scopedEntry.typeName;
531
- }
532
- else {
533
- // Try parent scope (e.g., call is in method, binding in class)
534
- const enclosing = symbolById.get(callEnclosingId);
535
- if (enclosing?.parentId) {
536
- const parentEntry = entries.find(e => e.scope === enclosing.parentId);
537
- if (parentEntry)
538
- typeName = parentEntry.typeName;
539
- }
640
+ if (scopedEntry)
641
+ return scopedEntry.typeName;
642
+ // Try parent scope (e.g., call is in method, binding in class)
643
+ const enclosing = symbolById.get(callEnclosingId);
644
+ if (enclosing?.parentId) {
645
+ const parentEntry = entries.find(e => e.scope === enclosing.parentId);
646
+ if (parentEntry)
647
+ return parentEntry.typeName;
540
648
  }
541
649
  }
542
650
  // Fallback: if only one entry or no scope match, use first (module-level or single)
543
- if (!typeName) {
544
- // Prefer module-level binding (scope undefined) when no scope match
545
- const moduleLevelEntry = entries.find(e => !e.scope);
546
- typeName = moduleLevelEntry?.typeName ?? entries[0].typeName;
547
- }
651
+ // Prefer module-level binding (scope undefined) when no scope match
652
+ const moduleLevelEntry = entries.find(e => !e.scope);
653
+ return moduleLevelEntry?.typeName ?? entries[0].typeName;
654
+ }
655
+ /** True when a receiver method call's receiver is itself declared with a type that
656
+ * came from an external (non-project) import — e.g. `this.configService: ConfigService`
657
+ * where `ConfigService` is imported from '@nestjs/config'. In that case any method
658
+ * called on the receiver is necessarily external too, regardless of whether the
659
+ * specific method name happens to also be used somewhere in the project. */
660
+ function isReceiverExternallyTyped(call, typeBindingsPerFile, symbolById, externalNamesPerFile) {
661
+ const receiver = call.receiver;
662
+ if (!receiver || receiver === 'this' || receiver === 'self')
663
+ return false;
664
+ const varName = (receiver.startsWith('this.') || receiver.startsWith('self.'))
665
+ ? receiver.slice(receiver.indexOf('.') + 1)
666
+ : receiver;
667
+ const typeName = resolveTypeNameForVar(varName, call.filePath, typeBindingsPerFile, symbolById, call.enclosingSymbolId);
668
+ if (!typeName)
669
+ return false;
670
+ return externalNamesPerFile.get(call.filePath)?.has(typeName) ?? false;
671
+ }
672
+ function narrowByTypeBinding(varName, filePath, candidates, symbolById, typeBindingsPerFile, callEnclosingId, heritageAncestors) {
673
+ const typeName = resolveTypeNameForVar(varName, filePath, typeBindingsPerFile, symbolById, callEnclosingId);
674
+ if (!typeName)
675
+ return null;
548
676
  // Find candidate whose parent class name matches the resolved type,
549
677
  // including ancestors via MRO (heritage chain)
550
678
  const method = resolveMethodByType(candidates, typeName, symbolById, heritageAncestors);
@@ -746,6 +874,48 @@ function makeLink(fromId, toId, type, confidence, line) {
746
874
  line,
747
875
  };
748
876
  }
877
+ /**
878
+ * Last resort when a receiver-based call's callee could not be resolved to a
879
+ * project symbol (whether because no candidate shares its name at all, or
880
+ * because receiver-type narrowing failed/scored too low). The callee itself
881
+ * (e.g. `.join()`, `.has()`) may genuinely be external/builtin — but the
882
+ * receiver it's invoked on can still be a real local symbol worth recording
883
+ * as a dependency (e.g. `SAFETY_TOOLS.join('/')`: SAFETY_TOOLS is a project
884
+ * const, `join` is Array.prototype.join and will never resolve). Without
885
+ * this, the receiver reference is silently dropped from the graph entirely.
886
+ * Only a bare-identifier receiver is considered — compound paths (`this.foo`,
887
+ * `a.b`) are intentionally out of scope. Resolution prefers the file the
888
+ * receiver was actually imported from (see the import-map lookup below);
889
+ * otherwise falls back to a same-file match. This is a best-effort fallback,
890
+ * not a scope-accurate resolution — it can miss renamed/aliased imports.
891
+ */
892
+ function tryLinkReceiverReference(call, symbolByName, importedNamesPerFile, links) {
893
+ if (!call.receiver ||
894
+ call.receiver.includes('.') ||
895
+ call.receiver === 'this' ||
896
+ call.receiver === 'self' ||
897
+ call.isArgumentRef) {
898
+ return;
899
+ }
900
+ const receiverCandidates = symbolByName.get(call.receiver);
901
+ if (!receiverCandidates || receiverCandidates.length === 0)
902
+ return;
903
+ // Prefer the file the receiver name was actually imported from, if any —
904
+ // this correctly disambiguates when another file coincidentally declares a
905
+ // same-named symbol. Falls back to a same-file match otherwise. Like the
906
+ // resolver's existing "imported type name" strategy, this assumes the local
907
+ // import binding name matches the target symbol's own name — it will miss
908
+ // renamed/aliased default imports (e.g. `import Foo from './registry'` where
909
+ // the exported symbol is actually named something else); that is a known,
910
+ // accepted limitation shared with the rest of the receiver-resolution logic.
911
+ const importedFile = importedNamesPerFile.get(call.filePath)?.get(call.receiver);
912
+ const target = importedFile
913
+ ? receiverCandidates.find(s => s.filePath === importedFile)
914
+ : receiverCandidates.find(s => s.filePath === call.filePath);
915
+ if (target) {
916
+ links.push(makeLink(call.enclosingSymbolId, target.id, 'references', 0.85, call.line));
917
+ }
918
+ }
749
919
  function deduplicateLinks(links) {
750
920
  const seen = new Set();
751
921
  return links.filter(l => {
@@ -823,6 +993,12 @@ function findDefaultExport(targetSymbols) {
823
993
  // Fallback to first
824
994
  return exported[0];
825
995
  }
996
+ // ── Dynamic language detection ──
997
+ /** Files in dynamically-typed languages where receiver types can't be statically resolved */
998
+ function isDynamicLang(filePath) {
999
+ const ext = filePath.split('.').pop()?.toLowerCase();
1000
+ return ext === 'py' || ext === 'rb' || ext === 'php';
1001
+ }
826
1002
  // ── External module detection ──
827
1003
  /** Returns true if the module path refers to an external package (not a relative local import) */
828
1004
  function isExternalModule(modulePath) {
@@ -870,6 +1046,33 @@ const BUILTIN_GLOBALS = new Set([
870
1046
  'array_map', 'array_filter', 'array_merge', 'array_keys', 'array_values',
871
1047
  'count', 'strlen', 'substr', 'explode', 'implode', 'trim',
872
1048
  ]);
1049
+ /** JS/TS test-framework globals (Jest/Vitest/Mocha/Jasmine) injected ambiently when a
1050
+ * project opts into globals mode (e.g. Vitest's `globals: true`) — no import, no project
1051
+ * symbol. Intentionally kept separate from BUILTIN_GLOBALS: these names are common enough
1052
+ * as ordinary project identifiers (`test`, `it`, `suite`) that treating them as unconditional
1053
+ * globals in the "unique candidate" fast path could wrongly suppress a real link to an
1054
+ * actual project symbol of the same name. Only checked where `candidates.length === 0` is
1055
+ * already established (no project symbol shares the name), where that risk cannot occur. */
1056
+ const TEST_FRAMEWORK_GLOBALS = new Set([
1057
+ 'describe', 'it', 'test', 'expect', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll',
1058
+ 'suite', 'bench', 'vi', 'jest',
1059
+ ]);
1060
+ /** Web/DOM APIs — browser globals (also present in Electron renderer processes and
1061
+ * polyfilled/native in modern Node) — ambient, never a project symbol or tracked import.
1062
+ * Same isolation rationale as TEST_FRAMEWORK_GLOBALS: several of these names (`Event`,
1063
+ * `File`, `Request`, `Response`, `Worker`, `Image`, `History`) are plausible names for a
1064
+ * project's own classes/DTOs, so this set is only ever consulted where
1065
+ * `candidates.length === 0` already holds — it can never shadow a real project symbol. */
1066
+ const WEB_DOM_GLOBALS = new Set([
1067
+ 'URL', 'URLSearchParams', 'FormData', 'Headers', 'Request', 'Response',
1068
+ 'requestAnimationFrame', 'cancelAnimationFrame', 'requestIdleCallback', 'cancelIdleCallback',
1069
+ 'IntersectionObserver', 'ResizeObserver', 'MutationObserver', 'PerformanceObserver',
1070
+ 'AbortController', 'AbortSignal', 'WebSocket', 'Notification', 'Blob', 'File', 'FileReader',
1071
+ 'CustomEvent', 'Event', 'EventTarget', 'Worker', 'SharedWorker', 'MessageChannel', 'MessagePort',
1072
+ 'localStorage', 'sessionStorage', 'indexedDB', 'navigator', 'window', 'document', 'location',
1073
+ 'history', 'performance', 'crypto', 'TextEncoder', 'TextDecoder',
1074
+ 'CSS', 'Image', 'Audio', 'Option',
1075
+ ]);
873
1076
  /** Common built-in prototype/instance method names (Set/Map/Array/RegExp/String/Promise/...)
874
1077
  * that frequently collide by bare name with unrelated project symbols. Unlike
875
1078
  * BUILTIN_GLOBALS (free-standing functions), these only matter when called with