gitnexus 1.6.10-rc.99 → 1.6.10

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 (775) hide show
  1. package/README.md +177 -18
  2. package/dist/_shared/graph/types.d.ts +21 -2
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +3 -3
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js +1 -1
  7. package/dist/_shared/index.js.map +1 -1
  8. package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
  9. package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
  10. package/dist/_shared/integrations/resilient-fetch.d.ts +16 -0
  11. package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
  12. package/dist/_shared/integrations/resilient-fetch.js +19 -7
  13. package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
  14. package/dist/_shared/language-detection.d.ts.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.d.ts +2 -2
  16. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  17. package/dist/_shared/lbug/schema-constants.js +3 -0
  18. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  19. package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
  20. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +5 -0
  21. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
  22. package/dist/_shared/scope-resolution/finalize-algorithm.js +315 -36
  23. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  24. package/dist/_shared/scope-resolution/reference-site.d.ts +115 -0
  25. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  26. package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
  27. package/dist/_shared/scope-resolution/registries/lookup-core.d.ts.map +1 -1
  28. package/dist/_shared/scope-resolution/registries/lookup-core.js +58 -2
  29. package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
  30. package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
  31. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  32. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  33. package/dist/_shared/scope-resolution/symbol-definition.d.ts +47 -0
  34. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  35. package/dist/_shared/scope-resolution/types.d.ts +278 -3
  36. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  37. package/dist/cli/ai-context.d.ts +3 -2
  38. package/dist/cli/ai-context.js +71 -16
  39. package/dist/cli/analyze-config.d.ts +1 -1
  40. package/dist/cli/analyze-options.d.ts +131 -0
  41. package/dist/cli/analyze-options.js +1 -0
  42. package/dist/cli/analyze.d.ts +21 -113
  43. package/dist/cli/analyze.js +172 -29
  44. package/dist/cli/cli-message.d.ts +1 -1
  45. package/dist/cli/detect-changes-format.js +19 -2
  46. package/dist/cli/doctor.d.ts +12 -0
  47. package/dist/cli/doctor.js +32 -5
  48. package/dist/cli/editor-targets.js +6 -0
  49. package/dist/cli/eval-server.js +2 -1
  50. package/dist/cli/format-symbol.d.ts +15 -0
  51. package/dist/cli/format-symbol.js +17 -0
  52. package/dist/cli/generated-skill.d.ts +17 -0
  53. package/dist/cli/generated-skill.js +1 -0
  54. package/dist/cli/group.js +229 -21
  55. package/dist/cli/help-i18n.js +1 -2
  56. package/dist/cli/i18n/en.d.ts +11 -9
  57. package/dist/cli/i18n/en.js +13 -9
  58. package/dist/cli/i18n/resources.d.ts +15 -11
  59. package/dist/cli/i18n/zh-CN.d.ts +4 -2
  60. package/dist/cli/i18n/zh-CN.js +11 -9
  61. package/dist/cli/index.js +8 -4
  62. package/dist/cli/resolve-invocation.d.ts +7 -3
  63. package/dist/cli/resolve-invocation.js +7 -3
  64. package/dist/cli/setup.js +4 -3
  65. package/dist/cli/skill-gen.d.ts +1 -6
  66. package/dist/cli/tool.d.ts +1 -0
  67. package/dist/cli/tool.js +74 -17
  68. package/dist/cli/wiki.js +53 -10
  69. package/dist/config/ignore-service.d.ts +2 -0
  70. package/dist/config/ignore-service.js +54 -13
  71. package/dist/core/analyzer-identity.d.ts +80 -0
  72. package/dist/core/analyzer-identity.js +364 -26
  73. package/dist/core/augmentation/engine.js +86 -71
  74. package/dist/core/embedding-checkpoint.d.ts +143 -0
  75. package/dist/core/embedding-checkpoint.js +221 -0
  76. package/dist/core/embedding-count.d.ts +61 -0
  77. package/dist/core/embedding-count.js +69 -0
  78. package/dist/core/embeddings/ast-utils.js +9 -1
  79. package/dist/core/embeddings/embedding-pipeline.d.ts +8 -0
  80. package/dist/core/embeddings/embedding-pipeline.js +253 -14
  81. package/dist/core/embeddings/http-client.d.ts +5 -0
  82. package/dist/core/embeddings/http-client.js +142 -27
  83. package/dist/core/graph/graph.js +3 -0
  84. package/dist/core/graph/import-cycles.d.ts +194 -3
  85. package/dist/core/graph/import-cycles.js +522 -73
  86. package/dist/core/graph/types.d.ts +18 -0
  87. package/dist/core/group/bridge-db.d.ts +204 -1
  88. package/dist/core/group/bridge-db.js +401 -28
  89. package/dist/core/group/completeness.d.ts +130 -0
  90. package/dist/core/group/completeness.js +83 -0
  91. package/dist/core/group/config-parser.js +0 -5
  92. package/dist/core/group/cross-impact.d.ts +46 -1
  93. package/dist/core/group/cross-impact.js +220 -19
  94. package/dist/core/group/cross-trace.d.ts +32 -11
  95. package/dist/core/group/cross-trace.js +114 -20
  96. package/dist/core/group/extractors/http-patterns/java.js +278 -22
  97. package/dist/core/group/extractors/http-patterns/node.js +332 -216
  98. package/dist/core/group/extractors/http-patterns/types.d.ts +8 -0
  99. package/dist/core/group/extractors/http-route-extractor.d.ts +1 -0
  100. package/dist/core/group/extractors/http-route-extractor.js +122 -48
  101. package/dist/core/group/extractors/include-extractor.js +20 -2
  102. package/dist/core/group/extractors/manifest-extractor.d.ts +1 -1
  103. package/dist/core/group/extractors/manifest-extractor.js +7 -7
  104. package/dist/core/group/extractors/python-workspace-extractor.js +5 -2
  105. package/dist/core/group/group-lock.d.ts +31 -0
  106. package/dist/core/group/group-lock.js +166 -0
  107. package/dist/core/group/service.js +297 -16
  108. package/dist/core/group/storage.d.ts +3 -0
  109. package/dist/core/group/storage.js +7 -39
  110. package/dist/core/group/sync.d.ts +49 -3
  111. package/dist/core/group/sync.js +0 -0
  112. package/dist/core/group/types.d.ts +183 -8
  113. package/dist/core/group/types.js +28 -1
  114. package/dist/core/incremental/subgraph-extract.d.ts +9 -6
  115. package/dist/core/incremental/subgraph-extract.js +33 -10
  116. package/dist/core/index-freshness.d.ts +77 -2
  117. package/dist/core/index-freshness.js +109 -2
  118. package/dist/core/ingestion/call-processor.d.ts +13 -1
  119. package/dist/core/ingestion/call-processor.js +110 -3
  120. package/dist/core/ingestion/cfg/callee-cell-format.d.ts +42 -0
  121. package/dist/core/ingestion/cfg/callee-cell-format.js +42 -0
  122. package/dist/core/ingestion/cfg/emit.d.ts +8 -23
  123. package/dist/core/ingestion/cfg/emit.js +9 -23
  124. package/dist/core/ingestion/class-extractors/configs/go.js +10 -5
  125. package/dist/core/ingestion/cluster-enricher.js +8 -4
  126. package/dist/core/ingestion/community-processor.d.ts +21 -3
  127. package/dist/core/ingestion/community-processor.js +81 -82
  128. package/dist/core/ingestion/di-extractors/index.d.ts +9 -33
  129. package/dist/core/ingestion/di-extractors/spring.d.ts +1 -1
  130. package/dist/core/ingestion/di-extractors/spring.js +8 -1
  131. package/dist/core/ingestion/di-extractors/types.d.ts +60 -0
  132. package/dist/core/ingestion/di-extractors/types.js +15 -0
  133. package/dist/core/ingestion/filesystem-walker.js +30 -14
  134. package/dist/core/ingestion/finalize-orchestrator.js +1 -0
  135. package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +6 -0
  136. package/dist/core/ingestion/frameworks/spring/analysis-features.js +35 -1
  137. package/dist/core/ingestion/frameworks/spring/annotation-arguments.d.ts +13 -0
  138. package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +227 -0
  139. package/dist/core/ingestion/frameworks/spring/aop-candidates.d.ts +15 -0
  140. package/dist/core/ingestion/frameworks/spring/aop-candidates.js +85 -0
  141. package/dist/core/ingestion/frameworks/spring/aop.d.ts +118 -0
  142. package/dist/core/ingestion/frameworks/spring/aop.js +476 -0
  143. package/dist/core/ingestion/frameworks/spring/auto-configuration.d.ts +8 -0
  144. package/dist/core/ingestion/frameworks/spring/auto-configuration.js +16 -0
  145. package/dist/core/ingestion/frameworks/spring/bean-catalog.js +1 -0
  146. package/dist/core/ingestion/frameworks/spring/bean-factories.d.ts +33 -0
  147. package/dist/core/ingestion/frameworks/spring/bean-factories.js +65 -0
  148. package/dist/core/ingestion/frameworks/spring/conditionals.d.ts +25 -0
  149. package/dist/core/ingestion/frameworks/spring/conditionals.js +319 -0
  150. package/dist/core/ingestion/frameworks/spring/di-metadata.d.ts +3 -0
  151. package/dist/core/ingestion/frameworks/spring/di-metadata.js +162 -13
  152. package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +28 -0
  153. package/dist/core/ingestion/frameworks/spring/non-http-handlers.js +152 -0
  154. package/dist/core/ingestion/frameworks/spring/resource-injection.d.ts +5 -0
  155. package/dist/core/ingestion/frameworks/spring/resource-injection.js +91 -0
  156. package/dist/core/ingestion/import-resolvers/configs/csharp.js +5 -1
  157. package/dist/core/ingestion/import-resolvers/configs/swift.js +13 -0
  158. package/dist/core/ingestion/import-resolvers/csharp.d.ts +9 -1
  159. package/dist/core/ingestion/import-resolvers/csharp.js +234 -27
  160. package/dist/core/ingestion/import-resolvers/go.d.ts +11 -1
  161. package/dist/core/ingestion/import-resolvers/go.js +44 -17
  162. package/dist/core/ingestion/import-resolvers/jvm.d.ts +2 -2
  163. package/dist/core/ingestion/import-resolvers/node-workspace-packages.d.ts +90 -0
  164. package/dist/core/ingestion/import-resolvers/node-workspace-packages.js +429 -0
  165. package/dist/core/ingestion/import-resolvers/package-dir-index.d.ts +124 -0
  166. package/dist/core/ingestion/import-resolvers/package-dir-index.js +223 -0
  167. package/dist/core/ingestion/import-resolvers/pass-cache.d.ts +50 -0
  168. package/dist/core/ingestion/import-resolvers/pass-cache.js +60 -0
  169. package/dist/core/ingestion/import-resolvers/per-file-set.d.ts +71 -0
  170. package/dist/core/ingestion/import-resolvers/per-file-set.js +11 -0
  171. package/dist/core/ingestion/import-resolvers/php.d.ts +1 -1
  172. package/dist/core/ingestion/import-resolvers/php.js +65 -19
  173. package/dist/core/ingestion/import-resolvers/python-file-index.d.ts +201 -0
  174. package/dist/core/ingestion/import-resolvers/python-file-index.js +302 -0
  175. package/dist/core/ingestion/import-resolvers/python.js +25 -6
  176. package/dist/core/ingestion/import-resolvers/ruby.d.ts +1 -1
  177. package/dist/core/ingestion/import-resolvers/rust.d.ts +2 -2
  178. package/dist/core/ingestion/import-resolvers/standard.d.ts +1 -1
  179. package/dist/core/ingestion/import-resolvers/types.d.ts +1 -12
  180. package/dist/core/ingestion/import-resolvers/utils.d.ts +65 -6
  181. package/dist/core/ingestion/import-resolvers/utils.js +215 -36
  182. package/dist/core/ingestion/import-resolvers/workspace-file-index.d.ts +72 -0
  183. package/dist/core/ingestion/import-resolvers/workspace-file-index.js +58 -0
  184. package/dist/core/ingestion/language-config.d.ts +29 -1
  185. package/dist/core/ingestion/language-config.js +110 -35
  186. package/dist/core/ingestion/language-provider.d.ts +209 -7
  187. package/dist/core/ingestion/language-provider.js +37 -0
  188. package/dist/core/ingestion/languages/c/captures.js +7 -0
  189. package/dist/core/ingestion/languages/c/import-target.js +12 -16
  190. package/dist/core/ingestion/languages/c/scope-resolver.js +20 -19
  191. package/dist/core/ingestion/languages/c/static-linkage.js +12 -16
  192. package/dist/core/ingestion/languages/c-cpp.js +13 -0
  193. package/dist/core/ingestion/languages/cobol/scope-resolver.js +27 -20
  194. package/dist/core/ingestion/languages/cobol.js +13 -0
  195. package/dist/core/ingestion/languages/cpp/adl.d.ts +2 -2
  196. package/dist/core/ingestion/languages/cpp/adl.js +67 -44
  197. package/dist/core/ingestion/languages/cpp/captures.js +14 -2
  198. package/dist/core/ingestion/languages/cpp/file-local-linkage.js +11 -15
  199. package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +28 -8
  200. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +242 -68
  201. package/dist/core/ingestion/languages/cpp/interpret.d.ts +2 -0
  202. package/dist/core/ingestion/languages/cpp/interpret.js +126 -6
  203. package/dist/core/ingestion/languages/cpp/query.js +106 -0
  204. package/dist/core/ingestion/languages/cpp/scope-resolver.js +48 -20
  205. package/dist/core/ingestion/languages/csharp/accessor-unwrap.d.ts +2 -15
  206. package/dist/core/ingestion/languages/csharp/accessor-unwrap.js +18 -10
  207. package/dist/core/ingestion/languages/csharp/captures.js +19 -0
  208. package/dist/core/ingestion/languages/csharp/import-target.js +46 -72
  209. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +5 -1
  210. package/dist/core/ingestion/languages/csharp/query.js +25 -5
  211. package/dist/core/ingestion/languages/csharp/scope-resolver.js +75 -2
  212. package/dist/core/ingestion/languages/dart/captures.d.ts +10 -0
  213. package/dist/core/ingestion/languages/dart/captures.js +598 -16
  214. package/dist/core/ingestion/languages/dart/import-target.js +32 -9
  215. package/dist/core/ingestion/languages/dart/index.d.ts +1 -1
  216. package/dist/core/ingestion/languages/dart/index.js +1 -1
  217. package/dist/core/ingestion/languages/dart/query.js +98 -1
  218. package/dist/core/ingestion/languages/dart/scope-resolver.js +14 -3
  219. package/dist/core/ingestion/languages/dart/simple-hooks.js +9 -0
  220. package/dist/core/ingestion/languages/dart.js +6 -1
  221. package/dist/core/ingestion/languages/go/captures.js +108 -3
  222. package/dist/core/ingestion/languages/go/generic-type-parameters.d.ts +31 -0
  223. package/dist/core/ingestion/languages/go/generic-type-parameters.js +140 -0
  224. package/dist/core/ingestion/languages/go/import-target.d.ts +3 -10
  225. package/dist/core/ingestion/languages/go/import-target.js +34 -30
  226. package/dist/core/ingestion/languages/go/index.d.ts +1 -1
  227. package/dist/core/ingestion/languages/go/interface-impls.d.ts +9 -1
  228. package/dist/core/ingestion/languages/go/interface-impls.js +693 -87
  229. package/dist/core/ingestion/languages/go/interpret.d.ts +2 -0
  230. package/dist/core/ingestion/languages/go/interpret.js +22 -8
  231. package/dist/core/ingestion/languages/go/method-owners.js +31 -12
  232. package/dist/core/ingestion/languages/go/package-clause.d.ts +46 -0
  233. package/dist/core/ingestion/languages/go/package-clause.js +75 -0
  234. package/dist/core/ingestion/languages/go/package-siblings.js +7 -11
  235. package/dist/core/ingestion/languages/go/query.js +56 -3
  236. package/dist/core/ingestion/languages/go/scope-resolver.js +39 -0
  237. package/dist/core/ingestion/languages/go.js +9 -0
  238. package/dist/core/ingestion/languages/java/analysis-features.d.ts +4 -0
  239. package/dist/core/ingestion/languages/java/analysis-features.js +12 -0
  240. package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +12 -0
  241. package/dist/core/ingestion/languages/java/capture-side-channel.js +48 -0
  242. package/dist/core/ingestion/languages/java/captures.js +77 -32
  243. package/dist/core/ingestion/languages/java/import-target.d.ts +49 -9
  244. package/dist/core/ingestion/languages/java/import-target.js +68 -88
  245. package/dist/core/ingestion/languages/java/interpret.js +3 -2
  246. package/dist/core/ingestion/languages/java/module-resolution.d.ts +62 -0
  247. package/dist/core/ingestion/languages/java/module-resolution.js +142 -0
  248. package/dist/core/ingestion/languages/java/query.js +15 -3
  249. package/dist/core/ingestion/languages/java/record-components.d.ts +14 -0
  250. package/dist/core/ingestion/languages/java/record-components.js +185 -0
  251. package/dist/core/ingestion/languages/java/scope-resolver.js +10 -2
  252. package/dist/core/ingestion/languages/java/spring-aop.d.ts +12 -0
  253. package/dist/core/ingestion/languages/java/spring-aop.js +49 -0
  254. package/dist/core/ingestion/languages/java/spring-conditionals.d.ts +11 -0
  255. package/dist/core/ingestion/languages/java/spring-conditionals.js +48 -0
  256. package/dist/core/ingestion/languages/java/spring-di.d.ts +4 -1
  257. package/dist/core/ingestion/languages/java/spring-di.js +41 -9
  258. package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +7 -0
  259. package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +32 -0
  260. package/dist/core/ingestion/languages/java.js +94 -3
  261. package/dist/core/ingestion/languages/javascript/captures.d.ts +6 -1
  262. package/dist/core/ingestion/languages/javascript/captures.js +262 -4
  263. package/dist/core/ingestion/languages/javascript/import-target.d.ts +17 -21
  264. package/dist/core/ingestion/languages/javascript/import-target.js +24 -41
  265. package/dist/core/ingestion/languages/javascript/index.d.ts +54 -5
  266. package/dist/core/ingestion/languages/javascript/index.js +54 -5
  267. package/dist/core/ingestion/languages/javascript/query.d.ts +1 -0
  268. package/dist/core/ingestion/languages/javascript/query.js +211 -5
  269. package/dist/core/ingestion/languages/javascript/scope-resolver.js +12 -0
  270. package/dist/core/ingestion/languages/javascript/simple-hooks.js +2 -1
  271. package/dist/core/ingestion/languages/jvm/package-siblings.js +77 -9
  272. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
  273. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +48 -0
  274. package/dist/core/ingestion/languages/kotlin/captures.js +43 -1
  275. package/dist/core/ingestion/languages/kotlin/import-target.d.ts +8 -1
  276. package/dist/core/ingestion/languages/kotlin/import-target.js +20 -123
  277. package/dist/core/ingestion/languages/kotlin/index.d.ts +1 -0
  278. package/dist/core/ingestion/languages/kotlin/index.js +1 -0
  279. package/dist/core/ingestion/languages/kotlin/module-resolution.d.ts +22 -0
  280. package/dist/core/ingestion/languages/kotlin/module-resolution.js +108 -0
  281. package/dist/core/ingestion/languages/kotlin/query.js +28 -2
  282. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +23 -2
  283. package/dist/core/ingestion/languages/kotlin/spring-aop.d.ts +12 -0
  284. package/dist/core/ingestion/languages/kotlin/spring-aop.js +64 -0
  285. package/dist/core/ingestion/languages/kotlin/spring-conditionals.d.ts +12 -0
  286. package/dist/core/ingestion/languages/kotlin/spring-conditionals.js +49 -0
  287. package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +2 -0
  288. package/dist/core/ingestion/languages/kotlin/spring-di.js +60 -11
  289. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +10 -0
  290. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +41 -0
  291. package/dist/core/ingestion/languages/php/captures.d.ts +5 -0
  292. package/dist/core/ingestion/languages/php/captures.js +319 -51
  293. package/dist/core/ingestion/languages/php/import-target.d.ts +3 -4
  294. package/dist/core/ingestion/languages/php/import-target.js +192 -62
  295. package/dist/core/ingestion/languages/php/query.js +31 -0
  296. package/dist/core/ingestion/languages/python/arity-metadata.d.ts +1 -0
  297. package/dist/core/ingestion/languages/python/arity-metadata.js +1 -0
  298. package/dist/core/ingestion/languages/python/captures.js +29 -0
  299. package/dist/core/ingestion/languages/python/import-decomposer.js +22 -1
  300. package/dist/core/ingestion/languages/python/import-target.d.ts +42 -1
  301. package/dist/core/ingestion/languages/python/import-target.js +277 -91
  302. package/dist/core/ingestion/languages/python/index.d.ts +1 -1
  303. package/dist/core/ingestion/languages/python/index.js +1 -1
  304. package/dist/core/ingestion/languages/python/interpret.d.ts +52 -0
  305. package/dist/core/ingestion/languages/python/interpret.js +249 -7
  306. package/dist/core/ingestion/languages/python/query.js +9 -0
  307. package/dist/core/ingestion/languages/python/receiver-binding.d.ts +8 -6
  308. package/dist/core/ingestion/languages/python/receiver-binding.js +108 -12
  309. package/dist/core/ingestion/languages/python/scope-resolver.js +27 -4
  310. package/dist/core/ingestion/languages/python/simple-hooks.js +2 -8
  311. package/dist/core/ingestion/languages/python.js +13 -0
  312. package/dist/core/ingestion/languages/ruby/captures.js +158 -0
  313. package/dist/core/ingestion/languages/ruby/import-target.js +7 -5
  314. package/dist/core/ingestion/languages/ruby/query.js +93 -0
  315. package/dist/core/ingestion/languages/ruby/scope-resolver.js +2 -0
  316. package/dist/core/ingestion/languages/ruby/simple-hooks.d.ts +1 -1
  317. package/dist/core/ingestion/languages/ruby/simple-hooks.js +22 -1
  318. package/dist/core/ingestion/languages/rust/captures.js +39 -1
  319. package/dist/core/ingestion/languages/rust/method-owners.js +11 -1
  320. package/dist/core/ingestion/languages/rust/module-path.d.ts +126 -0
  321. package/dist/core/ingestion/languages/rust/module-path.js +214 -0
  322. package/dist/core/ingestion/languages/rust/qualified-call.d.ts +41 -0
  323. package/dist/core/ingestion/languages/rust/qualified-call.js +481 -0
  324. package/dist/core/ingestion/languages/rust/query.js +39 -6
  325. package/dist/core/ingestion/languages/rust/scope-resolver.js +21 -2
  326. package/dist/core/ingestion/languages/rust.js +17 -0
  327. package/dist/core/ingestion/languages/swift/captures.js +87 -3
  328. package/dist/core/ingestion/languages/swift/conditional-directive-preprocess.d.ts +48 -0
  329. package/dist/core/ingestion/languages/swift/conditional-directive-preprocess.js +253 -0
  330. package/dist/core/ingestion/languages/swift/import-target.js +4 -9
  331. package/dist/core/ingestion/languages/swift/query.js +17 -0
  332. package/dist/core/ingestion/languages/swift/receiver-binding.d.ts +8 -0
  333. package/dist/core/ingestion/languages/swift/receiver-binding.js +6 -2
  334. package/dist/core/ingestion/languages/swift.js +2 -0
  335. package/dist/core/ingestion/languages/typescript/captures.d.ts +90 -1
  336. package/dist/core/ingestion/languages/typescript/captures.js +267 -5
  337. package/dist/core/ingestion/languages/typescript/cjs-export-assignment.d.ts +134 -0
  338. package/dist/core/ingestion/languages/typescript/cjs-export-assignment.js +523 -0
  339. package/dist/core/ingestion/languages/typescript/cjs-module-exports.d.ts +54 -0
  340. package/dist/core/ingestion/languages/typescript/cjs-module-exports.js +191 -0
  341. package/dist/core/ingestion/languages/typescript/convex-endpoint-metadata.d.ts +7 -0
  342. package/dist/core/ingestion/languages/typescript/convex-endpoint-metadata.js +92 -0
  343. package/dist/core/ingestion/languages/typescript/file-candidates.d.ts +29 -0
  344. package/dist/core/ingestion/languages/typescript/file-candidates.js +70 -0
  345. package/dist/core/ingestion/languages/typescript/import-decomposer.d.ts +28 -1
  346. package/dist/core/ingestion/languages/typescript/import-decomposer.js +125 -10
  347. package/dist/core/ingestion/languages/typescript/import-target.d.ts +25 -37
  348. package/dist/core/ingestion/languages/typescript/import-target.js +24 -26
  349. package/dist/core/ingestion/languages/typescript/interpret.d.ts +21 -1
  350. package/dist/core/ingestion/languages/typescript/interpret.js +45 -5
  351. package/dist/core/ingestion/languages/typescript/module-resolution.d.ts +48 -0
  352. package/dist/core/ingestion/languages/typescript/module-resolution.js +171 -0
  353. package/dist/core/ingestion/languages/typescript/query.d.ts +1 -0
  354. package/dist/core/ingestion/languages/typescript/query.js +303 -14
  355. package/dist/core/ingestion/languages/typescript/receiver-binding.d.ts +17 -0
  356. package/dist/core/ingestion/languages/typescript/receiver-binding.js +27 -0
  357. package/dist/core/ingestion/languages/typescript/scope-resolver.js +27 -40
  358. package/dist/core/ingestion/languages/typescript/simple-hooks.d.ts +0 -10
  359. package/dist/core/ingestion/languages/typescript/simple-hooks.js +22 -22
  360. package/dist/core/ingestion/languages/typescript/tsconfig.d.ts +59 -0
  361. package/dist/core/ingestion/languages/typescript/tsconfig.js +292 -0
  362. package/dist/core/ingestion/languages/typescript.js +93 -2
  363. package/dist/core/ingestion/languages/vue/import-target.d.ts +6 -22
  364. package/dist/core/ingestion/languages/vue/import-target.js +11 -47
  365. package/dist/core/ingestion/languages/vue/scope-resolver.js +4 -2
  366. package/dist/core/ingestion/local-symbol-pruner.js +11 -11
  367. package/dist/core/ingestion/method-extractors/configs/csharp.js +1 -0
  368. package/dist/core/ingestion/method-extractors/generic.js +1 -0
  369. package/dist/core/ingestion/method-types.d.ts +16 -0
  370. package/dist/core/ingestion/pipeline-phases/di.d.ts +1 -1
  371. package/dist/core/ingestion/pipeline-phases/di.js +136 -21
  372. package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
  373. package/dist/core/ingestion/pipeline-phases/index.js +2 -0
  374. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +15 -0
  375. package/dist/core/ingestion/pipeline-phases/parse-impl.js +154 -4
  376. package/dist/core/ingestion/pipeline-phases/parse.js +5 -0
  377. package/dist/core/ingestion/pipeline-phases/processes.d.ts +3 -2
  378. package/dist/core/ingestion/pipeline-phases/processes.js +91 -6
  379. package/dist/core/ingestion/pipeline-phases/routes.js +116 -25
  380. package/dist/core/ingestion/pipeline-phases/spring-aop.d.ts +34 -0
  381. package/dist/core/ingestion/pipeline-phases/spring-aop.js +439 -0
  382. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +34 -0
  383. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +255 -0
  384. package/dist/core/ingestion/pipeline-phases/types.d.ts +7 -0
  385. package/dist/core/ingestion/pipeline.d.ts +26 -2
  386. package/dist/core/ingestion/pipeline.js +60 -11
  387. package/dist/core/ingestion/process-processor.d.ts +109 -2
  388. package/dist/core/ingestion/process-processor.js +464 -52
  389. package/dist/core/ingestion/resolve-references.d.ts +6 -1
  390. package/dist/core/ingestion/resolve-references.js +66 -6
  391. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +8 -2
  392. package/dist/core/ingestion/route-extractors/constant-resolver.js +11 -7
  393. package/dist/core/ingestion/route-extractors/data-route-table.d.ts +40 -0
  394. package/dist/core/ingestion/route-extractors/data-route-table.js +876 -0
  395. package/dist/core/ingestion/route-extractors/dispatch-guard.d.ts +96 -0
  396. package/dist/core/ingestion/route-extractors/dispatch-guard.js +1184 -0
  397. package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +114 -0
  398. package/dist/core/ingestion/route-extractors/java-const-resolver.js +569 -0
  399. package/dist/core/ingestion/route-extractors/js-const-resolver.d.ts +192 -0
  400. package/dist/core/ingestion/route-extractors/js-const-resolver.js +1033 -0
  401. package/dist/core/ingestion/route-extractors/nest.d.ts +53 -0
  402. package/dist/core/ingestion/route-extractors/nest.js +523 -0
  403. package/dist/core/ingestion/route-extractors/spring-shared.d.ts +11 -0
  404. package/dist/core/ingestion/route-extractors/spring-shared.js +89 -0
  405. package/dist/core/ingestion/route-extractors/spring.js +214 -29
  406. package/dist/core/ingestion/scope-extractor-bridge.js +9 -1
  407. package/dist/core/ingestion/scope-extractor.d.ts +22 -7
  408. package/dist/core/ingestion/scope-extractor.js +309 -15
  409. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +311 -21
  410. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +16 -5
  411. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -0
  412. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +47 -0
  413. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +20 -15
  414. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +280 -42
  415. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.d.ts +123 -0
  416. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +171 -17
  417. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.d.ts +58 -1
  418. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +137 -34
  419. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +30 -1
  420. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +39 -1
  421. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +18 -1
  422. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +113 -18
  423. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +107 -5
  424. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +590 -33
  425. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +3 -0
  426. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +101 -41
  427. package/dist/core/ingestion/scope-resolution/passes/imported-value-refs.d.ts +34 -0
  428. package/dist/core/ingestion/scope-resolution/passes/imported-value-refs.js +62 -0
  429. package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +5 -1
  430. package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +8 -1
  431. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +105 -5
  432. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +931 -92
  433. package/dist/core/ingestion/scope-resolution/passes/return-shape-members.d.ts +58 -0
  434. package/dist/core/ingestion/scope-resolution/passes/return-shape-members.js +458 -0
  435. package/dist/core/ingestion/scope-resolution/passes/unique-name-properties.d.ts +180 -0
  436. package/dist/core/ingestion/scope-resolution/passes/unique-name-properties.js +418 -0
  437. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +29 -0
  438. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +57 -0
  439. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +55 -1
  440. package/dist/core/ingestion/scope-resolution/pipeline/run.js +241 -19
  441. package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +112 -2
  442. package/dist/core/ingestion/scope-resolution/resolution-outcome.js +38 -1
  443. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +25 -3
  444. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +36 -16
  445. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +210 -9
  446. package/dist/core/ingestion/scope-resolution/scope/walkers.js +905 -22
  447. package/dist/core/ingestion/scope-resolution/summary-maps.d.ts +28 -0
  448. package/dist/core/ingestion/scope-resolution/summary-maps.js +50 -0
  449. package/dist/core/ingestion/scope-resolution/undecided-satisfaction.d.ts +55 -0
  450. package/dist/core/ingestion/scope-resolution/undecided-satisfaction.js +37 -0
  451. package/dist/core/ingestion/scope-resolution/unresolved-receivers.d.ts +109 -0
  452. package/dist/core/ingestion/scope-resolution/unresolved-receivers.js +204 -0
  453. package/dist/core/ingestion/scope-resolution/utils/definition-id.d.ts +13 -0
  454. package/dist/core/ingestion/scope-resolution/utils/definition-id.js +19 -0
  455. package/dist/core/ingestion/scope-resolution/utils/generic-instantiation.d.ts +171 -0
  456. package/dist/core/ingestion/scope-resolution/utils/generic-instantiation.js +218 -0
  457. package/dist/core/ingestion/scope-resolution/workspace-index-types.d.ts +34 -0
  458. package/dist/core/ingestion/scope-resolution/workspace-index-types.js +15 -0
  459. package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +7 -20
  460. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  461. package/dist/core/ingestion/tree-sitter-queries.js +678 -4
  462. package/dist/core/ingestion/type-env.js +11 -7
  463. package/dist/core/ingestion/type-extractors/shared.d.ts +17 -0
  464. package/dist/core/ingestion/type-extractors/shared.js +16 -0
  465. package/dist/core/ingestion/type-extractors/types.d.ts +12 -0
  466. package/dist/core/ingestion/type-extractors/typescript.d.ts +20 -0
  467. package/dist/core/ingestion/type-extractors/typescript.js +26 -0
  468. package/dist/core/ingestion/utils/ast-helpers.d.ts +297 -15
  469. package/dist/core/ingestion/utils/ast-helpers.js +578 -46
  470. package/dist/core/ingestion/utils/call-analysis.d.ts +27 -22
  471. package/dist/core/ingestion/utils/call-analysis.js +202 -7
  472. package/dist/core/ingestion/utils/callable-flow-captures.d.ts +59 -0
  473. package/dist/core/ingestion/utils/callable-flow-captures.js +51 -1
  474. package/dist/core/ingestion/utils/callable-labels.d.ts +25 -0
  475. package/dist/core/ingestion/utils/callable-labels.js +31 -0
  476. package/dist/core/ingestion/utils/effective-ram.d.ts +40 -0
  477. package/dist/core/ingestion/utils/effective-ram.js +58 -0
  478. package/dist/core/ingestion/utils/line-base.d.ts +14 -0
  479. package/dist/core/ingestion/utils/line-base.js +14 -0
  480. package/dist/core/ingestion/utils/method-props.d.ts +27 -4
  481. package/dist/core/ingestion/utils/method-props.js +29 -4
  482. package/dist/core/ingestion/utils/receiver-chain-captures.d.ts +31 -0
  483. package/dist/core/ingestion/utils/receiver-chain-captures.js +57 -0
  484. package/dist/core/ingestion/utils/receiver-chain-codec.d.ts +89 -0
  485. package/dist/core/ingestion/utils/receiver-chain-codec.js +182 -0
  486. package/dist/core/ingestion/utils/scope-tree-walk.d.ts +22 -0
  487. package/dist/core/ingestion/utils/scope-tree-walk.js +33 -0
  488. package/dist/core/ingestion/utils/template-arguments.d.ts +96 -0
  489. package/dist/core/ingestion/utils/template-arguments.js +196 -0
  490. package/dist/core/ingestion/utils/type-parameters.d.ts +49 -0
  491. package/dist/core/ingestion/utils/type-parameters.js +206 -0
  492. package/dist/core/ingestion/workers/callable-id.d.ts +80 -0
  493. package/dist/core/ingestion/workers/callable-id.js +125 -0
  494. package/dist/core/ingestion/workers/parse-worker.d.ts +14 -1
  495. package/dist/core/ingestion/workers/parse-worker.js +493 -54
  496. package/dist/core/ingestion/workers/worker-pool.d.ts +20 -27
  497. package/dist/core/ingestion/workers/worker-pool.js +91 -3
  498. package/dist/core/lbug/csv-generator.d.ts +27 -0
  499. package/dist/core/lbug/csv-generator.js +72 -17
  500. package/dist/core/lbug/extension-load-error.js +13 -2
  501. package/dist/core/lbug/extension-loader.d.ts +29 -0
  502. package/dist/core/lbug/extension-loader.js +31 -6
  503. package/dist/core/lbug/graph-emit-sink.d.ts +264 -0
  504. package/dist/core/lbug/graph-emit-sink.js +581 -0
  505. package/dist/core/lbug/lbug-adapter.d.ts +290 -11
  506. package/dist/core/lbug/lbug-adapter.js +652 -69
  507. package/dist/core/lbug/native-check.d.ts +21 -0
  508. package/dist/core/lbug/native-check.js +248 -32
  509. package/dist/core/lbug/pdg-emit-sink.d.ts +13 -4
  510. package/dist/core/lbug/pdg-emit-sink.js +21 -111
  511. package/dist/core/lbug/pool-adapter.d.ts +9 -0
  512. package/dist/core/lbug/pool-adapter.js +164 -14
  513. package/dist/core/lbug/query-batch.d.ts +75 -0
  514. package/dist/core/lbug/query-batch.js +102 -0
  515. package/dist/core/lbug/rel-pair-routing.d.ts +160 -2
  516. package/dist/core/lbug/rel-pair-routing.js +228 -10
  517. package/dist/core/lbug/schema.d.ts +163 -4
  518. package/dist/core/lbug/schema.js +404 -159
  519. package/dist/core/lbug/sync-csv-writer.d.ts +47 -0
  520. package/dist/core/lbug/sync-csv-writer.js +108 -0
  521. package/dist/core/run-analyze.d.ts +147 -0
  522. package/dist/core/run-analyze.js +1215 -179
  523. package/dist/core/search/bm25-index.d.ts +11 -0
  524. package/dist/core/search/bm25-index.js +60 -26
  525. package/dist/core/search/fts-indexes.d.ts +150 -9
  526. package/dist/core/search/fts-indexes.js +241 -23
  527. package/dist/core/wiki/graph-queries.js +145 -112
  528. package/dist/core/wiki/llm-client.d.ts +29 -3
  529. package/dist/core/wiki/llm-client.js +47 -12
  530. package/dist/core/wiki/prompts.d.ts +19 -0
  531. package/dist/core/wiki/prompts.js +20 -1
  532. package/dist/lib/utils.d.ts +113 -0
  533. package/dist/lib/utils.js +185 -0
  534. package/dist/mcp/local/aop-metadata.d.ts +77 -0
  535. package/dist/mcp/local/aop-metadata.js +227 -0
  536. package/dist/mcp/local/bean-metadata.d.ts +2 -1
  537. package/dist/mcp/local/bean-metadata.js +22 -1
  538. package/dist/mcp/local/convex-metadata.d.ts +8 -0
  539. package/dist/mcp/local/convex-metadata.js +45 -0
  540. package/dist/mcp/local/local-backend.d.ts +174 -11
  541. package/dist/mcp/local/local-backend.js +1678 -331
  542. package/dist/mcp/local/path-predicate.d.ts +19 -0
  543. package/dist/mcp/local/path-predicate.js +21 -0
  544. package/dist/mcp/local/pdg-impact.d.ts +132 -10
  545. package/dist/mcp/local/pdg-impact.js +391 -98
  546. package/dist/mcp/repository-policy.d.ts +1 -0
  547. package/dist/mcp/repository-policy.js +5 -0
  548. package/dist/mcp/resources.js +26 -4
  549. package/dist/mcp/server.js +23 -13
  550. package/dist/mcp/tools.d.ts +8 -0
  551. package/dist/mcp/tools.js +76 -23
  552. package/dist/server/analyze-job.d.ts +37 -2
  553. package/dist/server/analyze-job.js +13 -2
  554. package/dist/server/analyze-launch.d.ts +1 -1
  555. package/dist/server/analyze-launch.js +79 -10
  556. package/dist/server/analyze-worker-core.d.ts +1 -1
  557. package/dist/server/analyze-worker-core.js +10 -1
  558. package/dist/server/analyze-worker-ipc.d.ts +1 -1
  559. package/dist/server/analyze-worker-ipc.js +4 -0
  560. package/dist/server/analyze-worker-protocol.d.ts +59 -0
  561. package/dist/server/analyze-worker-protocol.js +1 -0
  562. package/dist/server/analyze-worker.d.ts +1 -17
  563. package/dist/server/api.d.ts +2 -11
  564. package/dist/server/api.js +164 -163
  565. package/dist/server/embed-run-outcome.d.ts +89 -0
  566. package/dist/server/embed-run-outcome.js +88 -0
  567. package/dist/server/git-clone.js +6 -2
  568. package/dist/server/middleware.d.ts +116 -9
  569. package/dist/server/middleware.js +291 -22
  570. package/dist/server/sse-progress.d.ts +41 -0
  571. package/dist/server/sse-progress.js +125 -0
  572. package/dist/storage/branch-index.d.ts +11 -6
  573. package/dist/storage/branch-index.js +15 -7
  574. package/dist/storage/file-hash.js +2 -2
  575. package/dist/storage/fs-atomic.d.ts +25 -0
  576. package/dist/storage/fs-atomic.js +42 -0
  577. package/dist/storage/git.d.ts +131 -0
  578. package/dist/storage/git.js +236 -2
  579. package/dist/storage/index-lock.d.ts +102 -0
  580. package/dist/storage/index-lock.js +660 -0
  581. package/dist/storage/parse-cache.js +588 -6
  582. package/dist/storage/parsedfile-store.js +76 -6
  583. package/dist/storage/repo-manager.d.ts +54 -441
  584. package/dist/storage/repo-manager.js +312 -221
  585. package/dist/storage/repo-meta.d.ts +530 -0
  586. package/dist/storage/repo-meta.js +100 -0
  587. package/dist/types/pipeline.d.ts +37 -0
  588. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +1 -1
  589. package/hooks/claude/gitnexus-hook.cjs +1 -1
  590. package/hooks/claude/resolve-analyze-cmd.cjs +80 -13
  591. package/package.json +11 -2
  592. package/scripts/cross-platform-shard.ts +153 -0
  593. package/scripts/cross-platform-tests.ts +122 -0
  594. package/scripts/run-cross-platform.ts +16 -5
  595. package/skills/gitnexus-cli.md +3 -3
  596. package/skills/gitnexus-debugging.md +37 -7
  597. package/skills/gitnexus-exploring.md +26 -4
  598. package/skills/gitnexus-impact-analysis.md +71 -10
  599. package/skills/gitnexus-plan/README.md +11 -6
  600. package/skills/gitnexus-plan/references/evidence-provenance.md +49 -12
  601. package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +654 -372
  602. package/skills/gitnexus-refactoring.md +48 -5
  603. package/skills/gitnexus-review/SKILL.md +12 -6
  604. package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +1 -1
  605. package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +1 -1
  606. package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +1 -1
  607. package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +1 -1
  608. package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +1 -1
  609. package/skills/gitnexus-review/ci-personas/ci-security-lens.md +1 -1
  610. package/skills/gitnexus-taint-analysis.md +13 -7
  611. package/skills/gitnexus-work/SKILL.md +4 -1
  612. package/skills/gitnexus-work/references/evidence-provenance.md +49 -12
  613. package/skills/gitnexus-work/scripts/evidence-provenance.mjs +654 -372
  614. package/vendor/leiden/utils.cjs +28 -1
  615. package/web/assets/ProcessFlowModal-Badh2Pbg.js +24 -0
  616. package/web/assets/{__vite-browser-external-bMKyYQkO.js → __vite-browser-external-COxE8F0G.js} +1 -1
  617. package/web/assets/abnfDiagram-QNN2D4NM-Cq2djWWe.js +1 -0
  618. package/web/assets/agent-Dr4l5EOp.js +662 -0
  619. package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +1 -0
  620. package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +36 -0
  621. package/web/assets/{blockDiagram-7IZFK4PR-DBefcjof.js → blockDiagram-54WLDVWM-Dg_hrRWE.js} +4 -4
  622. package/web/assets/{c4Diagram-Y2BXMSZH-EjWnjEJl.js → c4Diagram-X2LASM7V-CnhoT4aV.js} +2 -2
  623. package/web/assets/chunk-224SPVON-B8gxtXpy.js +1 -0
  624. package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +127 -0
  625. package/web/assets/chunk-2SREHG4O-Dip42xOq.js +1 -0
  626. package/web/assets/chunk-4RFN2BYJ-DHHWuC-n.js +1 -0
  627. package/web/assets/chunk-66DQ2XMT-CM0xjFAN.js +1 -0
  628. package/web/assets/chunk-6BELYETK-ChsYtfHW.js +1 -0
  629. package/web/assets/{chunk-LII3EMHJ-BL6lKJ_P.js → chunk-6L755F7B-CMhLBxi2.js} +1 -1
  630. package/web/assets/{chunk-QA3QBVWF-DVXPOIxe.js → chunk-7CWYLC5S-DRgGkkpF.js} +1 -1
  631. package/web/assets/{chunk-ZXARS5L4-C3v-4Fsw.js → chunk-A7VWPJGB-B4O3oQdQ.js} +1 -1
  632. package/web/assets/chunk-BI6VK774-D0oaWk8V.js +1 -0
  633. package/web/assets/chunk-D6VWDJW2-BxcBdZ9c.js +2 -0
  634. package/web/assets/chunk-DMV4VAQV-Bn6WXDSX.js +4 -0
  635. package/web/assets/chunk-E5QJAATJ-dh-5CtIV.js +2 -0
  636. package/web/assets/chunk-EQFTRU2I-1ix7TzW9.js +2 -0
  637. package/web/assets/chunk-FWYVLQTC-BgDItRzJ.js +1 -0
  638. package/web/assets/chunk-HNC4WDU7-DoU3KnA7.js +1 -0
  639. package/web/assets/chunk-L5GCOVLC-CE2w8Nm_.js +161 -0
  640. package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +321 -0
  641. package/web/assets/chunk-LORZLZWG-B57uGw2N.js +88 -0
  642. package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +62 -0
  643. package/web/assets/chunk-NV3KIAZN-5yvcpMiu.js +1 -0
  644. package/web/assets/chunk-OIYT25JQ-CQ6KOZGX.js +1 -0
  645. package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +10 -0
  646. package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +156 -0
  647. package/web/assets/chunk-RRFMTAIC-CMN0wcYA.js +1 -0
  648. package/web/assets/{chunk-RLI5ZMPA-CkXZ0y0U.js → chunk-SATU7PGQ-B1zhgOvc.js} +1 -1
  649. package/web/assets/chunk-STOV2HOB-GnExfzIX.js +1 -0
  650. package/web/assets/{chunk-INKRHTLW-Ckl3_KkO.js → chunk-SZD42YQK-ijyKKVr1.js} +21 -21
  651. package/web/assets/{chunk-LCXTWHL2-C162wE5z.js → chunk-TFPGFQPA-Dj6a-0pC.js} +3 -3
  652. package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +2 -0
  653. package/web/assets/chunk-TZUXEDM2-B7p9AcTw.js +1 -0
  654. package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +1 -0
  655. package/web/assets/{chunk-6764PJDD-C7xxk063.js → chunk-VE5CLXGZ-C1vB7wpY.js} +1 -1
  656. package/web/assets/{chunk-RG4AUYOV-ZNgyLFq6.js → chunk-VJFVEZTB-CX66F2ep.js} +3 -3
  657. package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +1 -0
  658. package/web/assets/chunk-WJBAP47W-BckNkuEN.js +1 -0
  659. package/web/assets/chunk-XNMVGMAZ-Cg_LnPtj.js +1 -0
  660. package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +1 -0
  661. package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +1 -0
  662. package/web/assets/{cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js → cose-bilkent-RZA4XIPR-BHpK4Crp.js} +1 -1
  663. package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +1 -0
  664. package/web/assets/cynefinDiagram-TR7LZUCG-C3Iar9lZ.js +62 -0
  665. package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +4 -0
  666. package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +30 -0
  667. package/web/assets/diagram-JCD7PQ7C-DC5-9FRr.js +24 -0
  668. package/web/assets/{diagram-HNR7UZ2L-DVRltWbL.js → diagram-KFBZAVDW-Dfmf_4ti.js} +3 -3
  669. package/web/assets/diagram-L7DVE3PN-GIRyVUtt.js +41 -0
  670. package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +24 -0
  671. package/web/assets/ebnfDiagram-DRHRQJWO-D8_CI4ZF.js +1 -0
  672. package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +85 -0
  673. package/web/assets/error-D9MtuG9s.js +1 -0
  674. package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +1 -0
  675. package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +1 -0
  676. package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +292 -0
  677. package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +1 -0
  678. package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +106 -0
  679. package/web/assets/{index-D7mTFcvQ.js → index-2zdvEdzg.js} +51 -51
  680. package/web/assets/index-CJDpyH-n.css +2 -0
  681. package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +1 -0
  682. package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +2 -0
  683. package/web/assets/{ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js → ishikawaDiagram-4JDSWWDM-DmqWtjkl.js} +2 -2
  684. package/web/assets/{journeyDiagram-M6C3CM3L-C6wjooas.js → journeyDiagram-QUS3FAKT-XAzVzrQW.js} +3 -3
  685. package/web/assets/{kanban-definition-75IXJCU3-5_UVY79g.js → kanban-definition-D4L7SQKK-YurRnmYn.js} +6 -6
  686. package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +257 -0
  687. package/web/assets/{mindmap-definition-2TDM6QVE-8xDLzk2e.js → mindmap-definition-66QP5TD6-ChrWWnil.js} +5 -5
  688. package/web/assets/node.browser-U-KyT5AW.js +1 -0
  689. package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +1 -0
  690. package/web/assets/pegDiagram-YKIO5C6U-QGeQLEq2.js +1 -0
  691. package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +1 -0
  692. package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +39 -0
  693. package/web/assets/{quadrantDiagram-VICAPDV7-DR54jOeR.js → quadrantDiagram-VO5QLCXA-B7098wSc.js} +3 -3
  694. package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +1 -0
  695. package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +1 -0
  696. package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +1 -0
  697. package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +1 -0
  698. package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +1 -0
  699. package/web/assets/railroadDiagram-M77LTMSB-AXu4vxk_.js +1 -0
  700. package/web/assets/{requirementDiagram-JXO7QTGE-PEkg7sKC.js → requirementDiagram-RASO5HTO-B-l8InpK.js} +4 -4
  701. package/web/assets/{sankeyDiagram-URQDO5SZ-DDWEtjcs.js → sankeyDiagram-F32LOJ6L-Kd7zjJgX.js} +3 -3
  702. package/web/assets/{sequenceDiagram-VS2MUI6T-Bv-uwANx.js → sequenceDiagram-URATNSBD-BlcdY9DS.js} +7 -7
  703. package/web/assets/sizeCapture-5GORAGP4-BEqQzsxs.js +1 -0
  704. package/web/assets/src-C5sx_gMp.js +1 -0
  705. package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +1 -0
  706. package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +1 -0
  707. package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +2 -0
  708. package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +8 -0
  709. package/web/assets/{timeline-definition-O6YCAMPW-Qmsuo7qS.js → timeline-definition-WJXWRH4I-DUfp1R3E.js} +3 -3
  710. package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +1 -0
  711. package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +1 -0
  712. package/web/assets/vennDiagram-K3VCMQLI-Bj-FN-XS.js +34 -0
  713. package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +1 -0
  714. package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +78 -0
  715. package/web/assets/xychartDiagram-5VRUVLCW-CK_rbSWE.js +7 -0
  716. package/web/index.html +16 -15
  717. package/dist/core/ingestion/languages/python/index-stats.d.ts +0 -18
  718. package/dist/core/ingestion/languages/python/index-stats.js +0 -25
  719. package/web/assets/ProcessFlowModal-CwkpVkv-.js +0 -22
  720. package/web/assets/agent-Ds-lkZjX.js +0 -626
  721. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +0 -1
  722. package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +0 -36
  723. package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +0 -4
  724. package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +0 -1
  725. package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +0 -321
  726. package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +0 -159
  727. package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +0 -124
  728. package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +0 -10
  729. package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +0 -1
  730. package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +0 -1
  731. package/web/assets/chunk-J5EP6P6S-L19oz55R.js +0 -1
  732. package/web/assets/chunk-KGFNY3KK-BZeP-55u.js +0 -62
  733. package/web/assets/chunk-KGYTTC2M-zm6n242I.js +0 -1
  734. package/web/assets/chunk-KNLZD3CH-BGlP6X9R.js +0 -1
  735. package/web/assets/chunk-LRIF4GLE-n59lhprL.js +0 -1
  736. package/web/assets/chunk-RERM46MO-B5dAdWpP.js +0 -1
  737. package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +0 -1
  738. package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +0 -1
  739. package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +0 -1
  740. package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +0 -1
  741. package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +0 -1
  742. package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +0 -2
  743. package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +0 -1
  744. package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +0 -1
  745. package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +0 -4
  746. package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +0 -43
  747. package/web/assets/diagram-GF46GFSD-B2atbzmU.js +0 -24
  748. package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +0 -24
  749. package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +0 -10
  750. package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +0 -85
  751. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +0 -1
  752. package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +0 -162
  753. package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +0 -292
  754. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +0 -1
  755. package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +0 -106
  756. package/web/assets/index-CX_fADmQ.css +0 -2
  757. package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +0 -1
  758. package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +0 -2
  759. package/web/assets/katex-K3KEBU37-qRQBy-EZ.js +0 -261
  760. package/web/assets/node-Ct_zna8U.js +0 -8
  761. package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +0 -1
  762. package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +0 -1
  763. package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +0 -30
  764. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +0 -1
  765. package/web/assets/sdk-CzHHH8tD.js +0 -37
  766. package/web/assets/src-Cv1eWg0o.js +0 -1
  767. package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +0 -1
  768. package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +0 -1
  769. package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +0 -1
  770. package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +0 -1
  771. package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +0 -34
  772. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +0 -1
  773. package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +0 -78
  774. package/web/assets/xychartDiagram-N2JHSOCM-CoZ_Tits.js +0 -7
  775. /package/web/assets/{chunk-7W6UQGC5-pyKGssV3.js → chunk-LIEV3EAG-pyKGssV3.js} +0 -0
@@ -1,5 +1,7 @@
1
1
  import { simpleQualifiedName } from '../../scope-resolution/graph-bridge/ids.js';
2
2
  import { resolveInheritanceBaseInScope } from '../../scope-resolution/scope/walkers.js';
3
+ import { goPackageDir } from './package-clause.js';
4
+ import { matchingGoDelimiter, readGoTypeParameters, splitTopLevelGoList, } from './generic-type-parameters.js';
3
5
  export function detectGoInterfaceImplementations(parsedFiles, _indexes, _model) {
4
6
  return detectGoInterfaceImplementationsFromIndexes(buildDetectionIndexes(parsedFiles, _indexes));
5
7
  }
@@ -12,17 +14,25 @@ function buildDetectionIndexes(parsedFiles, indexes) {
12
14
  const interfaceOwnMethodsById = new Map();
13
15
  const embeddedSitesByInterfaceId = new Map();
14
16
  const parentStructIdsByStructId = new Map();
17
+ const valueMethodsByStructId = new Map();
15
18
  const structIdsByMethodName = new Map();
16
19
  const signatureContextByDefId = new Map();
17
20
  const interfaceIdByScopeId = new Map();
18
21
  const structIdByScopeId = new Map();
22
+ const typeParametersByInterfaceId = new Map();
23
+ const signatureContextByFilePath = new Map();
19
24
  for (const parsed of parsedFiles) {
20
25
  const signatureContext = signatureContextForFile(parsed, indexes);
26
+ signatureContextByFilePath.set(parsed.filePath, signatureContext);
21
27
  for (const def of parsed.localDefs) {
22
28
  signatureContextByDefId.set(def.nodeId, signatureContext);
23
29
  if (def.type === 'Interface') {
24
30
  interfaces.push(def);
25
31
  interfaceById.set(def.nodeId, def);
32
+ const typeParameters = readGoTypeParameters(def);
33
+ if (typeParameters !== undefined) {
34
+ typeParametersByInterfaceId.set(def.nodeId, typeParameters);
35
+ }
26
36
  continue;
27
37
  }
28
38
  if (def.type === 'Struct') {
@@ -33,14 +43,51 @@ function buildDetectionIndexes(parsedFiles, indexes) {
33
43
  continue;
34
44
  if (def.ownerId === undefined)
35
45
  continue;
36
- if (isPointerReceiverMethod(def))
37
- continue;
38
- const methodName = simpleQualifiedName(def);
39
- if (methodName === undefined || methodName.length === 0)
46
+ // POINTER-receiver methods count toward the method set (#2813).
47
+ //
48
+ // Go's rule is per-type, and there are two types here: the method set of
49
+ // `T` holds only its value-receiver methods, while the method set of `*T`
50
+ // holds BOTH. #1966 kept only the value-receiver half, which makes the
51
+ // `T` answer exactly right — and the `*T` answer permanently empty, so a
52
+ // struct whose methods all read `func (r *T)` satisfied nothing and got
53
+ // no IMPLEMENTS edge at all.
54
+ //
55
+ // That is the shape idiomatic Go actually writes: methods take pointer
56
+ // receivers so they can mutate, and `*T` is what gets stored in an
57
+ // interface-typed field. Excluding it did not make the graph
58
+ // conservative, it made it silent — every call through such a field
59
+ // resolved to the interface DECLARATION and `impact()` on the
60
+ // implementation reported zero callers, indistinguishable from a symbol
61
+ // that genuinely has none.
62
+ //
63
+ // GitNexus models one Struct node per type with no separate `*T` node, so
64
+ // the two method sets cannot both be represented. This picks the `*T`
65
+ // reading: the graph now answers "which types provide this interface's
66
+ // behaviour", and no longer proves `var x I = T{}` invalid. That trade is
67
+ // deliberate — blast radius is what every consumer of IMPLEMENTS asks for
68
+ // (verified: MRO/METHOD_IMPLEMENTS derivation, community clustering, the
69
+ // receiver-dispatch fan-out index, and the epistemic heritage probe; none
70
+ // performs value-assignability checking).
71
+ //
72
+ // `goReceiverKind` is still stamped in method-owners.ts and is the hook a
73
+ // future value/pointer-aware model would read; it is deliberately no
74
+ // longer a filter here.
75
+ const simpleName = simpleQualifiedName(def);
76
+ if (simpleName === undefined || simpleName.length === 0)
40
77
  continue;
41
- addMethod(methodsByOwner, def.ownerId, methodName, def);
78
+ addMethod(methodsByOwner, def.ownerId, methodSetKey(simpleName, def, signatureContextByDefId), def);
42
79
  }
43
80
  }
81
+ // Built from the nodeId-keyed map, so a def that appears in two ParsedFiles is
82
+ // one interface here just as it is one there — not a name collision with
83
+ // itself.
84
+ const interfacesByQualifiedName = new Map();
85
+ for (const iface of interfaceById.values()) {
86
+ const name = iface.qualifiedName;
87
+ if (name === undefined || name.length === 0)
88
+ continue;
89
+ interfacesByQualifiedName.set(name, interfacesByQualifiedName.has(name) ? null : iface);
90
+ }
44
91
  for (const parsed of parsedFiles) {
45
92
  for (const scope of parsed.scopes) {
46
93
  const iface = scope.ownedDefs.find((def) => def.type === 'Interface');
@@ -69,10 +116,12 @@ function buildDetectionIndexes(parsedFiles, indexes) {
69
116
  for (const def of childScope.ownedDefs) {
70
117
  if (def.type !== 'Method' && def.type !== 'Function')
71
118
  continue;
72
- const methodName = simpleQualifiedName(def);
73
- if (methodName === undefined || methodName.length === 0)
119
+ const simpleName = simpleQualifiedName(def);
120
+ if (simpleName === undefined || simpleName.length === 0)
74
121
  continue;
75
- addMethodOverload(methods, methodName, def);
122
+ // Same key function as the struct side — an interface requiring an
123
+ // unexported `seal()` must only be satisfied from its own package.
124
+ addMethodOverload(methods, methodSetKey(simpleName, def, signatureContextByDefId), def);
76
125
  }
77
126
  }
78
127
  interfaceOwnMethodsById.set(ifaceId, methods);
@@ -93,19 +142,24 @@ function buildDetectionIndexes(parsedFiles, indexes) {
93
142
  const parent = resolveInheritanceBaseInScope(site.inScope, site.name, indexes);
94
143
  if (parent === undefined || parent.type !== 'Struct')
95
144
  continue;
96
- addParentStruct(parentStructIdsByStructId, structId, parent.nodeId);
145
+ // `embeddedAsPointer` is the capture-layer record of `*T` vs `T`; the two
146
+ // promote different method sets (go.dev/ref/spec#Struct_types).
147
+ addParentStruct(parentStructIdsByStructId, structId, parent.nodeId, site.embeddedAsPointer === true);
97
148
  }
98
149
  }
99
150
  const structMethodSetCache = new Map();
100
151
  for (const structId of structsById.keys()) {
101
- const effective = collectStructMethodSet(structId, {
152
+ const dual = collectStructMethodSet(structId, {
102
153
  parentStructIdsByStructId,
103
154
  methodsByOwner,
104
155
  }, new Set(), structMethodSetCache);
105
- if (effective === undefined)
156
+ if (dual === undefined)
106
157
  continue;
107
- effectiveMethodsByStructId.set(structId, effective);
108
- for (const methodName of effective.keys()) {
158
+ // `pointer` is MS(*T) and is the superset, so it drives candidate lookup:
159
+ // a type that implements only in pointer form is still an implementor.
160
+ effectiveMethodsByStructId.set(structId, dual.pointer);
161
+ valueMethodsByStructId.set(structId, dual.value);
162
+ for (const methodName of dual.pointer.keys()) {
109
163
  addStructMethodCandidate(structIdsByMethodName, methodName, structId);
110
164
  }
111
165
  }
@@ -114,17 +168,185 @@ function buildDetectionIndexes(parsedFiles, indexes) {
114
168
  structsById,
115
169
  methodsByOwner,
116
170
  effectiveMethodsByStructId,
117
- interfaceById,
171
+ interfacesByQualifiedName,
118
172
  interfaceOwnMethodsById,
119
173
  embeddedSitesByInterfaceId,
120
174
  parentStructIdsByStructId,
121
175
  structIdsByMethodName,
176
+ valueMethodsByStructId,
122
177
  signatureContextByDefId,
178
+ typeParametersByInterfaceId,
179
+ // Gated on the repo declaring at least one generic interface. A Go codebase
180
+ // with none — the overwhelming majority — never runs the harvest at all,
181
+ // which matters because the spellings it would scan (`[]byte`,
182
+ // `map[string]X`) are among the commonest types in the language.
183
+ instantiationsByInterfaceId: typeParametersByInterfaceId.size === 0
184
+ ? new Map()
185
+ : collectGoInstantiations(parsedFiles, signatureContextByFilePath, typeParametersByInterfaceId, interfacesByQualifiedName, indexes),
123
186
  scopeIndexes: indexes,
124
187
  };
125
188
  }
189
+ /**
190
+ * Every distinct instantiation of a generic interface written anywhere in the
191
+ * program, resolved and deduplicated in one pass.
192
+ *
193
+ * Go records no instantiation anywhere on the DECLARATION — `Repo[User]` exists
194
+ * only where it is written — so the sites are the field/parameter/variable type
195
+ * spellings the capture layer already preserved: `TypeRef.declaredSpelling`
196
+ * (which keeps the arguments `rawName` drops), and the def-side `declaredType` /
197
+ * `parameterTypes` / `returnType`.
198
+ *
199
+ * A spelling is scanned rather than parsed as a whole, so decorated and nested
200
+ * forms yield their inner instantiations too: `[]Repo[User]`, `*Repo[User]` and
201
+ * `map[string]Repo[User]` all yield `Repo[User]`, and `Outer[Repo[User]]` yields
202
+ * both — each of which really is an instantiation present in the program. False
203
+ * bases (`map[` scans as base `map`) resolve to no interface and drop out.
204
+ */
205
+ function collectGoInstantiations(parsedFiles, signatureContextByFilePath, typeParametersByInterfaceId, interfacesByQualifiedName, indexes) {
206
+ // One map where there were two on the same key: the inner map's KEY is the
207
+ // joined argument list, so holding it is the deduplication.
208
+ const argsByInterfaceId = new Map();
209
+ // A base name resolves once per scope. The bracket gate below cannot filter
210
+ // Go's commonest types — `map[string]string` scans as base `map` — so the
211
+ // FALSE bases dominate this pass, and each one otherwise re-walks the whole
212
+ // scope chain for a name that will never bind.
213
+ const basesInScope = new Map();
214
+ const resolveBase = (baseName, inScope) => {
215
+ // NUL-joined for the same reason `methodSetKey` is: it cannot occur in Go
216
+ // source, so no two (scope, name) pairs can collide on one key.
217
+ const key = `${inScope}\u0000${baseName}`;
218
+ const memo = basesInScope.get(key);
219
+ if (memo !== undefined)
220
+ return memo ?? undefined;
221
+ const iface = resolveGoInstantiationBase(baseName, inScope, interfacesByQualifiedName, indexes);
222
+ basesInScope.set(key, iface ?? null);
223
+ return iface;
224
+ };
225
+ const record = (spelling, inScope, context) => {
226
+ // Cheap gate first: most Go type spellings have no bracket at all, and the
227
+ // scan below is the only per-spelling cost this pass adds.
228
+ if (spelling === undefined || !spelling.includes('['))
229
+ return;
230
+ for (const { baseName, rawArgs } of parseGoInstantiationSpellings(spelling)) {
231
+ const iface = resolveBase(baseName, inScope);
232
+ if (iface === undefined)
233
+ continue;
234
+ const typeParameters = typeParametersByInterfaceId.get(iface.nodeId);
235
+ // A partial or over-long argument list is not a valid instantiation
236
+ // ("For a generic type, all type arguments must always be provided
237
+ // explicitly" — go.dev/ref/spec#Instantiations), so there is nothing to
238
+ // substitute and the site is dropped.
239
+ if (typeParameters === undefined || typeParameters.length !== rawArgs.length)
240
+ continue;
241
+ const normalizedArgs = normalizeGoTypeArguments(rawArgs, context);
242
+ if (normalizedArgs === undefined)
243
+ continue;
244
+ let byArgs = argsByInterfaceId.get(iface.nodeId);
245
+ if (byArgs === undefined) {
246
+ byArgs = new Map();
247
+ argsByInterfaceId.set(iface.nodeId, byArgs);
248
+ }
249
+ const key = normalizedArgs.join(',');
250
+ if (!byArgs.has(key))
251
+ byArgs.set(key, normalizedArgs);
252
+ }
253
+ };
254
+ for (const parsed of parsedFiles) {
255
+ const context = signatureContextByFilePath.get(parsed.filePath);
256
+ if (context === undefined)
257
+ continue;
258
+ for (const scope of parsed.scopes) {
259
+ for (const binding of scope.typeBindings.values()) {
260
+ record(binding.declaredSpelling ?? binding.rawName, scope.id, context);
261
+ }
262
+ for (const def of scope.ownedDefs) {
263
+ record(def.declaredType, scope.id, context);
264
+ record(def.returnType, scope.id, context);
265
+ for (const parameterType of def.parameterTypes ?? []) {
266
+ record(parameterType, scope.id, context);
267
+ }
268
+ }
269
+ }
270
+ }
271
+ return argsByInterfaceId;
272
+ }
273
+ /** Every `Ident[…]` / `pkg.Ident[…]` application in a type spelling, with its
274
+ * top-level (comma-separated, delimiter-balanced) arguments. */
275
+ function parseGoInstantiationSpellings(spelling) {
276
+ const out = [];
277
+ const namePattern = /[A-Za-z_][A-Za-z0-9_.]*(?=\[)/g;
278
+ let match;
279
+ while ((match = namePattern.exec(spelling)) !== null) {
280
+ const open = match.index + match[0].length;
281
+ const close = matchingGoDelimiter(spelling, open);
282
+ if (close === -1)
283
+ continue;
284
+ const rawArgs = splitTopLevelGoList(spelling.slice(open + 1, close));
285
+ if (rawArgs.length === 0)
286
+ continue;
287
+ out.push({ baseName: match[0], rawArgs });
288
+ }
289
+ return out;
290
+ }
291
+ /** Normalize each type argument in the context of the file that WROTE it, or
292
+ * `undefined` when any of them carries an unresolvable import qualifier — a
293
+ * half-normalized argument list would compare against nothing meaningful. */
294
+ function normalizeGoTypeArguments(rawArgs, context) {
295
+ const normalizedArgs = [];
296
+ for (const rawArg of rawArgs) {
297
+ const normalized = normalizeSignatureType(rawArg, context);
298
+ if (normalized === undefined)
299
+ return undefined;
300
+ normalizedArgs.push(normalized);
301
+ }
302
+ return normalizedArgs;
303
+ }
304
+ /**
305
+ * Bind an instantiation's base name to the generic interface it names.
306
+ *
307
+ * Goes through `resolveInheritanceBaseInScope` first — the same real scope
308
+ * resolution the embedded-interface path uses — and falls back to a globally
309
+ * UNIQUE name match.
310
+ */
311
+ function resolveGoInstantiationBase(baseName, inScope, interfacesByQualifiedName, indexes) {
312
+ const bound = resolveInheritanceBaseInScope(inScope, simpleTypeName(baseName), indexes);
313
+ if (bound !== undefined)
314
+ return bound.type === 'Interface' ? bound : undefined;
315
+ return uniqueInterfaceNamed(baseName, interfacesByQualifiedName);
316
+ }
317
+ /**
318
+ * The one interface a written name denotes by NAME ALONE — the fallback both
319
+ * name-match routes here share, once the real scope resolution above them has
320
+ * declined.
321
+ *
322
+ * Ambiguity drops the site rather than guessing: two same-named interfaces in
323
+ * different packages would otherwise cross-pollinate each other's
324
+ * instantiations, and a dropped site only costs fan-out that does not exist
325
+ * today anyway. A qualified spelling is tried under both its own name and its
326
+ * simple tail, and a hit under EACH is two matches, so it declines as well.
327
+ *
328
+ * One probe rather than a scan of every interface in the program, which is what
329
+ * made this quadratic: the bracket gate in `collectGoInstantiations` cannot
330
+ * filter `map[…]` or `[]T`, so a Go program pays this once per bracketed
331
+ * spelling it writes.
332
+ */
333
+ function uniqueInterfaceNamed(name, interfacesByQualifiedName) {
334
+ const exact = interfacesByQualifiedName.get(name);
335
+ if (exact === null)
336
+ return undefined;
337
+ const simpleName = simpleTypeName(name);
338
+ if (simpleName === name)
339
+ return exact;
340
+ const simple = interfacesByQualifiedName.get(simpleName);
341
+ if (simple === null)
342
+ return undefined;
343
+ if (exact !== undefined && simple !== undefined)
344
+ return undefined;
345
+ return exact ?? simple;
346
+ }
126
347
  function detectGoInterfaceImplementationsFromIndexes(indexes) {
127
348
  const implementations = new Map();
349
+ const undecided = [];
128
350
  const methodSetCache = new Map();
129
351
  for (const iface of indexes.interfaces) {
130
352
  const required = collectInterfaceMethodSet(iface, indexes, new Set(), methodSetCache);
@@ -132,19 +354,244 @@ function detectGoInterfaceImplementationsFromIndexes(indexes) {
132
354
  continue;
133
355
  if (!methodSetHasVerifiableSignatures(required))
134
356
  continue;
135
- const implementors = [];
136
- for (const structId of candidateStructIdsFor(required, indexes)) {
137
- const actual = indexes.effectiveMethodsByStructId.get(structId);
138
- if (actual === undefined)
139
- continue;
140
- if (methodSetSatisfies(actual, required, indexes.signatureContextByDefId)) {
141
- implementors.push(structId);
357
+ // Hoisted, not recomputed per set: `substituteMethodSet` rewrites
358
+ // SIGNATURES and returns the identical key set, and `candidateStructIdsFor`
359
+ // keys off nothing but those method names — so every set below has exactly
360
+ // these candidates. Materialized because it is iterated once per
361
+ // instantiation and one of the branches behind it yields a live iterator.
362
+ const candidateStructIds = [...candidateStructIdsFor(required, indexes)];
363
+ // The declaration's own method set, then one per observed instantiation.
364
+ // The declaration set runs FIRST and unconditionally, so this is strictly
365
+ // additive: every implementor found before #2855 is still found, in the
366
+ // same order, and instantiation only ever appends.
367
+ const formByStructId = new Map();
368
+ const undecidedStructIds = new Set();
369
+ for (const candidateSet of [required, ...instantiatedMethodSetsFor(iface, required, indexes)]) {
370
+ for (const structId of candidateStructIds) {
371
+ if (formByStructId.get(structId) === 'value')
372
+ continue;
373
+ const pointerSet = indexes.effectiveMethodsByStructId.get(structId);
374
+ if (pointerSet === undefined)
375
+ continue;
376
+ // MS(*T) is the superset: if it does not satisfy, neither does MS(T).
377
+ const verdict = methodSetSatisfies(pointerSet, candidateSet, indexes.signatureContextByDefId);
378
+ if (verdict !== 'satisfied') {
379
+ // `undecided` mints no edge — a speculative IMPLEMENTS would fan out
380
+ // into fabricated CALLS through `emitReceiverBoundCalls`. It is
381
+ // recorded instead, so `impact` can report a lower bound rather than
382
+ // a confident zero (#2873). A decided `unsatisfied` records nothing:
383
+ // that answer is trustworthy.
384
+ if (verdict === 'undecided')
385
+ undecidedStructIds.add(structId);
386
+ continue;
387
+ }
388
+ // Then ask the narrower question separately — does the VALUE type satisfy?
389
+ // This is the distinction `var x I = T{}` turns on, and it is a fact about
390
+ // the program, not a heuristic.
391
+ const valueSet = indexes.valueMethodsByStructId.get(structId);
392
+ const satisfiesByValue = valueSet !== undefined &&
393
+ methodSetSatisfies(valueSet, candidateSet, indexes.signatureContextByDefId) ===
394
+ 'satisfied';
395
+ formByStructId.set(structId, satisfiesByValue ? 'value' : 'pointer');
396
+ undecidedStructIds.delete(structId);
142
397
  }
143
398
  }
399
+ const implementors = [...formByStructId].map(([structDefId, receiverForm]) => ({ structDefId, receiverForm }));
144
400
  if (implementors.length > 0)
145
401
  implementations.set(iface.nodeId, implementors);
402
+ if (undecidedStructIds.size > 0) {
403
+ const candidateNames = [];
404
+ for (const structId of undecidedStructIds) {
405
+ const name = indexes.structsById.get(structId)?.qualifiedName;
406
+ if (name !== undefined)
407
+ candidateNames.push(name);
408
+ }
409
+ undecided.push({
410
+ interfaceDefId: iface.nodeId,
411
+ interfaceName: iface.qualifiedName,
412
+ filePath: iface.filePath,
413
+ undecidedCandidates: undecidedStructIds.size,
414
+ candidateNames,
415
+ });
416
+ }
417
+ }
418
+ return { implementations, undecided };
419
+ }
420
+ /**
421
+ * The method set of each observed INSTANTIATION of a generic interface.
422
+ *
423
+ * Go spec, Instantiations: "A generic function or type is instantiated by
424
+ * substituting type arguments for the type parameters. … Each type argument is
425
+ * substituted for its corresponding type parameter in the generic declaration. …
426
+ * Instantiating a type results in a new non-generic named type." Combined with
427
+ * Type definitions ("Generic types must be instantiated when they are used") the
428
+ * consequence is that `Repo` is not a type at all and `Repo[User]` is — with
429
+ * method set `{ Save(x User) }` after substitution. Implementing an interface
430
+ * then asks whether a type "is an element of the type set of I", and Basic
431
+ * interfaces defines that type set as "the set of types which implement all of
432
+ * those methods". `UserRepo`, whose method set contains `Save(x User)`, is an
433
+ * element of `Repo[User]`'s type set — so it implements `Repo[User]`, and a call
434
+ * through a `Repo[User]`-typed field really can land on `UserRepo.Save`. Before
435
+ * this, it could not: the required parameter type stayed the type PARAMETER `T`,
436
+ * matched no implementor's `User`, and the interface got no IMPLEMENTS edge at
437
+ * all. That is the same false-silence shape as #2813/#2829, one abstraction up.
438
+ *
439
+ * SUBSTITUTION, NOT ERASURE. `Repo[Order]` instantiates to `Save(x Order)` and
440
+ * is NOT satisfied by a `Save(x User)` implementor. Treating `T` as a wildcard
441
+ * would satisfy both and mint an edge Go does not have; the whole point of
442
+ * #2829 was that an exact model beats an approximate one.
443
+ *
444
+ * WHAT THIS DELIBERATELY DOES NOT MODEL. GitNexus holds one node per generic
445
+ * DECLARATION, not one per instantiation, so an interface instantiated at two
446
+ * different arguments in the same program unions their implementors onto the one
447
+ * `Repo` node — `Repo[User]` and `Repo[Order]` in the same repo both fan out to
448
+ * every type satisfying either. That is the same one-node-per-declaration
449
+ * over-approximation every nominal language in the graph already carries (a
450
+ * Kotlin `class UserRepo : Repo<User>` yields `UserRepo IMPLEMENTS Repo`, argument
451
+ * discarded), and it is bounded by the arguments the program actually writes —
452
+ * strictly narrower than erasure, which admits arguments that appear nowhere.
453
+ *
454
+ * Constraints are out of reach by construction and that is correct: a generic
455
+ * interface used as a CONSTRAINT (`func F[T Repo[X]](…)`) is written in a type
456
+ * parameter list, which produces no type binding and no declared type, so no
457
+ * such site is ever harvested. Non-basic interfaces — the union/type-set kind
458
+ * that "may only be used as type constraints" (General interfaces) — declare no
459
+ * methods and are already dropped by the empty-method-set guard above.
460
+ */
461
+ function instantiatedMethodSetsFor(iface, required, indexes) {
462
+ const typeParameters = indexes.typeParametersByInterfaceId.get(iface.nodeId);
463
+ if (typeParameters === undefined)
464
+ return [];
465
+ const instantiations = indexes.instantiationsByInterfaceId.get(iface.nodeId);
466
+ if (instantiations === undefined || instantiations.size === 0)
467
+ return [];
468
+ const indexByName = new Map(typeParameters.map((name, index) => [name, index]));
469
+ const sets = [];
470
+ for (const normalizedArgs of instantiations.values()) {
471
+ const substituted = substituteMethodSet(required, indexByName, normalizedArgs, indexes.signatureContextByDefId);
472
+ if (substituted !== undefined)
473
+ sets.push(substituted);
474
+ }
475
+ return sets;
476
+ }
477
+ /**
478
+ * Rewrite a required method set under one instantiation, or `undefined` when any
479
+ * signature in it cannot be normalized (an unresolved import qualifier) — a
480
+ * partially substituted set would compare a mix of instantiated and
481
+ * uninstantiated types, so the instantiation is dropped whole.
482
+ *
483
+ * The substituted defs carry a synthetic node id that is deliberately absent
484
+ * from `signatureContextByDefId`. Their parameter/return types come out of here
485
+ * ALREADY normalized — the type arguments in the context that WROTE them, the
486
+ * rest in the interface's own — and `normalizeSignatureType` with no context is
487
+ * the identity beyond whitespace, so the comparison in `signaturesCompatible`
488
+ * cannot re-qualify a spelling that is already fully qualified.
489
+ */
490
+ function substituteMethodSet(required, indexByName, normalizedArgs, signatureContextByDefId) {
491
+ const out = new Map();
492
+ for (const [name, overloads] of required) {
493
+ const substitutedOverloads = [];
494
+ for (const def of overloads) {
495
+ const context = signatureContextByDefId.get(def.nodeId);
496
+ const parameterTypes = [];
497
+ for (const parameterType of def.parameterTypes ?? []) {
498
+ const substituted = substituteSignatureType(parameterType, indexByName, normalizedArgs, context);
499
+ if (substituted === undefined)
500
+ return undefined;
501
+ parameterTypes.push(substituted);
502
+ }
503
+ let returnType;
504
+ if (def.returnType !== undefined) {
505
+ returnType = substituteSignatureType(def.returnType, indexByName, normalizedArgs, context);
506
+ if (returnType === undefined)
507
+ return undefined;
508
+ }
509
+ substitutedOverloads.push({
510
+ ...def,
511
+ nodeId: `${def.nodeId}\u0000instantiated`,
512
+ ...(def.parameterTypes !== undefined ? { parameterTypes } : {}),
513
+ ...(returnType !== undefined ? { returnType } : {}),
514
+ });
515
+ }
516
+ out.set(name, substitutedOverloads);
146
517
  }
147
- return implementations;
518
+ return out;
519
+ }
520
+ /**
521
+ * Placeholder for the type argument at position `i` while its enclosing type is
522
+ * normalized. NUL-delimited — the same separator `methodSetKey` already uses,
523
+ * and for the same reason: it cannot occur in Go source.
524
+ *
525
+ * Both halves of that choice are load-bearing. `qualifyGoSignatureTypes` rewrites
526
+ * only tokens matching `[A-Za-z_][A-Za-z0-9_]*`, which can start with neither NUL
527
+ * nor a digit, so the placeholder survives normalization untouched; and
528
+ * `normalizeSignatureType` strips `\s+` FIRST, so a whitespace-delimited
529
+ * placeholder would lose its delimiters and become indistinguishable from an
530
+ * array length (`[5]int`).
531
+ */
532
+ const TYPE_PARAMETER_PLACEHOLDER = /\u0000(\d+)\u0000/g;
533
+ /**
534
+ * Substitute type arguments into one signature type, preserving Go's type
535
+ * identity rules for everything around them.
536
+ *
537
+ * Substitution happens BEFORE normalization and reinstatement AFTER, so the
538
+ * argument's own spelling is never re-qualified by the interface's package while
539
+ * the rest of the type still is: `[]T` in package `repo` with argument
540
+ * `internal/model.User` yields `[]internal/model.User`, not
541
+ * `[]repo.internal/model.User`. Pointer, slice, map and variadic shape survive
542
+ * because only the identifier token is replaced (`*T` -> `*model.User`), which is
543
+ * what makes `Save(x T)` and `Save(x *T)` stay different methods.
544
+ */
545
+ function substituteSignatureType(typeName, indexByName, normalizedArgs, context) {
546
+ const placeheld = typeName.replace(/[A-Za-z_][A-Za-z0-9_]*/g, (token, offset, source) => {
547
+ // `pkg.T` names `T` in package `pkg`, never the type parameter `T`.
548
+ if (hasPackageQualifierDot(source, offset))
549
+ return token;
550
+ const index = indexByName.get(token);
551
+ return index === undefined ? token : `\u0000${index}\u0000`;
552
+ });
553
+ const normalized = normalizeSignatureType(placeheld, context);
554
+ if (normalized === undefined)
555
+ return undefined;
556
+ return normalized.replace(TYPE_PARAMETER_PLACEHOLDER, (_match, digits) => {
557
+ return normalizedArgs[Number(digits)] ?? _match;
558
+ });
559
+ }
560
+ /**
561
+ * The key a method occupies in a method set.
562
+ *
563
+ * Go spec, Uniqueness of identifiers: "Two identifiers are different if they are
564
+ * spelled differently, **or if they appear in different packages and are not
565
+ * exported**." So an UNEXPORTED method name is scoped to its declaring package —
566
+ * `seal` in package `sealed` is a different identifier from `seal` in package
567
+ * `foreign`, and a type outside `sealed` can never satisfy `interface { seal() }`.
568
+ * That is the whole basis of the sealed-interface idiom.
569
+ *
570
+ * Matching on the bare name made those types satisfy each other, which is a
571
+ * FALSE implementation rather than an over-approximation. Qualifying the key
572
+ * with the declaring package for unexported names makes the comparison exact.
573
+ *
574
+ * Exported names are deliberately left unqualified: the spec makes them the same
575
+ * identifier across packages, which is what allows cross-package interface
576
+ * satisfaction to work at all.
577
+ */
578
+ function methodSetKey(simpleName, def, signatureContextByDefId) {
579
+ if (isExportedGoIdentifier(simpleName))
580
+ return simpleName;
581
+ const pkg = signatureContextByDefId.get(def.nodeId)?.packageQualifier;
582
+ return pkg === undefined ? simpleName : `${pkg}\u0000${simpleName}`;
583
+ }
584
+ /**
585
+ * Go spec, Exported identifiers: exported iff the first character is a Unicode
586
+ * uppercase letter (category Lu). Method names always satisfy the second clause
587
+ * (they are method names), so the first character is the whole test.
588
+ */
589
+ function isExportedGoIdentifier(name) {
590
+ const first = name.codePointAt(0);
591
+ if (first === undefined)
592
+ return false;
593
+ const ch = String.fromCodePoint(first);
594
+ return ch !== ch.toLowerCase() && ch === ch.toUpperCase();
148
595
  }
149
596
  function addMethod(methodsByOwner, ownerId, methodName, def) {
150
597
  let methods = methodsByOwner.get(ownerId);
@@ -164,42 +611,86 @@ function addStructMethodCandidate(structIdsByMethodName, methodName, structId) {
164
611
  structIds.add(structId);
165
612
  structIdsByMethodName.set(methodName, structIds);
166
613
  }
167
- function addParentStruct(parentStructIdsByStructId, structId, parentStructId) {
614
+ function addParentStruct(parentStructIdsByStructId, structId, parentStructId, asPointer) {
168
615
  const parents = parentStructIdsByStructId.get(structId) ?? [];
169
- parents.push(parentStructId);
616
+ parents.push({ structId: parentStructId, asPointer });
170
617
  parentStructIdsByStructId.set(structId, parents);
171
618
  }
172
619
  function collectStructMethodSet(structId, indexes, visiting, cache) {
173
620
  const entries = collectStructMethodEntries(structId, indexes, visiting, cache);
174
- return entries === undefined ? undefined : methodEntriesToMethodSet(entries);
621
+ if (entries === undefined)
622
+ return undefined;
623
+ return {
624
+ value: methodEntriesToMethodSet(entries.value),
625
+ pointer: methodEntriesToMethodSet(entries.pointer),
626
+ };
175
627
  }
628
+ /**
629
+ * Build MS(T) and MS(*T) together, applying the spec's promotion table exactly
630
+ * (go.dev/ref/spec#Method_sets, #Struct_types):
631
+ *
632
+ * declared receiver T -> in MS(T) and MS(*T)
633
+ * declared receiver *T -> in MS(*T) only
634
+ * S embeds T (value) -> MS(S) gets P's MS(T); MS(*S) gets P's MS(*T)
635
+ * S embeds *T (pointer) -> MS(S) AND MS(*S) both get P's MS(*T)
636
+ *
637
+ * The last row is the one that makes the embed FORM load-bearing: with
638
+ * `func (b *Base) Ping()`, `struct{ Base }` does not implement a `Ping`
639
+ * interface by value while `struct{ *Base }` does. Collapsing the forms gives
640
+ * both the same answer and one of them is then wrong.
641
+ */
176
642
  function collectStructMethodEntries(structId, indexes, visiting, cache) {
177
643
  const cached = cache.get(structId);
178
- if (cached !== undefined)
179
- return cloneMethodEntries(cached);
644
+ if (cached !== undefined) {
645
+ return { value: cloneMethodEntries(cached.value), pointer: cloneMethodEntries(cached.pointer) };
646
+ }
180
647
  if (visiting.has(structId))
181
648
  return undefined;
182
649
  visiting.add(structId);
183
- const merged = directMethodEntries(indexes.methodsByOwner.get(structId));
184
- for (const parentStructId of indexes.parentStructIdsByStructId.get(structId) ?? []) {
185
- const parentEntries = collectStructMethodEntries(parentStructId, indexes, visiting, cache);
650
+ const own = indexes.methodsByOwner.get(structId);
651
+ // MS(*T) holds every declared method; MS(T) drops the pointer-receiver ones.
652
+ const pointer = directMethodEntries(own);
653
+ const value = directMethodEntries(filterValueReceiverMethods(own));
654
+ for (const parent of indexes.parentStructIdsByStructId.get(structId) ?? []) {
655
+ const parentEntries = collectStructMethodEntries(parent.structId, indexes, visiting, cache);
186
656
  if (parentEntries === undefined) {
187
657
  visiting.delete(structId);
188
658
  return undefined;
189
659
  }
190
- for (const [methodName, entry] of parentEntries) {
191
- if (entry.ambiguous)
192
- continue;
193
- mergePromotedMethodEntry(merged, methodName, {
194
- overloads: entry.overloads,
195
- depth: entry.depth + 1,
196
- ambiguous: false,
197
- });
198
- }
660
+ // Embedding by POINTER lifts the parent's pointer-receiver methods into the
661
+ // embedder's VALUE method set; embedding by value does not.
662
+ const promotedIntoValue = parent.asPointer ? parentEntries.pointer : parentEntries.value;
663
+ promoteEntries(value, promotedIntoValue);
664
+ promoteEntries(pointer, parentEntries.pointer);
199
665
  }
200
666
  visiting.delete(structId);
201
- cache.set(structId, cloneMethodEntries(merged));
202
- return merged;
667
+ cache.set(structId, { value: cloneMethodEntries(value), pointer: cloneMethodEntries(pointer) });
668
+ return { value, pointer };
669
+ }
670
+ /** Merge one depth-level of promoted entries, preserving the shallowest-depth
671
+ * and ambiguity rules the selector spec defines. */
672
+ function promoteEntries(target, source) {
673
+ for (const [methodName, entry] of source) {
674
+ if (entry.ambiguous)
675
+ continue;
676
+ mergePromotedMethodEntry(target, methodName, {
677
+ overloads: entry.overloads,
678
+ depth: entry.depth + 1,
679
+ ambiguous: false,
680
+ });
681
+ }
682
+ }
683
+ /** MS(T) excludes methods declared with a `*T` receiver. */
684
+ function filterValueReceiverMethods(methods) {
685
+ if (methods === undefined)
686
+ return undefined;
687
+ const out = new Map();
688
+ for (const [name, overloads] of methods) {
689
+ const valueOnly = overloads.filter((def) => def.goReceiverKind !== 'pointer');
690
+ if (valueOnly.length > 0)
691
+ out.set(name, valueOnly);
692
+ }
693
+ return out;
203
694
  }
204
695
  function collectInterfaceMethodSet(iface, indexes, visiting, cache) {
205
696
  const cached = cache.get(iface.nodeId);
@@ -275,14 +766,7 @@ function resolveEmbeddedInterface(site, indexes) {
275
766
  const bound = resolveInheritanceBaseInScope(site.inScope, site.name, indexes.scopeIndexes);
276
767
  if (bound !== undefined)
277
768
  return bound.type === 'Interface' ? bound : undefined;
278
- const simpleName = simpleTypeName(site.name);
279
- const matches = [];
280
- for (const iface of indexes.interfaceById.values()) {
281
- if (iface.qualifiedName === site.name || iface.qualifiedName === simpleName) {
282
- matches.push(iface);
283
- }
284
- }
285
- return matches.length === 1 ? matches[0] : undefined;
769
+ return uniqueInterfaceNamed(site.name, indexes.interfacesByQualifiedName);
286
770
  }
287
771
  function simpleTypeName(name) {
288
772
  const dot = name.lastIndexOf('.');
@@ -340,30 +824,50 @@ function mergeMethodSet(target, source) {
340
824
  }
341
825
  }
342
826
  function methodSetSatisfies(actual, required, signatureContextByDefId) {
827
+ let undecided = false;
343
828
  for (const [name, requiredOverloads] of required) {
344
829
  const actualOverloads = actual.get(name);
345
830
  if (actualOverloads === undefined)
346
- return false;
831
+ return 'unsatisfied';
347
832
  for (const requiredMethod of requiredOverloads) {
348
833
  // Fast arity pre-filter: if the required method has a known parameter
349
834
  // count, reject immediately when no actual overload matches it. This
350
835
  // avoids the expensive signature normalization loop for obvious mismatches.
351
836
  if (requiredMethod.parameterCount !== undefined) {
352
837
  if (!actualOverloads.some((a) => a.parameterCount === requiredMethod.parameterCount)) {
353
- return false;
838
+ return 'unsatisfied';
354
839
  }
355
840
  }
356
- if (!hasCompatibleMethod(actualOverloads, requiredMethod, signatureContextByDefId)) {
357
- return false;
358
- }
841
+ const verdict = compatibleMethodVerdict(actualOverloads, requiredMethod, signatureContextByDefId);
842
+ // A decided mismatch anywhere ends it — a type that provably lacks ONE
843
+ // required method does not implement the interface, however many other
844
+ // methods we could not read. Undecided keeps scanning for exactly that
845
+ // reason: a hard no may still be waiting, and it is the better answer.
846
+ if (verdict === 'unsatisfied')
847
+ return 'unsatisfied';
848
+ if (verdict === 'undecided')
849
+ undecided = true;
359
850
  }
360
851
  }
361
- return true;
852
+ return undecided ? 'undecided' : 'satisfied';
362
853
  }
363
- function hasCompatibleMethod(actualOverloads, requiredMethod, signatureContextByDefId) {
854
+ function compatibleMethodVerdict(actualOverloads, requiredMethod, signatureContextByDefId) {
855
+ // Nothing in the interface's own method to compare against: this is missing
856
+ // information, not a difference. It was a `false` before #2873.
364
857
  if (!hasVerifiableSignature(requiredMethod))
365
- return false;
366
- return actualOverloads.some((actualMethod) => signaturesCompatible(actualMethod, requiredMethod, signatureContextByDefId));
858
+ return 'undecided';
859
+ let undecided = false;
860
+ for (const actualMethod of actualOverloads) {
861
+ const verdict = signaturesCompatible(actualMethod, requiredMethod, signatureContextByDefId);
862
+ // One overload that provably matches settles the method — the unknowns on
863
+ // the others cannot unsettle it. (Pyright does the same: a resolvable path
864
+ // suppresses the partially-unknown diagnostic from the others.)
865
+ if (verdict === 'satisfied')
866
+ return 'satisfied';
867
+ if (verdict === 'undecided')
868
+ undecided = true;
869
+ }
870
+ return undecided ? 'undecided' : 'unsatisfied';
367
871
  }
368
872
  function methodSetHasVerifiableSignatures(methods) {
369
873
  for (const overloads of methods.values()) {
@@ -372,9 +876,6 @@ function methodSetHasVerifiableSignatures(methods) {
372
876
  }
373
877
  return true;
374
878
  }
375
- function isPointerReceiverMethod(def) {
376
- return def.goReceiverKind === 'pointer';
377
- }
378
879
  function hasVerifiableSignature(def) {
379
880
  return (def.parameterCount !== undefined ||
380
881
  def.requiredParameterCount !== undefined ||
@@ -384,34 +885,76 @@ function hasVerifiableSignature(def) {
384
885
  function signaturesCompatible(actual, required, signatureContextByDefId) {
385
886
  const actualContext = signatureContextByDefId.get(actual.nodeId);
386
887
  const requiredContext = signatureContextByDefId.get(required.nodeId);
387
- return (countsCompatible(actual.parameterCount, required.parameterCount) &&
388
- countsCompatible(actual.requiredParameterCount, required.requiredParameterCount) &&
389
- parameterTypesCompatible(actual.parameterTypes, required.parameterTypes, actualContext, requiredContext) &&
390
- returnTypesCompatible(actual.returnType, required.returnType, actualContext, requiredContext));
888
+ if (!countsCompatible(actual.parameterCount, required.parameterCount) ||
889
+ !countsCompatible(actual.requiredParameterCount, required.requiredParameterCount)) {
890
+ return 'unsatisfied';
891
+ }
892
+ // A decided mismatch beats an unknown — it is the answer we can stand behind —
893
+ // so the parameter verdict only short-circuits when it is `unsatisfied`.
894
+ const parameters = parameterTypesVerdict(actual, required, actualContext, requiredContext);
895
+ if (parameters === 'unsatisfied')
896
+ return 'unsatisfied';
897
+ const returns = returnTypeVerdict(actual.returnType, required.returnType, actualContext, requiredContext);
898
+ if (returns === 'unsatisfied')
899
+ return 'unsatisfied';
900
+ return parameters === 'undecided' || returns === 'undecided' ? 'undecided' : 'satisfied';
391
901
  }
392
902
  function countsCompatible(actual, required) {
393
903
  return actual === undefined || required === undefined || actual === required;
394
904
  }
395
- function parameterTypesCompatible(actual, required, actualContext, requiredContext) {
396
- if (actual === undefined || required === undefined)
397
- return true;
905
+ function parameterTypesVerdict(actualDef, requiredDef, actualContext, requiredContext) {
906
+ const actual = actualDef.parameterTypes;
907
+ const required = requiredDef.parameterTypes;
908
+ if (actual === undefined || required === undefined) {
909
+ // A method that takes nothing has no list to carry — that is a decided
910
+ // agreement, not a gap, and it is the shape of every `Close() error`.
911
+ if (actualDef.parameterCount === 0 && requiredDef.parameterCount === 0)
912
+ return 'satisfied';
913
+ // Otherwise the types really are unread. This is where the old code assumed
914
+ // `true` and called two signatures compatible without comparing them.
915
+ return 'undecided';
916
+ }
398
917
  if (actual.length !== required.length)
399
- return false;
400
- return actual.every((type, index) => {
401
- const actualType = normalizeSignatureType(type, actualContext);
402
- const requiredType = normalizeSignatureType(required[index], requiredContext);
403
- return actualType !== undefined && requiredType !== undefined && actualType === requiredType;
404
- });
918
+ return 'unsatisfied';
919
+ // Indexed loop, not `entries()`: this is the innermost comparison in the
920
+ // detection pass and runs once per parameter per candidate pair.
921
+ let undecided = false;
922
+ for (let index = 0; index < actual.length; index++) {
923
+ const verdict = typeVerdict(actual[index], required[index], actualContext, requiredContext);
924
+ if (verdict === 'unsatisfied')
925
+ return 'unsatisfied';
926
+ if (verdict === 'undecided')
927
+ undecided = true;
928
+ }
929
+ return undecided ? 'undecided' : 'satisfied';
405
930
  }
406
- function returnTypesCompatible(actual, required, actualContext, requiredContext) {
931
+ function returnTypeVerdict(actual, required, actualContext, requiredContext) {
407
932
  if (required === undefined)
408
- return actual === undefined;
933
+ return actual === undefined ? 'satisfied' : 'unsatisfied';
409
934
  if (actual === undefined)
410
- return false;
935
+ return 'unsatisfied';
936
+ return typeVerdict(actual, required, actualContext, requiredContext);
937
+ }
938
+ /** The one place a type spelling decides anything, and the only mint site of
939
+ * `undecided` below the method level: `normalizeSignatureType` returns
940
+ * `undefined` when a package qualifier has no identity we could recover, and
941
+ * two spellings we could not normalize are not thereby different. */
942
+ function typeVerdict(actual, required, actualContext, requiredContext) {
411
943
  const actualType = normalizeSignatureType(actual, actualContext);
412
944
  const requiredType = normalizeSignatureType(required, requiredContext);
413
- return actualType !== undefined && requiredType !== undefined && actualType === requiredType;
945
+ if (actualType === undefined || requiredType === undefined)
946
+ return 'undecided';
947
+ return actualType === requiredType ? 'satisfied' : 'unsatisfied';
414
948
  }
949
+ /** Normalized form of every type spelling seen in a file, keyed by its context.
950
+ *
951
+ * Normalization is a pure function of (spelling, context), and a context is
952
+ * immutable once built — so this is a cache, not state. It earns its keep
953
+ * because #2873 removed the early bail: a parameter list that named an
954
+ * out-of-repo type used to normalize to `undefined` and stop the comparison at
955
+ * parameter 0, and now every pair of (interface method, candidate struct) walks
956
+ * its whole signature, re-normalizing both sides once per candidate. */
957
+ const normalizedTypesByContext = new WeakMap();
415
958
  function normalizeSignatureType(typeName, context) {
416
959
  // Go type identity includes pointer/slice/map/variadic shape and package
417
960
  // qualifiers. Only erase whitespace and qualify bare local type names; stripping
@@ -419,7 +962,18 @@ function normalizeSignatureType(typeName, context) {
419
962
  const compact = typeName.replace(/\s+/g, '');
420
963
  if (context === undefined)
421
964
  return compact;
422
- return qualifyGoSignatureTypes(compact, context);
965
+ let normalized = normalizedTypesByContext.get(context);
966
+ if (normalized === undefined) {
967
+ normalized = new Map();
968
+ normalizedTypesByContext.set(context, normalized);
969
+ }
970
+ // `has`, not a truthiness check: `undefined` — "no agreeable identity" — is
971
+ // itself a result worth caching, and it is the one this file mints most.
972
+ if (normalized.has(compact))
973
+ return normalized.get(compact);
974
+ const qualified = qualifyGoSignatureTypes(compact, context);
975
+ normalized.set(compact, qualified);
976
+ return qualified;
423
977
  }
424
978
  function qualifyGoSignatureTypes(typeName, context) {
425
979
  let unresolvedQualifier = false;
@@ -445,26 +999,78 @@ function hasPackageQualifierDot(source, offset) {
445
999
  return source[offset - 1] === '.' && source[offset - 2] !== '.';
446
1000
  }
447
1001
  function signatureContextForFile(parsed, indexes) {
1002
+ // A key present with an `undefined` value means "in-repo, but no directory to
1003
+ // name it by" — a repo-ROOT package, whose own file spells its types bare, so
1004
+ // no qualifier either side can agree on exists. It still has to occupy the
1005
+ // name, or the fallback below would label a repo package external.
448
1006
  const importQualifiers = new Map();
449
1007
  const importEdges = indexes.imports?.get(parsed.moduleScope) ?? [];
450
1008
  for (const edge of importEdges) {
451
1009
  if (edge.kind !== 'namespace' || edge.targetFile === null)
452
1010
  continue;
453
- const qualifier = packageQualifierForFile(edge.targetFile);
454
- if (qualifier !== undefined)
455
- importQualifiers.set(edge.localName, qualifier);
1011
+ importQualifiers.set(edge.localName, packageQualifierForFile(edge.targetFile));
1012
+ }
1013
+ // An import that resolves to no file in the repository — every stdlib and
1014
+ // third-party package — still has an identity: its import path, which the
1015
+ // parsed directive kept even though the finalized `ImportEdge` did not (#2873).
1016
+ // Without this fallback `ctx context.Context` normalized to `undefined`, and
1017
+ // `undefined` reads as "signatures differ" on both sides at once, so two
1018
+ // textually identical methods compared unequal and Go interface satisfaction
1019
+ // only ever succeeded for builtin-only signatures.
1020
+ for (const directive of parsed.parsedImports) {
1021
+ if (directive.kind !== 'namespace')
1022
+ continue;
1023
+ const token = goImportToken(directive.localName, directive.targetRaw);
1024
+ // The edges ran first, so a token an in-repo import already claimed keeps
1025
+ // its package directory — the fallback fills gaps, it does not compete.
1026
+ if (importQualifiers.has(token))
1027
+ continue;
1028
+ importQualifiers.set(token, externalPackageQualifier(directive.targetRaw));
456
1029
  }
457
1030
  return {
458
1031
  packageQualifier: packageQualifierForFile(parsed.filePath),
459
1032
  importQualifiers,
460
1033
  };
461
1034
  }
1035
+ /** Identity for a package that lives outside the repository.
1036
+ *
1037
+ * The import path is the exact identity — `net/http` and `example.com/x/http`
1038
+ * are different packages that both spell their qualifier `http`, so keying on
1039
+ * the local name would make them compare equal. The prefix keeps the result in
1040
+ * a namespace no in-repo qualifier can reach: no package directory can begin
1041
+ * with the literal `extern:`. */
1042
+ function externalPackageQualifier(importPath) {
1043
+ return `extern:${importPath}`;
1044
+ }
1045
+ /** The token Go source writes before the `.` for this import.
1046
+ *
1047
+ * An alias names its own token, so it is returned as-is. An unaliased import
1048
+ * arrives here spelled as the last path segment, which is right until a module
1049
+ * carries a major version: `github.com/foo/bar/v2` is written `bar` and
1050
+ * `gopkg.in/yaml.v3` is written `yaml`, per the rule the go tool applies.
1051
+ *
1052
+ * Deriving "aliased" from the path rather than from `importedName` is
1053
+ * deliberate — the Go extractor sets both names to the alias when there is one
1054
+ * (`import-decomposer.ts`), so the two fields never disagree.
1055
+ *
1056
+ * A package whose name diverges from its path for any OTHER reason cannot be
1057
+ * recovered without reading the dependency's own source, which is by definition
1058
+ * outside the repository. Those stay unresolved, which is the safe direction. */
1059
+ function goImportToken(localName, importPath) {
1060
+ const segments = importPath.split('/').filter((segment) => segment.length > 0);
1061
+ const leaf = segments.pop() ?? importPath;
1062
+ if (localName !== leaf)
1063
+ return localName;
1064
+ const name = /^v\d+$/.test(leaf) ? (segments.pop() ?? leaf) : leaf;
1065
+ return name.replace(/\.v\d+$/, '');
1066
+ }
1067
+ /** The package directory, or `undefined` for a repo-root file.
1068
+ *
1069
+ * Shares `goPackageDir` with the package-clause resolver rather than repeating
1070
+ * its normalize-and-slice (#2837): the two disagree only on how they spell "no
1071
+ * directory", so the difference stays here, at the one call site that cares. */
462
1072
  function packageQualifierForFile(filePath) {
463
- const normalized = filePath.replace(/\\/g, '/');
464
- const slash = normalized.lastIndexOf('/');
465
- if (slash === -1)
466
- return undefined;
467
- const packageDir = normalized.slice(0, slash);
1073
+ const packageDir = goPackageDir(filePath);
468
1074
  return packageDir.length === 0 ? undefined : packageDir;
469
1075
  }
470
1076
  const GO_BUILTIN_TYPES = new Set([