gitnexus 1.6.6-rc.98 → 1.6.6

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 (541) hide show
  1. package/README.md +122 -68
  2. package/dist/_shared/graph/types.d.ts +17 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +3 -5
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js +2 -4
  7. package/dist/_shared/index.js.map +1 -1
  8. package/dist/_shared/scope-resolution/module-scope-index.d.ts +1 -2
  9. package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -1
  10. package/dist/_shared/scope-resolution/module-scope-index.js +1 -2
  11. package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -1
  12. package/dist/_shared/scope-resolution/parsed-file.d.ts +24 -0
  13. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
  14. package/dist/_shared/scope-resolution/reference-site.d.ts +13 -1
  15. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  16. package/dist/_shared/scope-resolution/registries/context.d.ts +1 -0
  17. package/dist/_shared/scope-resolution/registries/context.d.ts.map +1 -1
  18. package/dist/_shared/scope-resolution/registries/context.js +6 -0
  19. package/dist/_shared/scope-resolution/registries/context.js.map +1 -1
  20. package/dist/_shared/scope-resolution/registries/evidence.d.ts +2 -3
  21. package/dist/_shared/scope-resolution/registries/evidence.d.ts.map +1 -1
  22. package/dist/_shared/scope-resolution/registries/evidence.js +2 -3
  23. package/dist/_shared/scope-resolution/registries/evidence.js.map +1 -1
  24. package/dist/_shared/scope-resolution/registries/macro-registry.d.ts +29 -0
  25. package/dist/_shared/scope-resolution/registries/macro-registry.d.ts.map +1 -0
  26. package/dist/_shared/scope-resolution/registries/macro-registry.js +32 -0
  27. package/dist/_shared/scope-resolution/registries/macro-registry.js.map +1 -0
  28. package/dist/_shared/scope-resolution/symbol-definition.d.ts +9 -0
  29. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  30. package/dist/_shared/scope-resolution/types.d.ts +1 -1
  31. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  32. package/dist/cli/ai-context.d.ts +35 -1
  33. package/dist/cli/ai-context.js +111 -12
  34. package/dist/cli/analyze-config.d.ts +92 -0
  35. package/dist/cli/analyze-config.js +364 -0
  36. package/dist/cli/analyze.d.ts +17 -1
  37. package/dist/cli/analyze.js +224 -71
  38. package/dist/cli/cli-message.d.ts +1 -1
  39. package/dist/cli/doctor.d.ts +18 -0
  40. package/dist/cli/doctor.js +32 -0
  41. package/dist/cli/i18n/en.d.ts +2 -2
  42. package/dist/cli/i18n/en.js +2 -2
  43. package/dist/cli/i18n/resources.d.ts +2 -2
  44. package/dist/cli/i18n/zh-CN.js +2 -2
  45. package/dist/cli/index.js +4 -2
  46. package/dist/cli/resolve-invocation.d.ts +21 -0
  47. package/dist/cli/resolve-invocation.js +68 -0
  48. package/dist/cli/setup.d.ts +33 -0
  49. package/dist/cli/setup.js +96 -35
  50. package/dist/cli/skill-gen.js +2 -2
  51. package/dist/cli/wiki.js +20 -4
  52. package/dist/core/embeddings/embedder.d.ts +1 -1
  53. package/dist/core/embeddings/embedder.js +14 -1
  54. package/dist/core/embeddings/runtime-support.d.ts +41 -0
  55. package/dist/core/embeddings/runtime-support.js +65 -0
  56. package/dist/core/group/extractors/grpc-patterns/proto.js +2 -1
  57. package/dist/core/group/extractors/http-patterns/java.js +15 -1
  58. package/dist/core/ingestion/call-processor.d.ts +57 -227
  59. package/dist/core/ingestion/call-processor.js +172 -2595
  60. package/dist/core/ingestion/call-routing.d.ts +6 -5
  61. package/dist/core/ingestion/call-routing.js +6 -6
  62. package/dist/core/ingestion/call-types.d.ts +0 -75
  63. package/dist/core/ingestion/class-extractors/configs/c-cpp.js +26 -1
  64. package/dist/core/ingestion/class-extractors/configs/ruby.js +3 -0
  65. package/dist/core/ingestion/class-extractors/generic.js +9 -11
  66. package/dist/core/ingestion/class-types.d.ts +23 -0
  67. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +11 -0
  68. package/dist/core/ingestion/cobol/cobol-preprocessor.js +227 -73
  69. package/dist/core/ingestion/cobol-processor.d.ts +1 -0
  70. package/dist/core/ingestion/cobol-processor.js +51 -2
  71. package/dist/core/ingestion/emit-references.js +8 -2
  72. package/dist/core/ingestion/export-detection.d.ts +2 -1
  73. package/dist/core/ingestion/export-detection.js +2 -6
  74. package/dist/core/ingestion/field-extractors/configs/dart.d.ts +0 -6
  75. package/dist/core/ingestion/field-extractors/configs/dart.js +62 -44
  76. package/dist/core/ingestion/field-extractors/configs/go.d.ts +0 -9
  77. package/dist/core/ingestion/field-extractors/configs/go.js +40 -1
  78. package/dist/core/ingestion/field-extractors/configs/jvm.js +43 -4
  79. package/dist/core/ingestion/field-extractors/configs/php.js +1 -2
  80. package/dist/core/ingestion/field-extractors/configs/swift.d.ts +12 -1
  81. package/dist/core/ingestion/field-extractors/configs/swift.js +31 -6
  82. package/dist/core/ingestion/field-extractors/generic.d.ts +6 -0
  83. package/dist/core/ingestion/field-extractors/generic.js +5 -4
  84. package/dist/core/ingestion/field-extractors/typescript.js +0 -29
  85. package/dist/core/ingestion/filesystem-walker.d.ts +0 -9
  86. package/dist/core/ingestion/filesystem-walker.js +0 -11
  87. package/dist/core/ingestion/finalize-orchestrator.js +14 -2
  88. package/dist/core/ingestion/import-resolvers/configs/swift.d.ts +21 -0
  89. package/dist/core/ingestion/import-resolvers/configs/swift.js +72 -11
  90. package/dist/core/ingestion/import-resolvers/python.d.ts +1 -1
  91. package/dist/core/ingestion/import-resolvers/standard.d.ts +2 -2
  92. package/dist/core/ingestion/import-resolvers/standard.js +6 -5
  93. package/dist/core/ingestion/import-resolvers/utils.d.ts +2 -5
  94. package/dist/core/ingestion/import-resolvers/utils.js +1 -9
  95. package/dist/core/ingestion/language-provider.d.ts +39 -119
  96. package/dist/core/ingestion/language-provider.js +0 -2
  97. package/dist/core/ingestion/languages/c/capture-side-channel.d.ts +62 -0
  98. package/dist/core/ingestion/languages/c/capture-side-channel.js +65 -0
  99. package/dist/core/ingestion/languages/c/captures.js +41 -23
  100. package/dist/core/ingestion/languages/c/import-decomposer.d.ts +9 -0
  101. package/dist/core/ingestion/languages/c/import-decomposer.js +15 -0
  102. package/dist/core/ingestion/languages/c/import-target.js +52 -9
  103. package/dist/core/ingestion/languages/c/index.d.ts +2 -1
  104. package/dist/core/ingestion/languages/c/index.js +2 -1
  105. package/dist/core/ingestion/languages/c/query.js +15 -0
  106. package/dist/core/ingestion/languages/c/scope-resolver.js +47 -4
  107. package/dist/core/ingestion/languages/c/static-linkage.d.ts +8 -0
  108. package/dist/core/ingestion/languages/c/static-linkage.js +46 -1
  109. package/dist/core/ingestion/languages/c-cpp.js +16 -7
  110. package/dist/core/ingestion/languages/cobol/captures.js +25 -2
  111. package/dist/core/ingestion/languages/cpp/adl.d.ts +88 -4
  112. package/dist/core/ingestion/languages/cpp/adl.js +380 -160
  113. package/dist/core/ingestion/languages/cpp/arity-metadata.js +2 -8
  114. package/dist/core/ingestion/languages/cpp/capture-side-channel.d.ts +65 -0
  115. package/dist/core/ingestion/languages/cpp/capture-side-channel.js +78 -0
  116. package/dist/core/ingestion/languages/cpp/captures.js +162 -54
  117. package/dist/core/ingestion/languages/cpp/file-local-linkage.d.ts +18 -52
  118. package/dist/core/ingestion/languages/cpp/file-local-linkage.js +49 -1
  119. package/dist/core/ingestion/languages/cpp/import-decomposer.d.ts +7 -0
  120. package/dist/core/ingestion/languages/cpp/import-decomposer.js +12 -0
  121. package/dist/core/ingestion/languages/cpp/index.d.ts +1 -0
  122. package/dist/core/ingestion/languages/cpp/index.js +1 -0
  123. package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +8 -0
  124. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +21 -0
  125. package/dist/core/ingestion/languages/cpp/query.js +21 -0
  126. package/dist/core/ingestion/languages/cpp/range-bindings.js +20 -5
  127. package/dist/core/ingestion/languages/cpp/scope-resolver.js +52 -5
  128. package/dist/core/ingestion/languages/cpp/two-phase-lookup.d.ts +20 -0
  129. package/dist/core/ingestion/languages/cpp/two-phase-lookup.js +83 -3
  130. package/dist/core/ingestion/languages/csharp/captures.js +205 -41
  131. package/dist/core/ingestion/languages/csharp/index.d.ts +3 -4
  132. package/dist/core/ingestion/languages/csharp/index.js +3 -4
  133. package/dist/core/ingestion/languages/csharp/interpret.js +17 -3
  134. package/dist/core/ingestion/languages/csharp/namespace-siblings.d.ts +17 -7
  135. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +129 -124
  136. package/dist/core/ingestion/languages/csharp/qualified-type-names.d.ts +14 -0
  137. package/dist/core/ingestion/languages/csharp/qualified-type-names.js +59 -0
  138. package/dist/core/ingestion/languages/csharp/query.js +13 -0
  139. package/dist/core/ingestion/languages/csharp/receiver-binding.js +10 -6
  140. package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -1
  141. package/dist/core/ingestion/languages/csharp.js +0 -5
  142. package/dist/core/ingestion/languages/dart/arity-metadata.d.ts +25 -0
  143. package/dist/core/ingestion/languages/dart/arity-metadata.js +35 -0
  144. package/dist/core/ingestion/languages/dart/arity.d.ts +19 -0
  145. package/dist/core/ingestion/languages/dart/arity.js +31 -0
  146. package/dist/core/ingestion/languages/dart/built-ins.d.ts +11 -0
  147. package/dist/core/ingestion/languages/dart/built-ins.js +34 -0
  148. package/dist/core/ingestion/languages/dart/cache-stats.d.ts +13 -0
  149. package/dist/core/ingestion/languages/dart/cache-stats.js +24 -0
  150. package/dist/core/ingestion/languages/dart/captures.d.ts +29 -0
  151. package/dist/core/ingestion/languages/dart/captures.js +445 -0
  152. package/dist/core/ingestion/languages/dart/expand-wildcards.d.ts +13 -0
  153. package/dist/core/ingestion/languages/dart/expand-wildcards.js +31 -0
  154. package/dist/core/ingestion/languages/dart/import-target.d.ts +15 -0
  155. package/dist/core/ingestion/languages/dart/import-target.js +65 -0
  156. package/dist/core/ingestion/languages/dart/index.d.ts +28 -0
  157. package/dist/core/ingestion/languages/dart/index.js +28 -0
  158. package/dist/core/ingestion/languages/dart/interpret.d.ts +24 -0
  159. package/dist/core/ingestion/languages/dart/interpret.js +95 -0
  160. package/dist/core/ingestion/languages/dart/merge-bindings.d.ts +10 -0
  161. package/dist/core/ingestion/languages/dart/merge-bindings.js +39 -0
  162. package/dist/core/ingestion/languages/dart/query.d.ts +26 -0
  163. package/dist/core/ingestion/languages/dart/query.js +142 -0
  164. package/dist/core/ingestion/languages/dart/receiver-binding.d.ts +24 -0
  165. package/dist/core/ingestion/languages/dart/receiver-binding.js +87 -0
  166. package/dist/core/ingestion/languages/dart/scope-resolver.d.ts +29 -0
  167. package/dist/core/ingestion/languages/dart/scope-resolver.js +194 -0
  168. package/dist/core/ingestion/languages/dart/signature-bindings.d.ts +23 -0
  169. package/dist/core/ingestion/languages/dart/signature-bindings.js +51 -0
  170. package/dist/core/ingestion/languages/dart/simple-hooks.d.ts +20 -0
  171. package/dist/core/ingestion/languages/dart/simple-hooks.js +47 -0
  172. package/dist/core/ingestion/languages/dart.d.ts +0 -1
  173. package/dist/core/ingestion/languages/dart.js +15 -29
  174. package/dist/core/ingestion/languages/go/arity-metadata.d.ts +1 -0
  175. package/dist/core/ingestion/languages/go/arity-metadata.js +31 -1
  176. package/dist/core/ingestion/languages/go/captures.js +247 -26
  177. package/dist/core/ingestion/languages/go/interface-impls.js +476 -50
  178. package/dist/core/ingestion/languages/go/interpret.js +21 -11
  179. package/dist/core/ingestion/languages/go/method-owners.js +20 -8
  180. package/dist/core/ingestion/languages/go/query.js +15 -7
  181. package/dist/core/ingestion/languages/go/range-binding.js +24 -9
  182. package/dist/core/ingestion/languages/go/receiver-binding.js +1 -1
  183. package/dist/core/ingestion/languages/go/scope-resolver.js +2 -2
  184. package/dist/core/ingestion/languages/go/simple-hooks.js +10 -5
  185. package/dist/core/ingestion/languages/go/type-binding.d.ts +1 -0
  186. package/dist/core/ingestion/languages/go/type-binding.js +40 -2
  187. package/dist/core/ingestion/languages/go.d.ts +0 -1
  188. package/dist/core/ingestion/languages/go.js +0 -5
  189. package/dist/core/ingestion/languages/index.d.ts +0 -5
  190. package/dist/core/ingestion/languages/index.js +0 -3
  191. package/dist/core/ingestion/languages/java/captures.js +252 -23
  192. package/dist/core/ingestion/languages/java/interpret.js +12 -6
  193. package/dist/core/ingestion/languages/java/package-siblings.js +18 -5
  194. package/dist/core/ingestion/languages/java/query.js +16 -1
  195. package/dist/core/ingestion/languages/java/scope-resolver.d.ts +2 -8
  196. package/dist/core/ingestion/languages/java/scope-resolver.js +2 -8
  197. package/dist/core/ingestion/languages/java.js +0 -5
  198. package/dist/core/ingestion/languages/javascript/captures.js +185 -11
  199. package/dist/core/ingestion/languages/javascript/query.js +107 -1
  200. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +57 -0
  201. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +60 -0
  202. package/dist/core/ingestion/languages/kotlin/captures.js +213 -22
  203. package/dist/core/ingestion/languages/kotlin/companion-scopes.d.ts +7 -0
  204. package/dist/core/ingestion/languages/kotlin/companion-scopes.js +10 -0
  205. package/dist/core/ingestion/languages/kotlin/index.d.ts +1 -0
  206. package/dist/core/ingestion/languages/kotlin/index.js +1 -0
  207. package/dist/core/ingestion/languages/kotlin/query.js +30 -0
  208. package/dist/core/ingestion/languages/kotlin/scope-resolver.d.ts +5 -7
  209. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +22 -7
  210. package/dist/core/ingestion/languages/kotlin.js +8 -5
  211. package/dist/core/ingestion/languages/php/captures.js +135 -19
  212. package/dist/core/ingestion/languages/php/import-decomposer.js +21 -63
  213. package/dist/core/ingestion/languages/php/index.d.ts +3 -4
  214. package/dist/core/ingestion/languages/php/index.js +3 -4
  215. package/dist/core/ingestion/languages/php/query.js +5 -0
  216. package/dist/core/ingestion/languages/php/receiver-binding.js +8 -4
  217. package/dist/core/ingestion/languages/php.js +0 -4
  218. package/dist/core/ingestion/languages/python/captures.js +128 -13
  219. package/dist/core/ingestion/languages/python/depends-references.js +1 -1
  220. package/dist/core/ingestion/languages/python/import-target.d.ts +4 -5
  221. package/dist/core/ingestion/languages/python/import-target.js +108 -16
  222. package/dist/core/ingestion/languages/python/index-stats.d.ts +18 -0
  223. package/dist/core/ingestion/languages/python/index-stats.js +25 -0
  224. package/dist/core/ingestion/languages/python/index.d.ts +3 -4
  225. package/dist/core/ingestion/languages/python/index.js +3 -4
  226. package/dist/core/ingestion/languages/python/query.js +17 -0
  227. package/dist/core/ingestion/languages/python/scope-resolver.js +7 -6
  228. package/dist/core/ingestion/languages/python.d.ts +0 -2
  229. package/dist/core/ingestion/languages/python.js +0 -7
  230. package/dist/core/ingestion/languages/ruby/captures.js +174 -31
  231. package/dist/core/ingestion/languages/ruby/import-target.js +2 -1
  232. package/dist/core/ingestion/languages/ruby/interpret.js +2 -1
  233. package/dist/core/ingestion/languages/ruby/query.js +10 -0
  234. package/dist/core/ingestion/languages/ruby/scope-resolver.js +61 -11
  235. package/dist/core/ingestion/languages/ruby.js +4 -53
  236. package/dist/core/ingestion/languages/rust/captures.js +95 -13
  237. package/dist/core/ingestion/languages/rust/query.js +64 -1
  238. package/dist/core/ingestion/languages/rust/range-binding.js +40 -12
  239. package/dist/core/ingestion/languages/rust/receiver-binding.js +9 -0
  240. package/dist/core/ingestion/languages/rust/scope-resolver.js +75 -1
  241. package/dist/core/ingestion/languages/rust.d.ts +0 -2
  242. package/dist/core/ingestion/languages/rust.js +0 -6
  243. package/dist/core/ingestion/languages/swift/arity-metadata.d.ts +24 -0
  244. package/dist/core/ingestion/languages/swift/arity-metadata.js +41 -0
  245. package/dist/core/ingestion/languages/swift/arity.d.ts +29 -0
  246. package/dist/core/ingestion/languages/swift/arity.js +42 -0
  247. package/dist/core/ingestion/languages/swift/base-type.d.ts +20 -0
  248. package/dist/core/ingestion/languages/swift/base-type.js +27 -0
  249. package/dist/core/ingestion/languages/swift/cache-stats.d.ts +15 -0
  250. package/dist/core/ingestion/languages/swift/cache-stats.js +26 -0
  251. package/dist/core/ingestion/languages/swift/captures.d.ts +35 -0
  252. package/dist/core/ingestion/languages/swift/captures.js +495 -0
  253. package/dist/core/ingestion/languages/swift/implicit-imports.d.ts +34 -0
  254. package/dist/core/ingestion/languages/swift/implicit-imports.js +57 -0
  255. package/dist/core/ingestion/languages/swift/import-decomposer.d.ts +24 -0
  256. package/dist/core/ingestion/languages/swift/import-decomposer.js +84 -0
  257. package/dist/core/ingestion/languages/swift/import-target.d.ts +33 -0
  258. package/dist/core/ingestion/languages/swift/import-target.js +81 -0
  259. package/dist/core/ingestion/languages/swift/index.d.ts +37 -0
  260. package/dist/core/ingestion/languages/swift/index.js +37 -0
  261. package/dist/core/ingestion/languages/swift/interpret.d.ts +15 -0
  262. package/dist/core/ingestion/languages/swift/interpret.js +89 -0
  263. package/dist/core/ingestion/languages/swift/merge-bindings.d.ts +20 -0
  264. package/dist/core/ingestion/languages/swift/merge-bindings.js +48 -0
  265. package/dist/core/ingestion/languages/swift/query.d.ts +46 -0
  266. package/dist/core/ingestion/languages/swift/query.js +194 -0
  267. package/dist/core/ingestion/languages/swift/receiver-binding.d.ts +40 -0
  268. package/dist/core/ingestion/languages/swift/receiver-binding.js +161 -0
  269. package/dist/core/ingestion/languages/swift/scope-resolver.d.ts +50 -0
  270. package/dist/core/ingestion/languages/swift/scope-resolver.js +189 -0
  271. package/dist/core/ingestion/languages/swift/sibling-type-bindings.d.ts +34 -0
  272. package/dist/core/ingestion/languages/swift/sibling-type-bindings.js +65 -0
  273. package/dist/core/ingestion/languages/swift/signature-bindings.d.ts +25 -0
  274. package/dist/core/ingestion/languages/swift/signature-bindings.js +66 -0
  275. package/dist/core/ingestion/languages/swift/simple-hooks.d.ts +37 -0
  276. package/dist/core/ingestion/languages/swift/simple-hooks.js +60 -0
  277. package/dist/core/ingestion/languages/swift/target-grouping.d.ts +51 -0
  278. package/dist/core/ingestion/languages/swift/target-grouping.js +93 -0
  279. package/dist/core/ingestion/languages/swift/target-siblings.d.ts +30 -0
  280. package/dist/core/ingestion/languages/swift/target-siblings.js +71 -0
  281. package/dist/core/ingestion/languages/swift.d.ts +0 -5
  282. package/dist/core/ingestion/languages/swift.js +11 -87
  283. package/dist/core/ingestion/languages/typescript/array-callback.d.ts +3 -29
  284. package/dist/core/ingestion/languages/typescript/array-callback.js +4 -43
  285. package/dist/core/ingestion/languages/typescript/captures.js +147 -17
  286. package/dist/core/ingestion/languages/typescript/index.d.ts +3 -4
  287. package/dist/core/ingestion/languages/typescript/index.js +3 -4
  288. package/dist/core/ingestion/languages/typescript/query.d.ts +2 -3
  289. package/dist/core/ingestion/languages/typescript/query.js +125 -4
  290. package/dist/core/ingestion/languages/typescript/receiver-binding.js +0 -1
  291. package/dist/core/ingestion/languages/typescript.d.ts +2 -3
  292. package/dist/core/ingestion/languages/typescript.js +46 -23
  293. package/dist/core/ingestion/languages/vue/captures.d.ts +46 -0
  294. package/dist/core/ingestion/languages/vue/captures.js +67 -0
  295. package/dist/core/ingestion/languages/vue/import-target.d.ts +27 -0
  296. package/dist/core/ingestion/languages/vue/import-target.js +58 -0
  297. package/dist/core/ingestion/languages/vue/index.d.ts +49 -0
  298. package/dist/core/ingestion/languages/vue/index.js +49 -0
  299. package/dist/core/ingestion/languages/vue/scope-resolver.d.ts +55 -0
  300. package/dist/core/ingestion/languages/vue/scope-resolver.js +292 -0
  301. package/dist/core/ingestion/languages/vue.js +12 -4
  302. package/dist/core/ingestion/local-symbol-pruner.d.ts +11 -0
  303. package/dist/core/ingestion/local-symbol-pruner.js +63 -0
  304. package/dist/core/ingestion/method-extractors/configs/dart.js +14 -1
  305. package/dist/core/ingestion/method-extractors/configs/jvm.js +37 -20
  306. package/dist/core/ingestion/method-extractors/configs/php.js +0 -1
  307. package/dist/core/ingestion/method-extractors/configs/swift.js +11 -4
  308. package/dist/core/ingestion/method-types.d.ts +2 -2
  309. package/dist/core/ingestion/model/index.d.ts +0 -3
  310. package/dist/core/ingestion/model/index.js +0 -8
  311. package/dist/core/ingestion/model/resolve.d.ts +7 -43
  312. package/dist/core/ingestion/model/resolve.js +7 -226
  313. package/dist/core/ingestion/model/scope-resolution-indexes.d.ts +46 -1
  314. package/dist/core/ingestion/model/semantic-model.d.ts +4 -6
  315. package/dist/core/ingestion/model/semantic-model.js +1 -1
  316. package/dist/core/ingestion/model/symbol-table.d.ts +3 -4
  317. package/dist/core/ingestion/model/symbol-table.js +3 -4
  318. package/dist/core/ingestion/parsing-processor.d.ts +30 -24
  319. package/dist/core/ingestion/parsing-processor.js +76 -640
  320. package/dist/core/ingestion/pipeline-phases/communities.d.ts +1 -1
  321. package/dist/core/ingestion/pipeline-phases/communities.js +5 -2
  322. package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +9 -8
  323. package/dist/core/ingestion/pipeline-phases/cross-file.js +16 -12
  324. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  325. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  326. package/dist/core/ingestion/pipeline-phases/mro.d.ts +1 -1
  327. package/dist/core/ingestion/pipeline-phases/mro.js +2 -2
  328. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +44 -22
  329. package/dist/core/ingestion/pipeline-phases/parse-impl.js +426 -565
  330. package/dist/core/ingestion/pipeline-phases/parse.d.ts +13 -33
  331. package/dist/core/ingestion/pipeline-phases/parse.js +2 -2
  332. package/dist/core/ingestion/pipeline-phases/processes.d.ts +1 -1
  333. package/dist/core/ingestion/pipeline-phases/processes.js +5 -3
  334. package/dist/core/ingestion/pipeline-phases/prune-local-symbols.d.ts +14 -0
  335. package/dist/core/ingestion/pipeline-phases/prune-local-symbols.js +26 -0
  336. package/dist/core/ingestion/pipeline.d.ts +27 -19
  337. package/dist/core/ingestion/pipeline.js +4 -2
  338. package/dist/core/ingestion/resolve-references.js +15 -3
  339. package/dist/core/ingestion/route-extractors/laravel.d.ts +10 -0
  340. package/dist/core/ingestion/route-extractors/laravel.js +88 -9
  341. package/dist/core/ingestion/scope-extractor-bridge.d.ts +2 -1
  342. package/dist/core/ingestion/scope-extractor-bridge.js +2 -2
  343. package/dist/core/ingestion/scope-extractor.js +13 -0
  344. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +181 -15
  345. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +21 -10
  346. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +10 -2
  347. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +7 -1
  348. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +58 -6
  349. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +24 -5
  350. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +68 -1
  351. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +189 -29
  352. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +21 -1
  353. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1 -1
  354. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +8 -11
  355. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +171 -50
  356. package/dist/core/ingestion/scope-resolution/pipeline/registry.d.ts +3 -4
  357. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +9 -4
  358. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +28 -5
  359. package/dist/core/ingestion/scope-resolution/pipeline/run.js +191 -24
  360. package/dist/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +31 -0
  361. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +72 -0
  362. package/dist/core/ingestion/scope-resolution/scope/walkers.js +440 -39
  363. package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +18 -2
  364. package/dist/core/ingestion/scope-resolution/workspace-index.js +94 -7
  365. package/dist/core/ingestion/tree-sitter-queries.d.ts +14 -14
  366. package/dist/core/ingestion/tree-sitter-queries.js +380 -158
  367. package/dist/core/ingestion/ts-js-hoc-utils.d.ts +12 -0
  368. package/dist/core/ingestion/ts-js-hoc-utils.js +105 -0
  369. package/dist/core/ingestion/type-env.d.ts +2 -1
  370. package/dist/core/ingestion/type-env.js +6 -8
  371. package/dist/core/ingestion/type-extractors/c-cpp.js +8 -10
  372. package/dist/core/ingestion/type-extractors/csharp.js +18 -34
  373. package/dist/core/ingestion/type-extractors/go.js +2 -10
  374. package/dist/core/ingestion/type-extractors/jvm.js +6 -5
  375. package/dist/core/ingestion/type-extractors/php.js +1 -1
  376. package/dist/core/ingestion/type-extractors/python.js +1 -1
  377. package/dist/core/ingestion/type-extractors/ruby.js +2 -2
  378. package/dist/core/ingestion/type-extractors/rust.js +0 -16
  379. package/dist/core/ingestion/type-extractors/shared.d.ts +2 -2
  380. package/dist/core/ingestion/type-extractors/shared.js +25 -11
  381. package/dist/core/ingestion/type-extractors/swift.js +5 -5
  382. package/dist/core/ingestion/type-extractors/types.d.ts +1 -1
  383. package/dist/core/ingestion/type-extractors/typescript.js +1 -1
  384. package/dist/core/ingestion/utils/ast-helpers.d.ts +119 -1
  385. package/dist/core/ingestion/utils/ast-helpers.js +260 -13
  386. package/dist/core/ingestion/utils/callable-labels.d.ts +13 -0
  387. package/dist/core/ingestion/utils/callable-labels.js +14 -0
  388. package/dist/core/ingestion/utils/deferred-resolution-profile.d.ts +10 -0
  389. package/dist/core/ingestion/utils/deferred-resolution-profile.js +30 -0
  390. package/dist/core/ingestion/utils/heap-probe.d.ts +20 -0
  391. package/dist/core/ingestion/utils/heap-probe.js +39 -0
  392. package/dist/core/ingestion/utils/heritage-marker.d.ts +33 -0
  393. package/dist/core/ingestion/utils/heritage-marker.js +41 -0
  394. package/dist/core/ingestion/utils/qualified-name.d.ts +37 -0
  395. package/dist/core/ingestion/utils/qualified-name.js +67 -0
  396. package/dist/core/ingestion/variable-extractors/configs/c-cpp.js +49 -0
  397. package/dist/core/ingestion/variable-extractors/configs/dart.js +76 -62
  398. package/dist/core/ingestion/variable-extractors/configs/go.js +74 -7
  399. package/dist/core/ingestion/variable-extractors/configs/jvm.js +35 -8
  400. package/dist/core/ingestion/variable-extractors/generic.js +40 -12
  401. package/dist/core/ingestion/variable-types.d.ts +9 -0
  402. package/dist/core/ingestion/vue-sfc-extractor.d.ts +97 -7
  403. package/dist/core/ingestion/vue-sfc-extractor.js +433 -11
  404. package/dist/core/ingestion/workers/parse-worker.d.ts +0 -11
  405. package/dist/core/ingestion/workers/parse-worker.js +358 -187
  406. package/dist/core/ingestion/workers/worker-pool.d.ts +78 -9
  407. package/dist/core/ingestion/workers/worker-pool.js +346 -49
  408. package/dist/core/lbug/csv-generator.js +20 -2
  409. package/dist/core/lbug/lbug-adapter.js +29 -10
  410. package/dist/core/lbug/native-check.js +17 -5
  411. package/dist/core/lbug/pool-adapter.d.ts +0 -19
  412. package/dist/core/lbug/pool-adapter.js +40 -77
  413. package/dist/core/lbug/query-result-utils.d.ts +19 -0
  414. package/dist/core/lbug/query-result-utils.js +28 -0
  415. package/dist/core/run-analyze.d.ts +9 -2
  416. package/dist/core/run-analyze.js +24 -3
  417. package/dist/core/tree-sitter/parser-loader.d.ts +13 -0
  418. package/dist/core/tree-sitter/parser-loader.js +4 -0
  419. package/dist/core/tree-sitter/safe-parse.d.ts +70 -3
  420. package/dist/core/tree-sitter/safe-parse.js +214 -11
  421. package/dist/core/wiki/generator.js +13 -5
  422. package/dist/core/wiki/graph-queries.d.ts +3 -0
  423. package/dist/core/wiki/graph-queries.js +9 -1
  424. package/dist/core/wiki/llm-client.d.ts +1 -1
  425. package/dist/core/wiki/llm-client.js +7 -2
  426. package/dist/core/wiki/local-cli-client.d.ts +2 -1
  427. package/dist/core/wiki/local-cli-client.js +62 -4
  428. package/dist/mcp/compatible-stdio-transport.d.ts +3 -0
  429. package/dist/mcp/compatible-stdio-transport.js +22 -0
  430. package/dist/mcp/core/embedder.d.ts +1 -1
  431. package/dist/mcp/core/embedder.js +13 -1
  432. package/dist/mcp/local/local-backend.d.ts +37 -5
  433. package/dist/mcp/local/local-backend.js +227 -129
  434. package/dist/mcp/resources.js +3 -3
  435. package/dist/mcp/server.js +9 -1
  436. package/dist/storage/git.d.ts +11 -0
  437. package/dist/storage/git.js +30 -0
  438. package/dist/storage/parse-cache.d.ts +23 -1
  439. package/dist/storage/parse-cache.js +138 -32
  440. package/dist/storage/parsedfile-store.d.ts +142 -0
  441. package/dist/storage/parsedfile-store.js +367 -0
  442. package/dist/storage/repo-manager.d.ts +2 -1
  443. package/dist/storage/scope-index-store.d.ts +114 -0
  444. package/dist/storage/scope-index-store.js +236 -0
  445. package/dist/types/pipeline.d.ts +6 -3
  446. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +2 -1
  447. package/hooks/claude/gitnexus-hook.cjs +2 -1
  448. package/hooks/claude/resolve-analyze-cmd.cjs +323 -0
  449. package/package.json +4 -5
  450. package/scripts/bench-scope-resolution.ts +1 -3
  451. package/scripts/cross-platform-tests.ts +4 -1
  452. package/skills/gitnexus-cli.md +8 -6
  453. package/skills/gitnexus-debugging.md +15 -15
  454. package/skills/gitnexus-exploring.md +11 -11
  455. package/skills/gitnexus-guide.md +1 -1
  456. package/skills/gitnexus-impact-analysis.md +10 -10
  457. package/skills/gitnexus-pr-review.md +19 -19
  458. package/skills/gitnexus-refactoring.md +25 -25
  459. package/web/assets/{agent-BRX-afm3.js → agent-EkX7webX.js} +156 -131
  460. package/web/assets/{architectureDiagram-UL44E2DR-B1oYB8-c.js → architectureDiagram-UL44E2DR-BoczH8cv.js} +1 -1
  461. package/web/assets/{chunk-LCXTWHL2-SPC6pgWI.js → chunk-LCXTWHL2-By5HB3b-.js} +1 -1
  462. package/web/assets/{chunk-RG4AUYOV-DZXr4Yv3.js → chunk-RG4AUYOV-BQE_DkpL.js} +1 -1
  463. package/web/assets/{classDiagram-KGZ6W3CR-BqpOj8L9.js → classDiagram-KGZ6W3CR-Dj_02GUH.js} +1 -1
  464. package/web/assets/{classDiagram-v2-72OJOZXJ-FmElywK2.js → classDiagram-v2-72OJOZXJ-D-NArMpf.js} +1 -1
  465. package/web/assets/{diagram-3NCE3AQN-BWtJXMDq.js → diagram-3NCE3AQN-VXtXDO95.js} +1 -1
  466. package/web/assets/{diagram-GF46GFSD-Hh-fChxU.js → diagram-GF46GFSD-B1qab2Ah.js} +1 -1
  467. package/web/assets/{diagram-QXG6HAR7-DYeQHxGU.js → diagram-QXG6HAR7-BSCHGzzT.js} +1 -1
  468. package/web/assets/{diagram-WEQXMOUZ-DYGU4T0y.js → diagram-WEQXMOUZ-DHtknmNT.js} +1 -1
  469. package/web/assets/{erDiagram-L5TCEMPS-bN3wlP2A.js → erDiagram-L5TCEMPS-Db-IYTmm.js} +1 -1
  470. package/web/assets/{flowDiagram-H6V6AXG4-YACVtF3-.js → flowDiagram-H6V6AXG4-BHDoyVoW.js} +1 -1
  471. package/web/assets/{index-BhnAdWTt.js → index-BR0IhgbR.js} +10 -10
  472. package/web/assets/{infoDiagram-3YFTVSEB-BWBzD28-.js → infoDiagram-3YFTVSEB-6h8wbWEe.js} +1 -1
  473. package/web/assets/{ishikawaDiagram-BNXS4ZKH-B8qYT-j9.js → ishikawaDiagram-BNXS4ZKH-Dx2OkPk1.js} +1 -1
  474. package/web/assets/{kanban-definition-75IXJCU3-BeoPr5Tl.js → kanban-definition-75IXJCU3-CIIEZfqV.js} +1 -1
  475. package/web/assets/{mindmap-definition-2TDM6QVE-CdLLN_so.js → mindmap-definition-2TDM6QVE-DUAqydRq.js} +1 -1
  476. package/web/assets/{pieDiagram-CU6KROY3-DEd2a_k_.js → pieDiagram-CU6KROY3-BntYuYZa.js} +1 -1
  477. package/web/assets/{requirementDiagram-JXO7QTGE-QNeTo5C_.js → requirementDiagram-JXO7QTGE-QCD6I29n.js} +1 -1
  478. package/web/assets/{sequenceDiagram-VS2MUI6T-BHC7q7yJ.js → sequenceDiagram-VS2MUI6T-DScFwLz2.js} +1 -1
  479. package/web/assets/{stateDiagram-7D4R322I-KONnc2Px.js → stateDiagram-7D4R322I-AkRAm6Hl.js} +1 -1
  480. package/web/assets/{stateDiagram-v2-36443NZ5-C2QfuMlu.js → stateDiagram-v2-36443NZ5-BCK1vigR.js} +1 -1
  481. package/web/assets/{timeline-definition-O6YCAMPW-D4t4NJx1.js → timeline-definition-O6YCAMPW-BvpIVXjX.js} +1 -1
  482. package/web/assets/{vennDiagram-MWXL3ELB-6bctC9Yg.js → vennDiagram-MWXL3ELB-BYGWk6dK.js} +1 -1
  483. package/web/assets/{wardleyDiagram-CUQ6CDDI-BPZYNTvC.js → wardleyDiagram-CUQ6CDDI-Dk1z7H2T.js} +1 -1
  484. package/web/assets/{xychartDiagram-N2JHSOCM-lBI9O6DW.js → xychartDiagram-N2JHSOCM-2N6NCSWN.js} +1 -1
  485. package/web/index.html +1 -1
  486. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +0 -63
  487. package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +0 -1
  488. package/dist/_shared/scope-resolution/shadow/aggregate.js +0 -122
  489. package/dist/_shared/scope-resolution/shadow/aggregate.js.map +0 -1
  490. package/dist/_shared/scope-resolution/shadow/diff.d.ts +0 -59
  491. package/dist/_shared/scope-resolution/shadow/diff.d.ts.map +0 -1
  492. package/dist/_shared/scope-resolution/shadow/diff.js +0 -79
  493. package/dist/_shared/scope-resolution/shadow/diff.js.map +0 -1
  494. package/dist/core/ingestion/ast-cache.d.ts +0 -26
  495. package/dist/core/ingestion/ast-cache.js +0 -48
  496. package/dist/core/ingestion/heritage-extractors/configs/go.d.ts +0 -13
  497. package/dist/core/ingestion/heritage-extractors/configs/go.js +0 -20
  498. package/dist/core/ingestion/heritage-extractors/configs/ruby.d.ts +0 -18
  499. package/dist/core/ingestion/heritage-extractors/configs/ruby.js +0 -65
  500. package/dist/core/ingestion/heritage-extractors/generic.d.ts +0 -23
  501. package/dist/core/ingestion/heritage-extractors/generic.js +0 -47
  502. package/dist/core/ingestion/heritage-processor.d.ts +0 -54
  503. package/dist/core/ingestion/heritage-processor.js +0 -367
  504. package/dist/core/ingestion/heritage-types.d.ts +0 -73
  505. package/dist/core/ingestion/heritage-types.js +0 -2
  506. package/dist/core/ingestion/import-processor.d.ts +0 -23
  507. package/dist/core/ingestion/import-processor.js +0 -377
  508. package/dist/core/ingestion/model/heritage-map.d.ts +0 -105
  509. package/dist/core/ingestion/model/heritage-map.js +0 -294
  510. package/dist/core/ingestion/model/resolution-context.d.ts +0 -93
  511. package/dist/core/ingestion/model/resolution-context.js +0 -337
  512. package/dist/core/ingestion/named-bindings/csharp.d.ts +0 -3
  513. package/dist/core/ingestion/named-bindings/csharp.js +0 -37
  514. package/dist/core/ingestion/named-bindings/java.d.ts +0 -3
  515. package/dist/core/ingestion/named-bindings/java.js +0 -29
  516. package/dist/core/ingestion/named-bindings/kotlin.d.ts +0 -3
  517. package/dist/core/ingestion/named-bindings/kotlin.js +0 -36
  518. package/dist/core/ingestion/named-bindings/php.d.ts +0 -3
  519. package/dist/core/ingestion/named-bindings/php.js +0 -61
  520. package/dist/core/ingestion/named-bindings/python.d.ts +0 -3
  521. package/dist/core/ingestion/named-bindings/python.js +0 -49
  522. package/dist/core/ingestion/named-bindings/rust.d.ts +0 -3
  523. package/dist/core/ingestion/named-bindings/rust.js +0 -66
  524. package/dist/core/ingestion/named-bindings/types.d.ts +0 -16
  525. package/dist/core/ingestion/named-bindings/types.js +0 -6
  526. package/dist/core/ingestion/named-bindings/typescript.d.ts +0 -3
  527. package/dist/core/ingestion/named-bindings/typescript.js +0 -58
  528. package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +0 -17
  529. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +0 -209
  530. package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +0 -22
  531. package/dist/core/ingestion/pipeline-phases/orm-extraction.js +0 -92
  532. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +0 -70
  533. package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +0 -312
  534. package/dist/core/ingestion/registry-primary-flag.d.ts +0 -89
  535. package/dist/core/ingestion/registry-primary-flag.js +0 -122
  536. package/dist/core/ingestion/shadow-harness.d.ts +0 -113
  537. package/dist/core/ingestion/shadow-harness.js +0 -148
  538. package/dist/core/ingestion/utils/ruby-self-call.d.ts +0 -52
  539. package/dist/core/ingestion/utils/ruby-self-call.js +0 -59
  540. package/scripts/ci-list-migrated-languages.ts +0 -24
  541. package/scripts/run-parity.ts +0 -128
@@ -1,9 +1,11 @@
1
- import { findNodeAtRange, nodeToCapture, syntheticCapture, } from '../../utils/ast-helpers.js';
1
+ import { findChild, nodeIfType, nodeToCapture, syntheticCapture, walkNamedTree, } from '../../utils/ast-helpers.js';
2
2
  import { getRubyParser, getRubyScopeQuery } from './query.js';
3
3
  import { recordRubyCacheHit, recordRubyCacheMiss } from './cache-stats.js';
4
4
  import { synthesizeRubyReceiverBinding, findEnclosingClassOrModule } from './receiver-binding.js';
5
5
  import { getTreeSitterBufferSize } from '../../constants.js';
6
6
  import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
7
+ import { splitQualifiedName } from '../../utils/qualified-name.js';
8
+ import { encodeMarker } from '../../utils/heritage-marker.js';
7
9
  const FUNCTION_NODE_TYPES = ['method', 'singleton_method'];
8
10
  const HERITAGE_CALL_NAMES = new Set(['include', 'extend', 'prepend']);
9
11
  const ATTR_CALL_NAMES = new Set([
@@ -11,6 +13,35 @@ const ATTR_CALL_NAMES = new Set([
11
13
  'attr_reader',
12
14
  'attr_writer',
13
15
  ]);
16
+ /**
17
+ * Build the full `.`-joined qualified owner name for a heritage/attr call by
18
+ * walking ALL enclosing class/module ancestors (not just the immediate one),
19
+ * so a same-tail nested owner (`module Outer; class Inner`) is keyed by its
20
+ * full path `Outer.Inner` instead of the bare tail `Inner` — which otherwise
21
+ * collapses both same-tail owners onto one `__heritage__`/`__property__` marker
22
+ * key (last-wins) and cross-wires their mixin / attr_accessor edges (#1982).
23
+ * Handles the compact `class Outer::Inner` form (name is a `scope_resolution`)
24
+ * via the shared normalizer, so the marker owner byte-matches the resolution
25
+ * def's `qualifiedName`. Returns undefined when there is no enclosing class/module.
26
+ */
27
+ function buildEnclosingQualifiedName(callNode) {
28
+ const segments = [];
29
+ let current = callNode.parent;
30
+ while (current !== null) {
31
+ if (current.type === 'class' || current.type === 'module') {
32
+ const nameNode = current.childForFieldName('name');
33
+ if (nameNode !== null)
34
+ segments.unshift(...splitQualifiedName(nameNode.text));
35
+ }
36
+ // Stop at the file root — nothing above `program` contributes a Ruby
37
+ // class/module scope segment (#1982 perf; avoids walking to the very top
38
+ // for every heritage/attr call).
39
+ if (current.type === 'program')
40
+ break;
41
+ current = current.parent;
42
+ }
43
+ return segments.length > 0 ? segments.join('.') : undefined;
44
+ }
14
45
  export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
15
46
  let tree = cachedTree;
16
47
  if (tree === undefined) {
@@ -37,18 +68,25 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
37
68
  const out = [];
38
69
  for (const m of rawMatches) {
39
70
  const grouped = {};
71
+ // Parallel tag -> captured SyntaxNode map. The query already hands us each
72
+ // matched node as c.node, so anchors are used directly (via nodeIfType)
73
+ // instead of re-deriving them with findNodeAtRange(tree.rootNode, ...) per
74
+ // match — the O(matches x rootChildren) root-walk fixed for go #1915 /
75
+ // python #1918, mirrored here.
76
+ const nodeMap = {};
40
77
  for (const c of m.captures) {
41
78
  const tag = '@' + c.name;
42
79
  if (tag.startsWith('@_'))
43
80
  continue;
44
81
  grouped[tag] = nodeToCapture(tag, c.node);
82
+ nodeMap[tag] = c.node;
45
83
  }
46
84
  if (Object.keys(grouped).length === 0)
47
85
  continue;
48
86
  // Decompose require/require_relative/load into import captures
49
87
  if (grouped['@import.statement'] !== undefined) {
50
88
  const anchor = grouped['@import.statement'];
51
- const callNode = findNodeAtRange(tree.rootNode, anchor.range, 'call');
89
+ const callNode = nodeIfType(nodeMap['@import.statement'], 'call');
52
90
  if (callNode !== null) {
53
91
  const decomposed = decomposeRubyImport(callNode, anchor);
54
92
  if (decomposed !== null) {
@@ -61,8 +99,7 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
61
99
  }
62
100
  // Synthesize self receiver bindings for methods inside class/module
63
101
  if (grouped['@scope.function'] !== undefined) {
64
- const scopeCap = grouped['@scope.function'];
65
- const fnNode = findFunctionNode(tree.rootNode, scopeCap.range);
102
+ const fnNode = nodeIfType(nodeMap['@scope.function'], ...FUNCTION_NODE_TYPES);
66
103
  if (fnNode !== null) {
67
104
  const enclosingNode = findEnclosingClassOrModule(fnNode);
68
105
  const receiver = synthesizeRubyReceiverBinding(fnNode, enclosingNode);
@@ -74,8 +111,7 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
74
111
  }
75
112
  // Reclassify declaration.function as declaration.method + attach arity
76
113
  if (grouped['@declaration.function'] !== undefined) {
77
- const anchorCap = grouped['@declaration.function'];
78
- const fnNode = findFunctionNode(tree.rootNode, anchorCap.range);
114
+ const fnNode = nodeIfType(nodeMap['@declaration.function'], ...FUNCTION_NODE_TYPES);
79
115
  if (fnNode !== null) {
80
116
  const enclosingNode = findEnclosingClassOrModule(fnNode);
81
117
  if (enclosingNode !== null) {
@@ -105,21 +141,27 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
105
141
  if (grouped['@reference.call.free'] !== undefined && grouped['@reference.name'] !== undefined) {
106
142
  const callName = grouped['@reference.name'].text;
107
143
  if (HERITAGE_CALL_NAMES.has(callName)) {
108
- const callNode = findNodeAtRange(tree.rootNode, grouped['@reference.call.free'].range, 'call');
144
+ const callNode = nodeIfType(nodeMap['@reference.call.free'], 'call');
109
145
  if (callNode !== null) {
110
- const enclosing = findEnclosingClassOrModule(callNode);
111
- const ownerName = enclosing?.childForFieldName('name')?.text;
146
+ const ownerName = buildEnclosingQualifiedName(callNode);
112
147
  if (ownerName) {
113
148
  const argList = callNode.childForFieldName('arguments');
114
149
  if (argList !== null) {
115
150
  for (let ai = 0; ai < argList.namedChildCount; ai++) {
116
151
  const arg = argList.namedChild(ai);
117
152
  if (arg !== null && (arg.type === 'constant' || arg.type === 'scope_resolution')) {
153
+ // Normalize a qualified mixin arg (`Outer::Mixin`) to its dotted
154
+ // form (`Outer.Mixin`) BEFORE embedding it in the ':'-delimited
155
+ // __heritage__ marker: the raw `::` collides with the marker's `:`
156
+ // field separator and emitRubyMixinEdges mis-splits it, dropping
157
+ // the edge (#1982). The dotted form also matches the mixin def's
158
+ // qualifiedName key for resolution. Simple names are unchanged.
159
+ const mixinName = splitQualifiedName(arg.text).join('.');
118
160
  out.push({
119
161
  '@import.statement': grouped['@reference.call.free'],
120
162
  '@import.kind': syntheticCapture('@import.kind', callNode, 'namespace'),
121
- '@import.source': syntheticCapture('@import.source', callNode, `__heritage__:${callName}:${arg.text}:${ownerName}`),
122
- '@import.name': syntheticCapture('@import.name', callNode, arg.text),
163
+ '@import.source': syntheticCapture('@import.source', callNode, encodeMarker('heritage', [callName, mixinName, ownerName])),
164
+ '@import.name': syntheticCapture('@import.name', callNode, mixinName),
123
165
  });
124
166
  }
125
167
  }
@@ -134,21 +176,20 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
134
176
  // localDefs and gets reconciled into model.fields, enabling write-access
135
177
  // resolution via receiver-bound-calls (Case 4 → findOwnedMember).
136
178
  if (ATTR_CALL_NAMES.has(callName)) {
137
- const callNode = findNodeAtRange(tree.rootNode, grouped['@reference.call.free'].range, 'call');
179
+ const callNode = nodeIfType(nodeMap['@reference.call.free'], 'call');
138
180
  if (callNode !== null) {
139
- const enclosing = findEnclosingClassOrModule(callNode);
140
- const ownerName = enclosing?.childForFieldName('name')?.text;
181
+ const ownerName = buildEnclosingQualifiedName(callNode);
141
182
  if (ownerName) {
142
183
  const argList = callNode.childForFieldName('arguments');
143
184
  if (argList !== null) {
144
185
  for (let ai = 0; ai < argList.namedChildCount; ai++) {
145
186
  const arg = argList.namedChild(ai);
146
- if (arg !== null && (arg.type === 'simple_symbol' || arg.type === 'symbol')) {
187
+ if (arg !== null && arg.type === 'simple_symbol') {
147
188
  const propName = arg.text.replace(/^:/, '');
148
189
  out.push({
149
190
  '@import.statement': grouped['@reference.call.free'],
150
191
  '@import.kind': syntheticCapture('@import.kind', callNode, 'namespace'),
151
- '@import.source': syntheticCapture('@import.source', callNode, `__property__:${callName}:${propName}:${ownerName}`),
192
+ '@import.source': syntheticCapture('@import.source', callNode, encodeMarker('property', [callName, propName, ownerName])),
152
193
  '@import.name': syntheticCapture('@import.name', callNode, propName),
153
194
  });
154
195
  // Emit a property declaration so the property flows into
@@ -168,8 +209,7 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
168
209
  // Attach call arity for call expressions
169
210
  const callTag = ['@reference.call.free', '@reference.call.member'].find((t) => grouped[t] !== undefined);
170
211
  if (callTag !== undefined && grouped['@reference.arity'] === undefined) {
171
- const anchor = grouped[callTag];
172
- const callNode = findNodeAtRange(tree.rootNode, anchor.range, 'call');
212
+ const callNode = nodeIfType(nodeMap[callTag], 'call');
173
213
  if (callNode !== null) {
174
214
  const arity = computeRubyCallArity(callNode);
175
215
  grouped['@reference.arity'] = syntheticCapture('@reference.arity', callNode, String(arity));
@@ -261,7 +301,7 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
261
301
  if (argList !== null) {
262
302
  for (let ai = 0; ai < argList.namedChildCount; ai++) {
263
303
  const arg = argList.namedChild(ai);
264
- if (arg !== null && (arg.type === 'simple_symbol' || arg.type === 'symbol')) {
304
+ if (arg !== null && arg.type === 'simple_symbol') {
265
305
  const propName = arg.text.replace(/^:/, '');
266
306
  out.push({
267
307
  '@type-binding.return': syntheticCapture('@type-binding.return', attrNode, text),
@@ -293,6 +333,29 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
293
333
  // return-type binding `methodName → ClassName` on the method node.
294
334
  // This enables cross-file return-type propagation for factory methods
295
335
  // like `def self.get_user; User.new; end` → `get_user → User`.
336
+ // Keys of methods that already got a return binding from the YARD pass above,
337
+ // precomputed once. The previous `out.some(...)` per method was
338
+ // O(methods x out.length) ~ O(n^2); this makes the dedup O(1) per method.
339
+ // Key = `<name>:<return-binding startLine>`, matching the old AND condition.
340
+ //
341
+ // Snapshot-vs-live note (PR #1918 tri-review P3): the old `out.some` was
342
+ // evaluated LIVE, so it also saw constructor-return bindings this very loop
343
+ // pushed in earlier iterations. That made the old code suppress the 2nd of
344
+ // two same-named methods one source row apart whose bodies both end in
345
+ // `Const.new` (the 1st's pushed binding startLine == the 2nd's row via the
346
+ // 1-based/0-based offset below). The snapshot is built from the YARD pass
347
+ // only, so it no longer cross-suppresses — both bindings are emitted, which
348
+ // is the intended behavior (the cross-suppression was unintended). This
349
+ // corner is absent from fixtures, so the capture fingerprint is unchanged;
350
+ // ruby-captures-golden.test.ts pins it explicitly.
351
+ const yardReturnKeys = new Set();
352
+ for (const m of out) {
353
+ const ret = m['@type-binding.return'];
354
+ const name = m['@type-binding.name'];
355
+ if (ret !== undefined && name !== undefined) {
356
+ yardReturnKeys.add(`${name.text}:${ret.range.startLine}`);
357
+ }
358
+ }
296
359
  for (const methodNode of [
297
360
  ...tree.rootNode.descendantsOfType('method'),
298
361
  ...tree.rootNode.descendantsOfType('singleton_method'),
@@ -300,10 +363,8 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
300
363
  const methodName = methodNode.childForFieldName('name')?.text;
301
364
  if (methodName === undefined)
302
365
  continue;
303
- // Skip if a YARD @return already created a return binding for this method
304
- if (out.some((m) => m['@type-binding.return'] !== undefined &&
305
- m['@type-binding.name']?.text === methodName &&
306
- m['@type-binding.return']?.range.startLine === methodNode.startPosition.row)) {
366
+ // Skip if a YARD @return already created a return binding for this method.
367
+ if (yardReturnKeys.has(`${methodName}:${methodNode.startPosition.row}`)) {
307
368
  continue;
308
369
  }
309
370
  const body = methodNode.childForFieldName('body');
@@ -329,8 +390,98 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
329
390
  }
330
391
  }
331
392
  }
393
+ // Fifth pass: superclass inheritance (`class Foo < Bar`).
394
+ // Emit `@reference.inherits` captures so the registry-primary scope-
395
+ // resolution path produces EXTENDS edges (issue #1951). This mirrors the
396
+ // C#/C++ inheritance synthesis: Ruby's superclass edges previously came
397
+ // only from the legacy heritage-capture query (removed in #942), which the
398
+ // worker pipeline drops for registry-primary languages → 0 inheritance edges
399
+ // in worker mode. Mixins (include/extend/prepend) are NOT touched here — they
400
+ // flow through `emitHeritageEdges` (the `__heritage__:` import path above),
401
+ // an independent lane that stays intact when the legacy heritage leg is gated off.
402
+ out.push(...synthesizeRubySuperclassReferences(tree.rootNode));
403
+ return out;
404
+ }
405
+ /**
406
+ * Synthesize `@reference.inherits` captures from Ruby `class Foo < Bar`
407
+ * superclass declarations so the shared `preEmitInheritanceEdges` pass can
408
+ * resolve the base to a Class def and emit an EXTENDS edge.
409
+ *
410
+ * Scope is `class` nodes whose `superclass` field holds either a bare
411
+ * `constant` base (`class D < Super`) or a qualified/scoped
412
+ * `scope_resolution` base (`class C < Outer::Super`, `class E < A::B::C`) —
413
+ * exactly the two shapes the config-driven legacy heritage alternation
414
+ * captured (heritage-extractors/configs/ruby.ts
415
+ * `rubyHeritageShapes: ['constant', 'scope_resolution']`). In prose: the
416
+ * legacy query matched a `class` whose name is a `constant` and whose
417
+ * `superclass` is either a `constant` or a `scope_resolution`, capturing the
418
+ * superclass constant as the inherited base.
419
+ *
420
+ * Previously this pass emitted only for a direct `(constant)` child, so the
421
+ * production registry-primary path silently dropped `Outer::Super`
422
+ * superclasses while the legacy heritage leg captured them — the exact
423
+ * EXTENDS/IMPLEMENTS-drop bug of #1951.
424
+ *
425
+ * THE PARITY CONTRACT: the `@reference.name` bare text must equal the legacy
426
+ * leg's `normalizeSupertypeName(baseNode)` reduction. For a `scope_resolution`
427
+ * (`Outer::Super`, `A::B::C`) the normalizer recurses into the `name:` field
428
+ * and returns the trailing `constant` (`Super` / `C`); this synth mirrors that
429
+ * by reading the same `name:` tail. A bare `constant` is unchanged
430
+ * (byte-identical to the prior emission). `module` nodes are excluded (no
431
+ * superclass field). Mixins (include/extend/prepend) are untouched — they flow
432
+ * through the `__heritage__:` import lane above.
433
+ *
434
+ * Edge type (EXTENDS vs IMPLEMENTS) is decided downstream from the resolved
435
+ * target's symbol kind — this pass only emits `@reference.inherits`.
436
+ */
437
+ function synthesizeRubySuperclassReferences(root) {
438
+ const out = [];
439
+ walkNamedTree(root, (node) => {
440
+ if (node.type !== 'class')
441
+ return;
442
+ const superclass = node.childForFieldName('superclass');
443
+ if (superclass === null)
444
+ return;
445
+ const baseNode = extractRubySuperclassBaseNode(superclass);
446
+ if (baseNode === null)
447
+ return;
448
+ out.push({
449
+ '@reference.inherits': nodeToCapture('@reference.inherits', baseNode),
450
+ '@reference.name': nodeToCapture('@reference.name', baseNode),
451
+ });
452
+ });
332
453
  return out;
333
454
  }
455
+ /**
456
+ * Reduce a Ruby `superclass` node to the bare `constant` the resolver should
457
+ * look up, at parity with the legacy heritage leg's
458
+ * `normalizeSupertypeName(baseNode)`:
459
+ *
460
+ * - direct `(constant)` child (`class D < Super`) → that constant
461
+ * (unchanged from the original emission — kept byte-identical)
462
+ * - `(scope_resolution)` child (`class C < Outer::Super`,
463
+ * `class E < A::B::C`) → the trailing
464
+ * `name:` constant (`Super` / `C`)
465
+ *
466
+ * A `scope_resolution` nests qualifier-first, name-last
467
+ * (`scope: (...) name: (constant)`), so the `name:` field is always the
468
+ * trailing simple identifier — the same tail `normalizeSupertypeName` reaches
469
+ * by recursing through its `name` field. Any other shape returns null (no
470
+ * edge), keeping this emitter at parity with the legacy alternation
471
+ * (`['constant', 'scope_resolution']`).
472
+ */
473
+ function extractRubySuperclassBaseNode(superclass) {
474
+ const directConstant = findChild(superclass, 'constant');
475
+ if (directConstant !== null)
476
+ return directConstant;
477
+ const scoped = findChild(superclass, 'scope_resolution');
478
+ if (scoped !== null) {
479
+ const tail = scoped.childForFieldName('name');
480
+ if (tail !== null && tail.type === 'constant')
481
+ return tail;
482
+ }
483
+ return null;
484
+ }
334
485
  function decomposeRubyImport(callNode, anchor) {
335
486
  const methodNode = callNode.childForFieldName('method');
336
487
  if (methodNode === null)
@@ -431,14 +582,6 @@ function computeRubyCallArity(callNode) {
431
582
  }
432
583
  return count;
433
584
  }
434
- function findFunctionNode(rootNode, range) {
435
- for (const nodeType of FUNCTION_NODE_TYPES) {
436
- const n = findNodeAtRange(rootNode, range, nodeType);
437
- if (n !== null)
438
- return n;
439
- }
440
- return null;
441
- }
442
585
  function scopeExtractionError(stage, filePath, err) {
443
586
  const reason = err instanceof Error ? err.message : String(err);
444
587
  return new Error(`[ruby] tree-sitter ${stage} failed for ${filePath}: ${reason}; skipping scope extraction for this file`);
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { resolveRubyImportInternal } from '../../import-resolvers/ruby.js';
10
10
  import { buildSuffixIndex } from '../../import-resolvers/utils.js';
11
+ import { isHeritageMarker } from '../../utils/heritage-marker.js';
11
12
  // ─── resolveRubyImportTarget ──────────────────────────────────────────────
12
13
  /**
13
14
  * ScopeResolver-shaped adapter:
@@ -25,7 +26,7 @@ import { buildSuffixIndex } from '../../import-resolvers/utils.js';
25
26
  export function resolveRubyImportTarget(targetRaw, fromFile, allFilePaths, _resolutionConfig) {
26
27
  if (!targetRaw)
27
28
  return null;
28
- if (targetRaw.startsWith('__heritage__:') || targetRaw.startsWith('__property__:'))
29
+ if (isHeritageMarker(targetRaw))
29
30
  return null;
30
31
  const fromNormalized = fromFile.replace(/\\/g, '/');
31
32
  const fromDir = fromNormalized.includes('/')
@@ -1,3 +1,4 @@
1
+ import { isHeritageMarker } from '../../utils/heritage-marker.js';
1
2
  // ─── interpretImport ──────────────────────────────────────────────────────
2
3
  /**
3
4
  * Interpret a pre-decomposed Ruby import capture into a `ParsedImport`.
@@ -18,7 +19,7 @@ export function interpretRubyImport(captures) {
18
19
  return null;
19
20
  // Heritage-encoded imports (__heritage__:include:Serializable:User)
20
21
  // are stored as namespace imports so emitHeritageEdges can read them.
21
- if (source.startsWith('__heritage__:') || source.startsWith('__property__:')) {
22
+ if (isHeritageMarker(source)) {
22
23
  const name = captures['@import.name']?.text ?? source;
23
24
  return { kind: 'namespace', localName: name, importedName: name, targetRaw: source };
24
25
  }
@@ -52,11 +52,21 @@ const RUBY_SCOPE_QUERY = `
52
52
  (class
53
53
  name: (constant) @declaration.name) @declaration.class
54
54
 
55
+ ;; class Foo::Bar — namespaced class definition
56
+ (class
57
+ name: (scope_resolution
58
+ name: (constant) @declaration.name)) @declaration.class
59
+
55
60
  ;; ── Declarations — module (labeled Trait for class-like registry lookup) ─
56
61
 
57
62
  (module
58
63
  name: (constant) @declaration.name) @declaration.trait
59
64
 
65
+ ;; module Baz::Qux — namespaced module definition
66
+ (module
67
+ name: (scope_resolution
68
+ name: (constant) @declaration.name)) @declaration.trait
69
+
60
70
  ;; ── Declarations — method (instance) ─────────────────────────────────────
61
71
 
62
72
  (method
@@ -5,17 +5,59 @@ import { rubyArityCompatibility, rubyMergeBindings, resolveRubyImportTarget } fr
5
5
  import { populateClassOwnedMembers, isClassLike } from '../../scope-resolution/scope/walkers.js';
6
6
  import { resolveDefGraphId } from '../../scope-resolution/graph-bridge/ids.js';
7
7
  import { generateId } from '../../../../lib/utils.js';
8
- const HERITAGE_PREFIX = '__heritage__:';
8
+ import { decodeMarker } from '../../utils/heritage-marker.js';
9
+ /**
10
+ * #1991: resolve a BARE mixin reference (`include Loggable`) to a nested module by
11
+ * the INCLUDING class's lexical scope — Ruby looks up a constant in the innermost
12
+ * enclosing scope first. For owner `App.S`, try `App.Loggable`, then walk outward.
13
+ * Returns undefined if no enclosing-scope-qualified module exists.
14
+ */
15
+ function qualifyMixinByOwnerScope(mixinName, ownerName, graphIdByName) {
16
+ let prefix = ownerName;
17
+ let dot = prefix.lastIndexOf('.');
18
+ while (dot !== -1) {
19
+ prefix = prefix.slice(0, dot);
20
+ const g = graphIdByName.get(`${prefix}.${mixinName}`);
21
+ if (g !== undefined)
22
+ return g;
23
+ dot = prefix.lastIndexOf('.');
24
+ }
25
+ return undefined;
26
+ }
9
27
  function emitRubyMixinEdges(graph, parsedFiles, nodeLookup) {
10
28
  const graphIdByName = new Map();
29
+ // Secondary tail -> graphId map. The `__heritage__` marker carries the mixin
30
+ // TARGET as the bare written name (`arg.text`, e.g. `Loggable`), not its full
31
+ // qualifiedName, so a nested mixin module included by its short name misses the
32
+ // full-qn map. We first resolve it lexically by the including class's enclosing
33
+ // scope (`qualifyMixinByOwnerScope`); this tail map is the last resort. A genuine
34
+ // same-tail collision is mapped to `null` so we REFUSE to guess (#1991) rather
35
+ // than the old first-wins, which cross-wired App::Loggable / Web::Loggable.
36
+ const graphIdByTail = new Map();
11
37
  for (const parsed of parsedFiles) {
12
38
  for (const def of parsed.localDefs) {
13
39
  if (!isClassLike(def.type))
14
40
  continue;
15
41
  const graphId = resolveDefGraphId(parsed.filePath, def, nodeLookup);
16
42
  if (graphId !== undefined) {
17
- const simpleName = def.qualifiedName?.split('.').pop() ?? def.qualifiedName ?? '';
18
- graphIdByName.set(simpleName, graphId);
43
+ // Key by the FULL qualified name (`Outer.Inner`), NOT the simple tail.
44
+ // Same-tail nested classes (`Outer::Inner` + `Other::Inner`) otherwise
45
+ // collapse onto one `Inner` key (last-wins) and cross-wire their mixin /
46
+ // attr_accessor owners (#1982). The `__heritage__`/`__property__` markers
47
+ // carry the full qualified owner name in lockstep (see ruby/captures.ts).
48
+ const fullName = def.qualifiedName ?? '';
49
+ if (fullName.length > 0) {
50
+ graphIdByName.set(fullName, graphId);
51
+ const dot = fullName.lastIndexOf('.');
52
+ const tail = dot === -1 ? fullName : fullName.slice(dot + 1);
53
+ if (tail.length > 0) {
54
+ const existingTail = graphIdByTail.get(tail);
55
+ if (existingTail === undefined)
56
+ graphIdByTail.set(tail, graphId);
57
+ else if (existingTail !== null && existingTail !== graphId)
58
+ graphIdByTail.set(tail, null); // same-tail collision — refuse to guess
59
+ }
60
+ }
19
61
  }
20
62
  }
21
63
  }
@@ -28,14 +70,22 @@ function emitRubyMixinEdges(graph, parsedFiles, nodeLookup) {
28
70
  }
29
71
  for (const parsed of parsedFiles) {
30
72
  for (const imp of parsed.parsedImports) {
31
- if (!imp.targetRaw.startsWith(HERITAGE_PREFIX))
73
+ const decoded = decodeMarker(imp.targetRaw);
74
+ if (decoded?.kind !== 'heritage')
32
75
  continue;
33
- const parts = imp.targetRaw.slice(HERITAGE_PREFIX.length).split(':');
76
+ const parts = decoded.fields;
34
77
  if (parts.length < 3)
35
78
  continue;
36
79
  const [kind, mixinName, className] = parts;
37
80
  const classGraphId = graphIdByName.get(className);
38
- const mixinGraphId = graphIdByName.get(mixinName);
81
+ // Owner stays full-qn. The mixin target may be written by short name and miss
82
+ // the full-qn map; resolve it lexically by the including class's enclosing
83
+ // scope (`App::S` + `Loggable` -> `App::Loggable`), then fall back to the tail
84
+ // map ONLY when unambiguous — never first-wins on a collision (#1982/#1991).
85
+ const mixinGraphId = graphIdByName.get(mixinName) ??
86
+ qualifyMixinByOwnerScope(mixinName, className, graphIdByName) ??
87
+ graphIdByTail.get(mixinName) ??
88
+ undefined;
39
89
  if (classGraphId === undefined || mixinGraphId === undefined)
40
90
  continue;
41
91
  const edgeKey = `${classGraphId}->${mixinGraphId}:${kind}`;
@@ -62,12 +112,12 @@ function emitRubyMixinEdges(graph, parsedFiles, nodeLookup) {
62
112
  existingProps.add(`${rel.sourceId}->prop:${targetNode.properties.name}`);
63
113
  }
64
114
  }
65
- const PROPERTY_PREFIX = '__property__:';
66
115
  for (const parsed of parsedFiles) {
67
116
  for (const imp of parsed.parsedImports) {
68
- if (!imp.targetRaw.startsWith(PROPERTY_PREFIX))
117
+ const decoded = decodeMarker(imp.targetRaw);
118
+ if (decoded?.kind !== 'property')
69
119
  continue;
70
- const parts = imp.targetRaw.slice(PROPERTY_PREFIX.length).split(':');
120
+ const parts = decoded.fields;
71
121
  if (parts.length < 3)
72
122
  continue;
73
123
  const [_attrKind, propName, className] = parts;
@@ -137,8 +187,8 @@ function buildRubyMro(graph, parsedFiles, nodeLookup) {
137
187
  }
138
188
  // Step 4: Reorder MRO per Ruby semantics.
139
189
  // Order: prepend (reversed) → direct extends chain → include (reversed).
140
- // `extend` is excluded — it belongs to singleton dispatch only (legacy
141
- // `getInstanceAncestry` in heritage-map.ts explicitly drops extend entries).
190
+ // `extend` is excluded — it belongs to singleton dispatch only (the
191
+ // instance-ancestry walk drops extend entries).
142
192
  // Reversed because Ruby declaration order means last-declared wins
143
193
  // (prepend B; prepend A → B checked before A).
144
194
  for (const defId of defIdByGraphId.values()) {
@@ -24,10 +24,6 @@ import { createVariableExtractor } from '../variable-extractors/generic.js';
24
24
  import { rubyVariableConfig } from '../variable-extractors/configs/ruby.js';
25
25
  import { createCallExtractor } from '../call-extractors/generic.js';
26
26
  import { rubyCallConfig } from '../call-extractors/configs/ruby.js';
27
- import { createHeritageExtractor } from '../heritage-extractors/generic.js';
28
- import { rubyHeritageConfig } from '../heritage-extractors/configs/ruby.js';
29
- import { maybeRewriteRubyBareCallToSelf } from '../utils/ruby-self-call.js';
30
- import { findEnclosingClassInfo } from '../utils/ast-helpers.js';
31
27
  import { emitRubyScopeCaptures, rubyArityCompatibility, rubyBindingScopeFor, rubyImportOwningScope, rubyReceiverBinding, interpretRubyImport, interpretRubyTypeBinding, } from './ruby/index.js';
32
28
  /**
33
29
  * Ruby label override. Applied to:
@@ -122,7 +118,8 @@ const BUILT_INS = new Set([
122
118
  /**
123
119
  * Remaps `class << self` (singleton_class) to its enclosing class/module for
124
120
  * receiver inference. A `singleton_class` node is not itself a type — walking
125
- * up to the real owner lets `inferImplicitReceiver` set `hint='singleton'`.
121
+ * up to the real owner resolves the singleton's enclosing class for the
122
+ * `resolveEnclosingOwner` scope-resolution hook.
126
123
  * Returns null for orphaned singleton_class (no enclosing class/module found).
127
124
  * All other container types are returned as-is.
128
125
  */
@@ -172,7 +169,6 @@ export const rubyProvider = defineLanguage({
172
169
  exportChecker: rubyExportChecker,
173
170
  importResolver: createImportResolver(rubyImportConfig),
174
171
  callRouter: routeRubyCall,
175
- importSemantics: 'wildcard-leaf',
176
172
  callExtractor: createCallExtractor(rubyCallConfig),
177
173
  resolveEnclosingOwner: rubyResolveEnclosingOwner,
178
174
  fieldExtractor: createFieldExtractor(rubyFieldConfig),
@@ -182,56 +178,11 @@ export const rubyProvider = defineLanguage({
182
178
  }),
183
179
  variableExtractor: createVariableExtractor(rubyVariableConfig),
184
180
  classExtractor: createClassExtractor(rubyClassConfig),
185
- heritageExtractor: createHeritageExtractor(rubyHeritageConfig),
186
181
  labelOverride: rubyLabelOverride,
187
182
  // Ruby MRO is kind-aware: prepend providers beat the class's own method,
188
- // which in turn beats include providers. See `lookupMethodByOwnerWithMRO`
189
- // in `model/resolve.ts` for the walk order.
183
+ // which in turn beats include providers. The graph-level MRO phase
184
+ // (mro-processor.ts) and per-resolver buildMro consume this strategy.
190
185
  mroStrategy: 'ruby-mixin',
191
- // ── DAG hooks ────────────────────────────────────────────────────
192
- //
193
- // DAG stage 3: rewrite bare calls (e.g. `serialize` in Account#call_serialize)
194
- // as `self.serialize` so they route through owner-scoped MRO instead of
195
- // global free-call lookup. `dispatchKind` goes into `hint` for stage 4.
196
- inferImplicitReceiver: ({ calledName, callForm, receiverName, receiverTypeName, callNode, filePath, }) => {
197
- // Only fire when no receiver has been resolved already.
198
- if (receiverName || receiverTypeName)
199
- return null;
200
- const enclosing = findEnclosingClassInfo(callNode, filePath, rubyResolveEnclosingOwner);
201
- const rewrite = maybeRewriteRubyBareCallToSelf(calledName, callForm, callNode, enclosing?.className ?? null, { isBuiltInName: (n) => BUILT_INS.has(n), mroStrategy: 'ruby-mixin' });
202
- if (!rewrite)
203
- return null;
204
- return {
205
- callForm: rewrite.callForm,
206
- receiverName: rewrite.receiverName,
207
- receiverTypeName: rewrite.receiverTypeName,
208
- receiverSource: 'implicit-self',
209
- hint: rewrite.dispatchKind, // 'instance' | 'singleton'
210
- };
211
- },
212
- // DAG stage 4: two Ruby dispatch overrides —
213
- // implicit-self: MRO walk first, fallback to free-arity-narrowed on miss.
214
- // class-as-receiver: singleton ancestry (extend providers only); miss null-routes.
215
- selectDispatch: ({ receiverSource, hint }) => {
216
- if (receiverSource === 'implicit-self') {
217
- // hint='instance' → instance ancestry (prepend→direct→include, see mro-strategy.ts § 'ruby-mixin')
218
- // hint='singleton' → singleton ancestry (extend providers only; miss null-routes)
219
- const ancestryView = hint === 'singleton' ? 'singleton' : 'instance';
220
- return {
221
- primary: 'owner-scoped',
222
- fallback: 'free-arity-narrowed',
223
- ancestryView,
224
- };
225
- }
226
- if (receiverSource === 'class-as-receiver') {
227
- // Class constant receiver (e.g. Account.log): singleton ancestry only; miss null-routes.
228
- return {
229
- primary: 'owner-scoped',
230
- ancestryView: 'singleton',
231
- };
232
- }
233
- return null;
234
- },
235
186
  builtInNames: BUILT_INS,
236
187
  // ── RFC #909 Ring 3: scope-based resolution hooks ──────────
237
188
  emitScopeCaptures: emitRubyScopeCaptures,