gitnexus 1.6.3-rc.9 → 1.6.3

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 (257) hide show
  1. package/README.md +21 -5
  2. package/dist/_shared/graph/types.d.ts +16 -0
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +4 -2
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js +2 -0
  7. package/dist/_shared/index.js.map +1 -1
  8. package/dist/_shared/scope-resolution/def-index.js +2 -2
  9. package/dist/_shared/scope-resolution/def-index.js.map +1 -1
  10. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +8 -0
  11. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
  12. package/dist/_shared/scope-resolution/method-dispatch-index.js +2 -2
  13. package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
  14. package/dist/_shared/scope-resolution/module-scope-index.d.ts +8 -0
  15. package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -1
  16. package/dist/_shared/scope-resolution/module-scope-index.js +10 -2
  17. package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -1
  18. package/dist/_shared/scope-resolution/parsed-file.d.ts +76 -0
  19. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -0
  20. package/dist/_shared/scope-resolution/parsed-file.js +54 -0
  21. package/dist/_shared/scope-resolution/parsed-file.js.map +1 -0
  22. package/dist/_shared/scope-resolution/position-index.d.ts +12 -0
  23. package/dist/_shared/scope-resolution/position-index.d.ts.map +1 -1
  24. package/dist/_shared/scope-resolution/position-index.js +2 -2
  25. package/dist/_shared/scope-resolution/position-index.js.map +1 -1
  26. package/dist/_shared/scope-resolution/qualified-name-index.js +2 -2
  27. package/dist/_shared/scope-resolution/qualified-name-index.js.map +1 -1
  28. package/dist/_shared/scope-resolution/reference-site.d.ts +75 -0
  29. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -0
  30. package/dist/_shared/scope-resolution/reference-site.js +24 -0
  31. package/dist/_shared/scope-resolution/reference-site.js.map +1 -0
  32. package/dist/_shared/scope-resolution/registries/evidence.js +5 -0
  33. package/dist/_shared/scope-resolution/registries/evidence.js.map +1 -1
  34. package/dist/_shared/scope-resolution/registries/lookup-core.js +21 -5
  35. package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
  36. package/dist/_shared/scope-resolution/resolve-type-ref.d.ts +1 -10
  37. package/dist/_shared/scope-resolution/resolve-type-ref.d.ts.map +1 -1
  38. package/dist/_shared/scope-resolution/resolve-type-ref.js +6 -0
  39. package/dist/_shared/scope-resolution/resolve-type-ref.js.map +1 -1
  40. package/dist/_shared/scope-resolution/scope-tree.d.ts +4 -4
  41. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  42. package/dist/_shared/scope-resolution/scope-tree.js +3 -2
  43. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  44. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +6 -2
  45. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +1 -1
  46. package/dist/_shared/scope-resolution/shadow/aggregate.js +5 -0
  47. package/dist/_shared/scope-resolution/shadow/aggregate.js.map +1 -1
  48. package/dist/_shared/scope-resolution/types.d.ts +11 -0
  49. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  50. package/dist/cli/ai-context.js +35 -4
  51. package/dist/cli/analyze.d.ts +27 -0
  52. package/dist/cli/analyze.js +31 -1
  53. package/dist/cli/clean.js +19 -1
  54. package/dist/cli/group.js +73 -0
  55. package/dist/cli/index-repo.js +8 -1
  56. package/dist/cli/index.js +26 -1
  57. package/dist/cli/list.js +11 -1
  58. package/dist/cli/remove.d.ts +30 -0
  59. package/dist/cli/remove.js +99 -0
  60. package/dist/cli/setup.js +185 -57
  61. package/dist/cli/tool.d.ts +5 -0
  62. package/dist/cli/tool.js +42 -0
  63. package/dist/config/ignore-service.d.ts +9 -0
  64. package/dist/config/ignore-service.js +80 -13
  65. package/dist/core/embedding-mode.d.ts +30 -0
  66. package/dist/core/embedding-mode.js +30 -0
  67. package/dist/core/embeddings/ast-utils.js +22 -22
  68. package/dist/core/embeddings/chunker.js +30 -25
  69. package/dist/core/embeddings/embedding-pipeline.d.ts +6 -0
  70. package/dist/core/embeddings/embedding-pipeline.js +15 -6
  71. package/dist/core/embeddings/text-generator.d.ts +1 -1
  72. package/dist/core/embeddings/text-generator.js +33 -24
  73. package/dist/core/embeddings/types.d.ts +43 -1
  74. package/dist/core/embeddings/types.js +101 -29
  75. package/dist/core/git-staleness.d.ts +18 -0
  76. package/dist/core/git-staleness.js +108 -0
  77. package/dist/core/graph/graph.js +115 -20
  78. package/dist/core/graph/types.d.ts +12 -1
  79. package/dist/core/group/config-parser.d.ts +4 -0
  80. package/dist/core/group/config-parser.js +18 -1
  81. package/dist/core/group/cross-impact.d.ts +41 -0
  82. package/dist/core/group/cross-impact.js +441 -0
  83. package/dist/core/group/extractors/http-patterns/php.js +126 -18
  84. package/dist/core/group/group-path-utils.d.ts +17 -0
  85. package/dist/core/group/group-path-utils.js +40 -0
  86. package/dist/core/group/resolve-at-member.d.ts +10 -0
  87. package/dist/core/group/resolve-at-member.js +31 -0
  88. package/dist/core/group/service.d.ts +9 -0
  89. package/dist/core/group/service.js +259 -25
  90. package/dist/core/group/types.d.ts +30 -0
  91. package/dist/core/ingestion/ast-cache.d.ts +16 -1
  92. package/dist/core/ingestion/ast-cache.js +14 -2
  93. package/dist/core/ingestion/call-processor.js +9 -0
  94. package/dist/core/ingestion/emit-references.d.ts +88 -0
  95. package/dist/core/ingestion/emit-references.js +229 -0
  96. package/dist/core/ingestion/filesystem-walker.js +6 -4
  97. package/dist/core/ingestion/finalize-orchestrator.d.ts +63 -0
  98. package/dist/core/ingestion/finalize-orchestrator.js +139 -0
  99. package/dist/core/ingestion/framework-detection.js +6 -2
  100. package/dist/core/ingestion/import-processor.js +4 -0
  101. package/dist/core/ingestion/import-resolvers/python.js +9 -6
  102. package/dist/core/ingestion/import-target-adapter.d.ts +73 -0
  103. package/dist/core/ingestion/import-target-adapter.js +95 -0
  104. package/dist/core/ingestion/language-provider.d.ts +36 -33
  105. package/dist/core/ingestion/languages/csharp/accessor-unwrap.d.ts +21 -0
  106. package/dist/core/ingestion/languages/csharp/accessor-unwrap.js +56 -0
  107. package/dist/core/ingestion/languages/csharp/arity-metadata.d.ts +26 -0
  108. package/dist/core/ingestion/languages/csharp/arity-metadata.js +46 -0
  109. package/dist/core/ingestion/languages/csharp/arity.d.ts +23 -0
  110. package/dist/core/ingestion/languages/csharp/arity.js +37 -0
  111. package/dist/core/ingestion/languages/csharp/cache-stats.d.ts +15 -0
  112. package/dist/core/ingestion/languages/csharp/cache-stats.js +26 -0
  113. package/dist/core/ingestion/languages/csharp/captures.d.ts +19 -0
  114. package/dist/core/ingestion/languages/csharp/captures.js +249 -0
  115. package/dist/core/ingestion/languages/csharp/import-decomposer.d.ts +19 -0
  116. package/dist/core/ingestion/languages/csharp/import-decomposer.js +93 -0
  117. package/dist/core/ingestion/languages/csharp/import-target.d.ts +25 -0
  118. package/dist/core/ingestion/languages/csharp/import-target.js +123 -0
  119. package/dist/core/ingestion/languages/csharp/index.d.ts +82 -0
  120. package/dist/core/ingestion/languages/csharp/index.js +82 -0
  121. package/dist/core/ingestion/languages/csharp/interpret.d.ts +15 -0
  122. package/dist/core/ingestion/languages/csharp/interpret.js +132 -0
  123. package/dist/core/ingestion/languages/csharp/merge-bindings.d.ts +27 -0
  124. package/dist/core/ingestion/languages/csharp/merge-bindings.js +55 -0
  125. package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +50 -0
  126. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +374 -0
  127. package/dist/core/ingestion/languages/csharp/query.d.ts +35 -0
  128. package/dist/core/ingestion/languages/csharp/query.js +515 -0
  129. package/dist/core/ingestion/languages/csharp/receiver-binding.d.ts +31 -0
  130. package/dist/core/ingestion/languages/csharp/receiver-binding.js +135 -0
  131. package/dist/core/ingestion/languages/csharp/scope-resolver.d.ts +10 -0
  132. package/dist/core/ingestion/languages/csharp/scope-resolver.js +63 -0
  133. package/dist/core/ingestion/languages/csharp/simple-hooks.d.ts +53 -0
  134. package/dist/core/ingestion/languages/csharp/simple-hooks.js +76 -0
  135. package/dist/core/ingestion/languages/csharp.js +14 -0
  136. package/dist/core/ingestion/languages/python/arity-metadata.d.ts +24 -0
  137. package/dist/core/ingestion/languages/python/arity-metadata.js +45 -0
  138. package/dist/core/ingestion/languages/python/arity.d.ts +22 -0
  139. package/dist/core/ingestion/languages/python/arity.js +38 -0
  140. package/dist/core/ingestion/languages/python/cache-stats.d.ts +17 -0
  141. package/dist/core/ingestion/languages/python/cache-stats.js +28 -0
  142. package/dist/core/ingestion/languages/python/captures.d.ts +19 -0
  143. package/dist/core/ingestion/languages/python/captures.js +106 -0
  144. package/dist/core/ingestion/languages/python/import-decomposer.d.ts +15 -0
  145. package/dist/core/ingestion/languages/python/import-decomposer.js +112 -0
  146. package/dist/core/ingestion/languages/python/import-target.d.ts +21 -0
  147. package/dist/core/ingestion/languages/python/import-target.js +99 -0
  148. package/dist/core/ingestion/languages/python/index.d.ts +80 -0
  149. package/dist/core/ingestion/languages/python/index.js +80 -0
  150. package/dist/core/ingestion/languages/python/interpret.d.ts +15 -0
  151. package/dist/core/ingestion/languages/python/interpret.js +191 -0
  152. package/dist/core/ingestion/languages/python/merge-bindings.d.ts +16 -0
  153. package/dist/core/ingestion/languages/python/merge-bindings.js +44 -0
  154. package/dist/core/ingestion/languages/python/query.d.ts +9 -0
  155. package/dist/core/ingestion/languages/python/query.js +267 -0
  156. package/dist/core/ingestion/languages/python/receiver-binding.d.ts +21 -0
  157. package/dist/core/ingestion/languages/python/receiver-binding.js +116 -0
  158. package/dist/core/ingestion/languages/python/scope-resolver.d.ts +16 -0
  159. package/dist/core/ingestion/languages/python/scope-resolver.js +53 -0
  160. package/dist/core/ingestion/languages/python/simple-hooks.d.ts +23 -0
  161. package/dist/core/ingestion/languages/python/simple-hooks.js +35 -0
  162. package/dist/core/ingestion/languages/python.js +14 -0
  163. package/dist/core/ingestion/model/method-registry.d.ts +9 -0
  164. package/dist/core/ingestion/model/method-registry.js +4 -0
  165. package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +59 -0
  166. package/dist/core/ingestion/model/scope-resolution-indexes.js +42 -0
  167. package/dist/core/ingestion/model/semantic-model.d.ts +64 -0
  168. package/dist/core/ingestion/model/semantic-model.js +55 -0
  169. package/dist/core/ingestion/mro-processor.js +38 -22
  170. package/dist/core/ingestion/parsing-processor.d.ts +18 -1
  171. package/dist/core/ingestion/parsing-processor.js +45 -11
  172. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  173. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  174. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +10 -0
  175. package/dist/core/ingestion/pipeline-phases/parse-impl.js +17 -2
  176. package/dist/core/ingestion/pipeline-phases/parse.d.ts +18 -0
  177. package/dist/core/ingestion/pipeline.js +2 -1
  178. package/dist/core/ingestion/registry-primary-flag.d.ts +86 -0
  179. package/dist/core/ingestion/registry-primary-flag.js +111 -0
  180. package/dist/core/ingestion/resolve-references.d.ts +63 -0
  181. package/dist/core/ingestion/resolve-references.js +175 -0
  182. package/dist/core/ingestion/scope-extractor-bridge.d.ts +32 -0
  183. package/dist/core/ingestion/scope-extractor-bridge.js +44 -0
  184. package/dist/core/ingestion/scope-extractor.d.ts +86 -0
  185. package/dist/core/ingestion/scope-extractor.js +758 -0
  186. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +372 -0
  187. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +212 -0
  188. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +43 -0
  189. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +79 -0
  190. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +57 -0
  191. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +112 -0
  192. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.d.ts +17 -0
  193. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +46 -0
  194. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +19 -0
  195. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +30 -0
  196. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.d.ts +37 -0
  197. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +113 -0
  198. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +38 -0
  199. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +73 -0
  200. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +42 -0
  201. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +198 -0
  202. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +27 -0
  203. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +131 -0
  204. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.d.ts +48 -0
  205. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +130 -0
  206. package/dist/core/ingestion/scope-resolution/passes/mro.d.ts +42 -0
  207. package/dist/core/ingestion/scope-resolution/passes/mro.js +99 -0
  208. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +26 -0
  209. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +61 -0
  210. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +46 -0
  211. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +327 -0
  212. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +47 -0
  213. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +130 -0
  214. package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.d.ts +68 -0
  215. package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +125 -0
  216. package/dist/core/ingestion/scope-resolution/pipeline/registry.d.ts +17 -0
  217. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +21 -0
  218. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +66 -0
  219. package/dist/core/ingestion/scope-resolution/pipeline/run.js +157 -0
  220. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +36 -0
  221. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +52 -0
  222. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +127 -0
  223. package/dist/core/ingestion/scope-resolution/scope/walkers.js +349 -0
  224. package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +52 -0
  225. package/dist/core/ingestion/scope-resolution/workspace-index.js +61 -0
  226. package/dist/core/ingestion/shadow-harness.d.ts +113 -0
  227. package/dist/core/ingestion/shadow-harness.js +148 -0
  228. package/dist/core/ingestion/utils/ast-helpers.d.ts +19 -1
  229. package/dist/core/ingestion/utils/ast-helpers.js +70 -0
  230. package/dist/core/ingestion/utils/max-file-size.d.ts +20 -0
  231. package/dist/core/ingestion/utils/max-file-size.js +52 -0
  232. package/dist/core/ingestion/workers/parse-worker.d.ts +9 -0
  233. package/dist/core/ingestion/workers/parse-worker.js +57 -21
  234. package/dist/core/lbug/lbug-adapter.d.ts +22 -2
  235. package/dist/core/lbug/lbug-adapter.js +58 -14
  236. package/dist/core/lbug/pool-adapter.d.ts +17 -0
  237. package/dist/core/lbug/pool-adapter.js +24 -14
  238. package/dist/core/run-analyze.d.ts +32 -0
  239. package/dist/core/run-analyze.js +74 -19
  240. package/dist/core/search/bm25-index.d.ts +18 -0
  241. package/dist/core/search/bm25-index.js +125 -12
  242. package/dist/core/tree-sitter/parser-loader.js +6 -1
  243. package/dist/mcp/local/local-backend.d.ts +67 -3
  244. package/dist/mcp/local/local-backend.js +296 -34
  245. package/dist/mcp/resources.d.ts +31 -0
  246. package/dist/mcp/resources.js +100 -17
  247. package/dist/mcp/tools.d.ts +4 -1
  248. package/dist/mcp/tools.js +75 -54
  249. package/dist/server/api.js +6 -2
  250. package/dist/storage/git.d.ts +49 -0
  251. package/dist/storage/git.js +111 -0
  252. package/dist/storage/repo-manager.d.ts +246 -1
  253. package/dist/storage/repo-manager.js +391 -9
  254. package/package.json +7 -6
  255. package/scripts/bench-scope-resolution.ts +134 -0
  256. package/scripts/ci-list-migrated-languages.ts +24 -0
  257. package/skills/gitnexus-cli.md +1 -0
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Bridge between CLI-package per-language `ImportResolverFn`s and the
3
+ * shared `FinalizeHooks.resolveImportTarget` contract
4
+ * (RFC §5.2; Ring 2 PKG #922).
5
+ *
6
+ * The shared finalize algorithm (#915) asks one question:
7
+ *
8
+ * resolveImportTarget(targetRaw, fromFile, workspaceIndex): string | null
9
+ *
10
+ * The CLI already has 16 language-specific resolvers satisfying a
11
+ * richer signature:
12
+ *
13
+ * ImportResolverFn(rawImportPath, filePath, resolveCtx): ImportResult
14
+ *
15
+ * This module builds a dispatch adapter — one FinalizeHook implementation
16
+ * that looks up the file's language from its path and delegates to the
17
+ * right per-language resolver. Callers package per-language resolvers +
18
+ * a shared `ResolveCtx` into an opaque `ImportTargetWorkspace` and pass
19
+ * it as `workspaceIndex` to `finalizeScopeModel`.
20
+ *
21
+ * ## What's deliberately NOT here
22
+ *
23
+ * - **Re-implementation of any per-language resolver.** We wrap the
24
+ * existing `importResolver` field on each `LanguageProvider` — the
25
+ * same code path the legacy DAG uses today.
26
+ * - **Dynamic-import handling.** The shared finalize algorithm short-
27
+ * circuits `ParsedImport { kind: 'dynamic-unresolved' }` before
28
+ * calling `resolveImportTarget`, so the adapter never sees those.
29
+ * - **`importPathPreprocessor`.** Preprocessing belongs inside the
30
+ * provider's `interpretImport` hook (which writes the final
31
+ * `ParsedImport.targetRaw`). By the time finalize passes a
32
+ * `targetRaw` to this adapter, it is the string the provider wants
33
+ * resolved verbatim.
34
+ */
35
+ import { getLanguageFromFilename, } from '../../_shared/index.js';
36
+ /**
37
+ * Build the workspace index from a map of language → provider. Providers
38
+ * whose `importResolver` is absent are silently skipped (no language will
39
+ * ever hit that branch at dispatch time).
40
+ *
41
+ * The `resolveCtx` is shared across all languages. Callers assemble it
42
+ * once per run (the existing pipeline already does this for the legacy
43
+ * DAG) and hand it to both the legacy resolution path and this factory.
44
+ */
45
+ export function buildImportTargetWorkspace(providers, resolveCtx) {
46
+ const perLanguage = new Map();
47
+ for (const [lang, provider] of providers) {
48
+ if (provider.importResolver === undefined)
49
+ continue;
50
+ perLanguage.set(lang, { resolver: provider.importResolver, ctx: resolveCtx });
51
+ }
52
+ return { perLanguage };
53
+ }
54
+ /**
55
+ * The FinalizeHooks-compatible implementation. Dispatches on `fromFile`'s
56
+ * extension → per-language resolver. Returns the first resolved file,
57
+ * or `null` if the resolver returns `null` or doesn't know about the
58
+ * language.
59
+ *
60
+ * Picks the first entry of `files[]` for both `'files'` and `'package'`
61
+ * result kinds — the legacy pipeline uses the whole array, but the
62
+ * shared `finalize()` hook contract is single-file. If the workspace
63
+ * later needs richer semantics (split-target packages), this is the
64
+ * single site to extend.
65
+ */
66
+ export function resolveImportTargetAcrossLanguages(targetRaw, fromFile, workspaceIndex) {
67
+ const workspace = workspaceIndex;
68
+ if (workspace === undefined || workspace.perLanguage === undefined)
69
+ return null;
70
+ const lang = getLanguageFromFilename(fromFile);
71
+ if (lang === null)
72
+ return null;
73
+ const entry = workspace.perLanguage.get(lang);
74
+ if (entry === undefined)
75
+ return null;
76
+ let result;
77
+ try {
78
+ result = entry.resolver(targetRaw, fromFile, entry.ctx);
79
+ }
80
+ catch {
81
+ // Existing resolvers can throw on malformed inputs (e.g., Python
82
+ // relative paths above the workspace root). Swallow — the shared
83
+ // algorithm treats a null here as `linkStatus: 'unresolved'`, which
84
+ // is the right fallback.
85
+ return null;
86
+ }
87
+ if (result === null)
88
+ return null;
89
+ // Both `files` and `package` variants expose a `files` array; the
90
+ // package variant also carries `dirSuffix` which we ignore at the
91
+ // FinalizeHook boundary (single-file contract). Legacy consumers
92
+ // continue to see the full result via `importResolver` directly.
93
+ const first = result.files[0];
94
+ return first ?? null;
95
+ }
@@ -8,7 +8,7 @@
8
8
  * The providers table in `languages/index.ts` uses `satisfies Record<SupportedLanguages, LanguageProvider>`
9
9
  * so adding a language to the enum without creating a provider is a compiler error.
10
10
  */
11
- import type { SupportedLanguages, MroStrategy, Capture, CaptureMatch, BindingRef, TypeRef, Scope, ScopeId, ScopeKind, ScopeTree, ParsedImport, ParsedTypeBinding, SymbolDefinition, Callsite, WorkspaceIndex } from '../../_shared/index.js';
11
+ import type { SupportedLanguages, MroStrategy, CaptureMatch, BindingRef, TypeRef, Scope, ScopeId, ScopeKind, ScopeTree, ParsedImport, ParsedTypeBinding, SymbolDefinition, Callsite, WorkspaceIndex } from '../../_shared/index.js';
12
12
  import type { LanguageTypeConfig } from './type-extractors/types.js';
13
13
  import type { CallRouter } from './call-routing.js';
14
14
  import type { CallExtractor, DispatchDecision, ImplicitReceiverOverride, ReceiverEnriched } from './call-types.js';
@@ -223,19 +223,46 @@ interface LanguageProviderConfig {
223
223
  * Default: undefined (no language-specific filtering). */
224
224
  readonly builtInNames?: ReadonlySet<string>;
225
225
  /**
226
- * Emit scope captures from raw source. Tree-sitter-based providers run a
227
- * `scopes.scm` query; standalone providers (COBOL) emit captures from a
228
- * regex tagger. The return shape is parser-agnostic: the central
229
- * `ScopeExtractor` consumes `Capture[]` without knowing which parser
230
- * produced them.
226
+ * Emit scope captures from raw source, **pre-grouped per tree-sitter
227
+ * query match**. Tree-sitter-based providers run a scope query
228
+ * (embedded as a string constant in each language's `query.ts`) and
229
+ * emit one `CaptureMatch` per query match; standalone providers
230
+ * (COBOL) emit matches from a regex tagger. The return shape is
231
+ * parser-agnostic: the central `ScopeExtractor` consumes
232
+ * `CaptureMatch[]` without knowing which parser produced them.
233
+ *
234
+ * **Pre-grouping is the provider's job.** The extractor expects each
235
+ * `CaptureMatch` to correspond to one logical match — e.g., an import
236
+ * statement match carries `@import.statement` + `@import.source` +
237
+ * `@import.name` keyed under their capture names. Providers MUST
238
+ * preserve the tree-sitter match boundaries so the extractor's topic
239
+ * routing (scope / declaration / import / type-binding / reference)
240
+ * lands on coherent records.
231
241
  *
232
242
  * Required for any provider participating in scope-based resolution.
233
- * Providers that have not yet migrated continue to run through the legacy
234
- * DAG path (feature-flagged per `REGISTRY_PRIMARY_<LANG>`).
243
+ * Providers that have not yet migrated continue to run through the
244
+ * legacy DAG path (feature-flagged per `REGISTRY_PRIMARY_<LANG>`).
245
+ *
246
+ * **Sync return.** Tree-sitter query execution and COBOL's regex
247
+ * tagger are both synchronous; no current or foreseeable provider
248
+ * needs async work inside this hook. The sync signature lets
249
+ * `parse-worker.ts` (#920) invoke it inline in its already-sync
250
+ * per-file loop without cascading `async` through the batch pipeline.
235
251
  *
236
252
  * Default: undefined (language continues to use legacy DAG).
237
253
  */
238
- readonly emitScopeCaptures?: (sourceText: string, filePath: string) => Promise<readonly Capture[]>;
254
+ readonly emitScopeCaptures?: (sourceText: string, filePath: string,
255
+ /**
256
+ * Optional pre-parsed tree-sitter Tree the caller has already
257
+ * produced (e.g. from the parse phase's AST cache). When supplied,
258
+ * the provider SHOULD skip its own `parser.parse(sourceText)` and
259
+ * run its capture query against the supplied tree directly. Typed
260
+ * as `unknown` here to avoid leaking the tree-sitter dependency
261
+ * into the provider contract — the provider casts at use site.
262
+ * Cache miss (parameter omitted or undefined) is always safe and
263
+ * MUST trigger a fresh parse.
264
+ */
265
+ cachedTree?: unknown) => readonly CaptureMatch[];
239
266
  /**
240
267
  * Interpret a raw `@import.statement` capture group into a `ParsedImport`.
241
268
  * The central finalize algorithm resolves `ParsedImport.targetRaw` to a
@@ -273,18 +300,6 @@ interface LanguageProviderConfig {
273
300
  * suffix — `@scope.function` → `'Function'`, etc.).
274
301
  */
275
302
  readonly resolveScopeKind?: (captures: CaptureMatch) => ScopeKind | null;
276
- /**
277
- * Should this scope capture materialize as a real `Scope` node? Return
278
- * `false` to skip scope creation while still emitting declarations that
279
- * would have gone inside (they attach to the enclosing real scope).
280
- *
281
- * Example: Python `if`/`for`/`while` bodies capture as `@scope.block` but
282
- * Python has no block scope — hook returns `false` and child declarations
283
- * lift to the enclosing function/module.
284
- *
285
- * Default: undefined (treated as `true` — always create).
286
- */
287
- readonly shouldCreateScope?: (captures: CaptureMatch) => boolean;
288
303
  /**
289
304
  * Override where a declaration's name becomes visible. By default the name
290
305
  * is bound in the innermost enclosing scope; return a different `ScopeId`
@@ -367,18 +382,6 @@ interface LanguageProviderConfig {
367
382
  * else treats as `'free'`).
368
383
  */
369
384
  readonly classifyCallForm?: (captures: CaptureMatch, enclosingScope: Scope) => 'free' | 'member' | 'constructor' | 'index';
370
- /**
371
- * Does a binding at this scope shadow bindings of the same name in outer
372
- * scopes? Default: any binding shadows (standard lexical scoping). Return
373
- * `false` for transparent-scope edge cases (Python `from x import *`
374
- * contexts, JS `var` hoisting quirks, COBOL PARAGRAPH transparency).
375
- *
376
- * Consulted by `Registry.lookup` Step 1 and by `resolveTypeRef` for
377
- * shadowing decisions during the lexical chain walk.
378
- *
379
- * Default: undefined (treated as `true` — any binding shadows).
380
- */
381
- readonly shouldShadow?: (scope: Scope, bindings: readonly BindingRef[]) => boolean;
382
385
  /**
383
386
  * Is this callable definition compatible with the given call-site arity?
384
387
  * Language-specific rules: Python `*args`/`**kwargs`/defaults, JS default
@@ -0,0 +1,21 @@
1
+ /**
2
+ * C# collection-accessor unwrapping.
3
+ *
4
+ * When the compound-receiver resolver encounters a trailing
5
+ * `.Values` / `.Keys` on a dotted member-access chain, it calls the
6
+ * provider's `unwrapCollectionAccessor` hook to find the element
7
+ * type. This module supplies the C# implementation — recognizing
8
+ * Dictionary-family generics and returning the value or key type.
9
+ *
10
+ * Other languages (Python, Java, TypeScript) use method-call syntax
11
+ * for the same access (`.values()` / `.keys()`), which the compound-
12
+ * receiver's call-expression branch already handles; they leave this
13
+ * hook undefined.
14
+ */
15
+ /**
16
+ * Resolve `data.Values` / `data.Keys` on a Dictionary-like receiver
17
+ * to its element-type simple name. Returns `undefined` for any
18
+ * receiver / accessor combination we don't recognize, letting the
19
+ * compound-receiver pass fall through to the regular field walk.
20
+ */
21
+ export declare function unwrapCsharpCollectionAccessor(receiverType: string, accessor: string): string | undefined;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * C# collection-accessor unwrapping.
3
+ *
4
+ * When the compound-receiver resolver encounters a trailing
5
+ * `.Values` / `.Keys` on a dotted member-access chain, it calls the
6
+ * provider's `unwrapCollectionAccessor` hook to find the element
7
+ * type. This module supplies the C# implementation — recognizing
8
+ * Dictionary-family generics and returning the value or key type.
9
+ *
10
+ * Other languages (Python, Java, TypeScript) use method-call syntax
11
+ * for the same access (`.values()` / `.keys()`), which the compound-
12
+ * receiver's call-expression branch already handles; they leave this
13
+ * hook undefined.
14
+ */
15
+ /** Extract (K, V) from `Dictionary<K, V>` / `IDictionary<K, V>` /
16
+ * `IReadOnlyDictionary<K, V>` / `SortedDictionary<K, V>` /
17
+ * `ConcurrentDictionary<K, V>` / `ImmutableDictionary<K, V>`.
18
+ * Returns undefined if the type name doesn't match or the argument
19
+ * list isn't exactly two top-level args. */
20
+ function extractDictionaryArgs(rawName) {
21
+ const match = rawName.match(/^(?:[A-Za-z_][A-Za-z0-9_.]*\.)?(?:Dictionary|IDictionary|IReadOnlyDictionary|SortedDictionary|ConcurrentDictionary|ImmutableDictionary)<(.+)>$/);
22
+ if (match === null)
23
+ return undefined;
24
+ const inner = match[1];
25
+ // Split on the top-level comma (tolerate nested `<...>`).
26
+ let depth = 0;
27
+ let commaIdx = -1;
28
+ for (let i = 0; i < inner.length; i++) {
29
+ const ch = inner[i];
30
+ if (ch === '<')
31
+ depth++;
32
+ else if (ch === '>')
33
+ depth--;
34
+ else if (ch === ',' && depth === 0) {
35
+ commaIdx = i;
36
+ break;
37
+ }
38
+ }
39
+ if (commaIdx === -1)
40
+ return undefined;
41
+ return { key: inner.slice(0, commaIdx).trim(), value: inner.slice(commaIdx + 1).trim() };
42
+ }
43
+ /**
44
+ * Resolve `data.Values` / `data.Keys` on a Dictionary-like receiver
45
+ * to its element-type simple name. Returns `undefined` for any
46
+ * receiver / accessor combination we don't recognize, letting the
47
+ * compound-receiver pass fall through to the regular field walk.
48
+ */
49
+ export function unwrapCsharpCollectionAccessor(receiverType, accessor) {
50
+ if (accessor !== 'Values' && accessor !== 'Keys')
51
+ return undefined;
52
+ const args = extractDictionaryArgs(receiverType);
53
+ if (args === undefined)
54
+ return undefined;
55
+ return accessor === 'Values' ? args.value : args.key;
56
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Extract C# arity metadata from a method-like tree-sitter node —
3
+ * `method_declaration`, `constructor_declaration`, `destructor_declaration`,
4
+ * `operator_declaration`, `conversion_operator_declaration`, or
5
+ * `local_function_statement`.
6
+ *
7
+ * Reuses `csharpMethodConfig.extractParameters` so scope-extracted defs
8
+ * carry the same arity semantics as the legacy parse-worker path:
9
+ * - `params` variadic collapses `parameterCount` to `undefined`,
10
+ * which `csharpArityCompatibility` then treats as "max unknown" —
11
+ * the candidate stays eligible at `argCount >= required`.
12
+ * - Defaulted parameters (`= expr`) contribute to `optionalCount`;
13
+ * `requiredParameterCount = total − optionalCount`.
14
+ * - `parameterTypes` collects declared type names (with `ref`/`out`/
15
+ * `in` prefix) for overload narrowing; a literal `'params'` marker
16
+ * is appended for variadic methods so `csharpArityCompatibility`
17
+ * can detect them without re-reading the AST.
18
+ */
19
+ import type { SyntaxNode } from '../../utils/ast-helpers.js';
20
+ interface CsharpArityMetadata {
21
+ readonly parameterCount: number | undefined;
22
+ readonly requiredParameterCount: number | undefined;
23
+ readonly parameterTypes: readonly string[] | undefined;
24
+ }
25
+ export declare function computeCsharpArityMetadata(fnNode: SyntaxNode): CsharpArityMetadata;
26
+ export {};
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Extract C# arity metadata from a method-like tree-sitter node —
3
+ * `method_declaration`, `constructor_declaration`, `destructor_declaration`,
4
+ * `operator_declaration`, `conversion_operator_declaration`, or
5
+ * `local_function_statement`.
6
+ *
7
+ * Reuses `csharpMethodConfig.extractParameters` so scope-extracted defs
8
+ * carry the same arity semantics as the legacy parse-worker path:
9
+ * - `params` variadic collapses `parameterCount` to `undefined`,
10
+ * which `csharpArityCompatibility` then treats as "max unknown" —
11
+ * the candidate stays eligible at `argCount >= required`.
12
+ * - Defaulted parameters (`= expr`) contribute to `optionalCount`;
13
+ * `requiredParameterCount = total − optionalCount`.
14
+ * - `parameterTypes` collects declared type names (with `ref`/`out`/
15
+ * `in` prefix) for overload narrowing; a literal `'params'` marker
16
+ * is appended for variadic methods so `csharpArityCompatibility`
17
+ * can detect them without re-reading the AST.
18
+ */
19
+ import { csharpMethodConfig } from '../../method-extractors/configs/csharp.js';
20
+ export function computeCsharpArityMetadata(fnNode) {
21
+ const params = csharpMethodConfig.extractParameters?.(fnNode) ?? [];
22
+ let hasVariadic = false;
23
+ let optionalCount = 0;
24
+ const types = [];
25
+ for (const p of params) {
26
+ if (p.isVariadic)
27
+ hasVariadic = true;
28
+ else if (p.isOptional)
29
+ optionalCount++;
30
+ if (p.type !== null)
31
+ types.push(p.type);
32
+ }
33
+ if (hasVariadic)
34
+ types.push('params');
35
+ const total = params.length;
36
+ // `params int[] args` declares one formal param but accepts any arg
37
+ // count ≥ required — mirror Python's treatment of `*args` and leave
38
+ // `parameterCount` undefined so the registry treats max as unknown.
39
+ const parameterCount = hasVariadic ? undefined : total;
40
+ const requiredParameterCount = hasVariadic ? undefined : total - optionalCount;
41
+ return {
42
+ parameterCount,
43
+ requiredParameterCount,
44
+ parameterTypes: types.length > 0 ? types : undefined,
45
+ };
46
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * C# arity check, accommodating `params` variadic and default parameters.
3
+ *
4
+ * The `def` metadata we care about (synthesized by `arity-metadata.ts`):
5
+ * - `parameterCount` — total formal parameters; `undefined`
6
+ * when the method has `params T[]` variadic.
7
+ * - `requiredParameterCount` — min required (excludes defaulted params
8
+ * and `params` variadic).
9
+ * - `parameterTypes` — declared type strings; contains the
10
+ * literal `'params'` when the method is
11
+ * variadic.
12
+ *
13
+ * Verdicts:
14
+ * - `'compatible'` — `requiredParameterCount <= argCount <= parameterCount`,
15
+ * OR the def takes `params` (then any `argCount >= required`).
16
+ * - `'incompatible'` — argCount is below required, OR above max with no variadic.
17
+ * - `'unknown'` — metadata is absent / incomplete.
18
+ *
19
+ * `'incompatible'` is a soft signal in `Registry.lookup` (penalized but
20
+ * still considered when no compatible candidate exists), per RFC §4.
21
+ */
22
+ import type { Callsite, SymbolDefinition } from '../../../../_shared/index.js';
23
+ export declare function csharpArityCompatibility(def: SymbolDefinition, callsite: Callsite): 'compatible' | 'unknown' | 'incompatible';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * C# arity check, accommodating `params` variadic and default parameters.
3
+ *
4
+ * The `def` metadata we care about (synthesized by `arity-metadata.ts`):
5
+ * - `parameterCount` — total formal parameters; `undefined`
6
+ * when the method has `params T[]` variadic.
7
+ * - `requiredParameterCount` — min required (excludes defaulted params
8
+ * and `params` variadic).
9
+ * - `parameterTypes` — declared type strings; contains the
10
+ * literal `'params'` when the method is
11
+ * variadic.
12
+ *
13
+ * Verdicts:
14
+ * - `'compatible'` — `requiredParameterCount <= argCount <= parameterCount`,
15
+ * OR the def takes `params` (then any `argCount >= required`).
16
+ * - `'incompatible'` — argCount is below required, OR above max with no variadic.
17
+ * - `'unknown'` — metadata is absent / incomplete.
18
+ *
19
+ * `'incompatible'` is a soft signal in `Registry.lookup` (penalized but
20
+ * still considered when no compatible candidate exists), per RFC §4.
21
+ */
22
+ export function csharpArityCompatibility(def, callsite) {
23
+ const max = def.parameterCount;
24
+ const min = def.requiredParameterCount;
25
+ if (max === undefined && min === undefined)
26
+ return 'unknown';
27
+ const argCount = callsite.arity;
28
+ if (!Number.isFinite(argCount) || argCount < 0)
29
+ return 'unknown';
30
+ const hasVarArgs = def.parameterTypes !== undefined &&
31
+ def.parameterTypes.some((t) => t === 'params' || t.startsWith('params '));
32
+ if (min !== undefined && argCount < min)
33
+ return 'incompatible';
34
+ if (max !== undefined && argCount > max && !hasVarArgs)
35
+ return 'incompatible';
36
+ return 'compatible';
37
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Dev-mode counters for the cross-phase scope-captures parse cache
3
+ * (C# mirror of `languages/python/cache-stats.ts`).
4
+ *
5
+ * Gated by `PROF_SCOPE_RESOLUTION=1`. Production builds fold every
6
+ * increment into dead code via the module-level `PROF` constant, so
7
+ * the hot path in `captures.ts` stays branch-free.
8
+ */
9
+ export declare function recordCacheHit(): void;
10
+ export declare function recordCacheMiss(): void;
11
+ export declare function getCsharpCaptureCacheStats(): {
12
+ hits: number;
13
+ misses: number;
14
+ };
15
+ export declare function resetCsharpCaptureCacheStats(): void;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Dev-mode counters for the cross-phase scope-captures parse cache
3
+ * (C# mirror of `languages/python/cache-stats.ts`).
4
+ *
5
+ * Gated by `PROF_SCOPE_RESOLUTION=1`. Production builds fold every
6
+ * increment into dead code via the module-level `PROF` constant, so
7
+ * the hot path in `captures.ts` stays branch-free.
8
+ */
9
+ const PROF = process.env.PROF_SCOPE_RESOLUTION === '1';
10
+ let CACHE_HITS = 0;
11
+ let CACHE_MISSES = 0;
12
+ export function recordCacheHit() {
13
+ if (PROF)
14
+ CACHE_HITS++;
15
+ }
16
+ export function recordCacheMiss() {
17
+ if (PROF)
18
+ CACHE_MISSES++;
19
+ }
20
+ export function getCsharpCaptureCacheStats() {
21
+ return { hits: CACHE_HITS, misses: CACHE_MISSES };
22
+ }
23
+ export function resetCsharpCaptureCacheStats() {
24
+ CACHE_HITS = 0;
25
+ CACHE_MISSES = 0;
26
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `emitScopeCaptures` for C#.
3
+ *
4
+ * Drives the C# scope query against tree-sitter-c-sharp and groups raw
5
+ * matches into `CaptureMatch[]` for the central extractor. Layers one
6
+ * synthesized stream on top today:
7
+ *
8
+ * 1. **Decomposed using directives** — each `using_directive` is
9
+ * re-emitted with `@import.kind/source/name/alias` markers so
10
+ * `interpretCsharpImport` can recover the ParsedImport shape
11
+ * without re-parsing raw text (see `import-decomposer.ts`).
12
+ *
13
+ * Receiver-binding synthesis (`this` / `base` type anchors) and arity
14
+ * metadata synthesis (Unit 5) layer on top later.
15
+ *
16
+ * Pure given the input source text. No I/O, no globals consulted.
17
+ */
18
+ import type { CaptureMatch } from '../../../../_shared/index.js';
19
+ export declare function emitCsharpScopeCaptures(sourceText: string, _filePath: string, cachedTree?: unknown): readonly CaptureMatch[];