gitnexus 1.6.8-rc.9 → 1.6.8

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 (430) hide show
  1. package/README.md +3 -3
  2. package/dist/_shared/graph/types.d.ts +31 -1
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/language-detection.d.ts.map +1 -1
  5. package/dist/_shared/language-detection.js +11 -1
  6. package/dist/_shared/language-detection.js.map +1 -1
  7. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  8. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  9. package/dist/_shared/lbug/schema-constants.js +6 -0
  10. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  11. package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
  12. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
  13. package/dist/_shared/scope-resolution/symbol-definition.d.ts +6 -0
  14. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  15. package/dist/cli/ai-context.d.ts +31 -1
  16. package/dist/cli/ai-context.js +18 -16
  17. package/dist/cli/analyze-config.js +11 -0
  18. package/dist/cli/analyze.d.ts +14 -0
  19. package/dist/cli/analyze.js +98 -0
  20. package/dist/cli/embedding-dims.d.ts +33 -0
  21. package/dist/cli/embedding-dims.js +39 -0
  22. package/dist/cli/eval-server.d.ts +8 -0
  23. package/dist/cli/eval-server.js +242 -2
  24. package/dist/cli/help-i18n.js +19 -0
  25. package/dist/cli/i18n/en.d.ts +15 -1
  26. package/dist/cli/i18n/en.js +15 -1
  27. package/dist/cli/i18n/resources.d.ts +29 -1
  28. package/dist/cli/i18n/zh-CN.d.ts +14 -0
  29. package/dist/cli/i18n/zh-CN.js +15 -1
  30. package/dist/cli/index.js +89 -1
  31. package/dist/cli/mcp.d.ts +6 -1
  32. package/dist/cli/mcp.js +26 -1
  33. package/dist/cli/optional-grammars.d.ts +6 -8
  34. package/dist/cli/optional-grammars.js +8 -11
  35. package/dist/cli/setup.d.ts +3 -1
  36. package/dist/cli/setup.js +67 -17
  37. package/dist/cli/skill-gen.js +2 -1
  38. package/dist/cli/tool.d.ts +19 -1
  39. package/dist/cli/tool.js +96 -3
  40. package/dist/core/embeddings/hf-env.d.ts +0 -66
  41. package/dist/core/embeddings/http-client.d.ts +7 -0
  42. package/dist/core/embeddings/http-client.js +5 -3
  43. package/dist/core/embeddings/server-mapping.d.ts +1 -1
  44. package/dist/core/embeddings/server-mapping.js +7 -3
  45. package/dist/core/graph/import-cycles.d.ts +10 -0
  46. package/dist/core/graph/import-cycles.js +103 -0
  47. package/dist/core/group/cross-impact.d.ts +2 -1
  48. package/dist/core/group/cross-impact.js +5 -1
  49. package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
  50. package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
  51. package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
  52. package/dist/core/group/extractors/http-route-extractor.js +22 -4
  53. package/dist/core/group/extractors/include-extractor.js +22 -13
  54. package/dist/core/group/sync.d.ts +27 -1
  55. package/dist/core/group/sync.js +0 -0
  56. package/dist/core/incremental/subgraph-extract.js +18 -1
  57. package/dist/core/ingestion/cfg/cfg-builder.d.ts +114 -0
  58. package/dist/core/ingestion/cfg/cfg-builder.js +196 -0
  59. package/dist/core/ingestion/cfg/collect.d.ts +51 -0
  60. package/dist/core/ingestion/cfg/collect.js +77 -0
  61. package/dist/core/ingestion/cfg/control-dependence.d.ts +58 -0
  62. package/dist/core/ingestion/cfg/control-dependence.js +182 -0
  63. package/dist/core/ingestion/cfg/control-flow-context.d.ts +106 -0
  64. package/dist/core/ingestion/cfg/control-flow-context.js +124 -0
  65. package/dist/core/ingestion/cfg/emit.d.ts +293 -0
  66. package/dist/core/ingestion/cfg/emit.js +646 -0
  67. package/dist/core/ingestion/cfg/post-dominators.d.ts +79 -0
  68. package/dist/core/ingestion/cfg/post-dominators.js +176 -0
  69. package/dist/core/ingestion/cfg/reaching-def-reason-codec.d.ts +106 -0
  70. package/dist/core/ingestion/cfg/reaching-def-reason-codec.js +133 -0
  71. package/dist/core/ingestion/cfg/reaching-defs-graph.d.ts +18 -0
  72. package/dist/core/ingestion/cfg/reaching-defs-graph.js +312 -0
  73. package/dist/core/ingestion/cfg/reaching-defs.d.ts +162 -0
  74. package/dist/core/ingestion/cfg/reaching-defs.js +785 -0
  75. package/dist/core/ingestion/cfg/synthetic-escape.d.ts +124 -0
  76. package/dist/core/ingestion/cfg/synthetic-escape.js +300 -0
  77. package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
  78. package/dist/core/ingestion/cfg/traversal-result.js +2 -0
  79. package/dist/core/ingestion/cfg/types.d.ts +274 -0
  80. package/dist/core/ingestion/cfg/types.js +13 -0
  81. package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.d.ts +111 -0
  82. package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.js +541 -0
  83. package/dist/core/ingestion/cfg/visitors/c-cpp.d.ts +74 -0
  84. package/dist/core/ingestion/cfg/visitors/c-cpp.js +584 -0
  85. package/dist/core/ingestion/cfg/visitors/call-site-harvest.d.ts +195 -0
  86. package/dist/core/ingestion/cfg/visitors/call-site-harvest.js +350 -0
  87. package/dist/core/ingestion/cfg/visitors/csharp-harvest.d.ts +124 -0
  88. package/dist/core/ingestion/cfg/visitors/csharp-harvest.js +589 -0
  89. package/dist/core/ingestion/cfg/visitors/csharp.d.ts +87 -0
  90. package/dist/core/ingestion/cfg/visitors/csharp.js +867 -0
  91. package/dist/core/ingestion/cfg/visitors/dart-harvest.d.ts +278 -0
  92. package/dist/core/ingestion/cfg/visitors/dart-harvest.js +870 -0
  93. package/dist/core/ingestion/cfg/visitors/dart.d.ts +119 -0
  94. package/dist/core/ingestion/cfg/visitors/dart.js +836 -0
  95. package/dist/core/ingestion/cfg/visitors/go-harvest.d.ts +160 -0
  96. package/dist/core/ingestion/cfg/visitors/go-harvest.js +621 -0
  97. package/dist/core/ingestion/cfg/visitors/go.d.ts +108 -0
  98. package/dist/core/ingestion/cfg/visitors/go.js +638 -0
  99. package/dist/core/ingestion/cfg/visitors/java-harvest.d.ts +108 -0
  100. package/dist/core/ingestion/cfg/visitors/java-harvest.js +513 -0
  101. package/dist/core/ingestion/cfg/visitors/java.d.ts +101 -0
  102. package/dist/core/ingestion/cfg/visitors/java.js +812 -0
  103. package/dist/core/ingestion/cfg/visitors/kotlin-harvest.d.ts +253 -0
  104. package/dist/core/ingestion/cfg/visitors/kotlin-harvest.js +719 -0
  105. package/dist/core/ingestion/cfg/visitors/kotlin.d.ts +121 -0
  106. package/dist/core/ingestion/cfg/visitors/kotlin.js +809 -0
  107. package/dist/core/ingestion/cfg/visitors/php-harvest.d.ts +172 -0
  108. package/dist/core/ingestion/cfg/visitors/php-harvest.js +626 -0
  109. package/dist/core/ingestion/cfg/visitors/php.d.ts +96 -0
  110. package/dist/core/ingestion/cfg/visitors/php.js +721 -0
  111. package/dist/core/ingestion/cfg/visitors/python-harvest.d.ts +212 -0
  112. package/dist/core/ingestion/cfg/visitors/python-harvest.js +739 -0
  113. package/dist/core/ingestion/cfg/visitors/python.d.ts +103 -0
  114. package/dist/core/ingestion/cfg/visitors/python.js +558 -0
  115. package/dist/core/ingestion/cfg/visitors/ruby-harvest.d.ts +223 -0
  116. package/dist/core/ingestion/cfg/visitors/ruby-harvest.js +587 -0
  117. package/dist/core/ingestion/cfg/visitors/ruby.d.ts +112 -0
  118. package/dist/core/ingestion/cfg/visitors/ruby.js +756 -0
  119. package/dist/core/ingestion/cfg/visitors/rust-harvest.d.ts +324 -0
  120. package/dist/core/ingestion/cfg/visitors/rust-harvest.js +873 -0
  121. package/dist/core/ingestion/cfg/visitors/rust.d.ts +95 -0
  122. package/dist/core/ingestion/cfg/visitors/rust.js +558 -0
  123. package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.d.ts +87 -0
  124. package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.js +116 -0
  125. package/dist/core/ingestion/cfg/visitors/swift-harvest.d.ts +255 -0
  126. package/dist/core/ingestion/cfg/visitors/swift-harvest.js +679 -0
  127. package/dist/core/ingestion/cfg/visitors/swift.d.ts +116 -0
  128. package/dist/core/ingestion/cfg/visitors/swift.js +787 -0
  129. package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +149 -0
  130. package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1056 -0
  131. package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
  132. package/dist/core/ingestion/cfg/visitors/typescript.js +583 -0
  133. package/dist/core/ingestion/import-resolvers/utils.js +2 -0
  134. package/dist/core/ingestion/language-provider.d.ts +11 -0
  135. package/dist/core/ingestion/languages/c-cpp.js +6 -1
  136. package/dist/core/ingestion/languages/cobol.js +4 -0
  137. package/dist/core/ingestion/languages/cpp/arity-metadata.js +41 -2
  138. package/dist/core/ingestion/languages/cpp/captures.js +50 -1
  139. package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
  140. package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
  141. package/dist/core/ingestion/languages/cpp/header-scan.d.ts +1 -1
  142. package/dist/core/ingestion/languages/cpp/header-scan.js +2 -2
  143. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
  144. package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
  145. package/dist/core/ingestion/languages/cpp/query.js +23 -0
  146. package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
  147. package/dist/core/ingestion/languages/csharp.js +2 -0
  148. package/dist/core/ingestion/languages/dart.js +2 -0
  149. package/dist/core/ingestion/languages/go.js +2 -0
  150. package/dist/core/ingestion/languages/java.js +3 -0
  151. package/dist/core/ingestion/languages/kotlin/query.js +3 -2
  152. package/dist/core/ingestion/languages/kotlin.js +3 -0
  153. package/dist/core/ingestion/languages/php.js +2 -0
  154. package/dist/core/ingestion/languages/python.js +2 -0
  155. package/dist/core/ingestion/languages/ruby.js +2 -0
  156. package/dist/core/ingestion/languages/rust.js +2 -0
  157. package/dist/core/ingestion/languages/swift.js +2 -0
  158. package/dist/core/ingestion/languages/typescript.js +5 -0
  159. package/dist/core/ingestion/languages/vue.js +6 -0
  160. package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
  161. package/dist/core/ingestion/method-extractors/generic.js +1 -0
  162. package/dist/core/ingestion/method-types.d.ts +2 -0
  163. package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
  164. package/dist/core/ingestion/model/symbol-table.js +1 -0
  165. package/dist/core/ingestion/mro-processor.js +109 -0
  166. package/dist/core/ingestion/parsing-processor.js +23 -0
  167. package/dist/core/ingestion/pipeline-phases/call-summaries.d.ts +26 -0
  168. package/dist/core/ingestion/pipeline-phases/call-summaries.js +46 -0
  169. package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
  170. package/dist/core/ingestion/pipeline-phases/index.js +2 -0
  171. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +0 -21
  172. package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
  173. package/dist/core/ingestion/pipeline-phases/routes.d.ts +10 -0
  174. package/dist/core/ingestion/pipeline-phases/routes.js +30 -1
  175. package/dist/core/ingestion/pipeline-phases/taint-summaries.d.ts +30 -0
  176. package/dist/core/ingestion/pipeline-phases/taint-summaries.js +81 -0
  177. package/dist/core/ingestion/pipeline.d.ts +92 -10
  178. package/dist/core/ingestion/pipeline.js +11 -2
  179. package/dist/core/ingestion/scope-extractor.js +12 -2
  180. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
  181. package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +75 -0
  182. package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +67 -0
  183. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -2
  184. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +14 -2
  185. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +6 -1
  186. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +13 -1
  187. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +9 -1
  188. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +28 -2
  189. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
  190. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
  191. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +6 -1
  192. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +174 -40
  193. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +24 -0
  194. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +276 -190
  195. package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
  196. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +75 -0
  197. package/dist/core/ingestion/scope-resolution/pipeline/run.js +349 -1
  198. package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
  199. package/dist/core/ingestion/taint/call-summary-codec.d.ts +75 -0
  200. package/dist/core/ingestion/taint/call-summary-codec.js +128 -0
  201. package/dist/core/ingestion/taint/call-summary-emit.d.ts +43 -0
  202. package/dist/core/ingestion/taint/call-summary-emit.js +70 -0
  203. package/dist/core/ingestion/taint/call-summary-harvest.d.ts +77 -0
  204. package/dist/core/ingestion/taint/call-summary-harvest.js +179 -0
  205. package/dist/core/ingestion/taint/call-summary-model.d.ts +47 -0
  206. package/dist/core/ingestion/taint/call-summary-model.js +25 -0
  207. package/dist/core/ingestion/taint/emit.d.ts +125 -0
  208. package/dist/core/ingestion/taint/emit.js +208 -0
  209. package/dist/core/ingestion/taint/interproc-emit.d.ts +50 -0
  210. package/dist/core/ingestion/taint/interproc-emit.js +88 -0
  211. package/dist/core/ingestion/taint/interproc-solver.d.ts +110 -0
  212. package/dist/core/ingestion/taint/interproc-solver.js +312 -0
  213. package/dist/core/ingestion/taint/match.d.ts +153 -0
  214. package/dist/core/ingestion/taint/match.js +278 -0
  215. package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
  216. package/dist/core/ingestion/taint/path-codec.js +190 -0
  217. package/dist/core/ingestion/taint/propagate.d.ts +216 -0
  218. package/dist/core/ingestion/taint/propagate.js +659 -0
  219. package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
  220. package/dist/core/ingestion/taint/site-safety.js +98 -0
  221. package/dist/core/ingestion/taint/source-sink-config.d.ts +107 -23
  222. package/dist/core/ingestion/taint/source-sink-config.js +35 -12
  223. package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
  224. package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
  225. package/dist/core/ingestion/taint/summary-harvest-driver.d.ts +80 -0
  226. package/dist/core/ingestion/taint/summary-harvest-driver.js +179 -0
  227. package/dist/core/ingestion/taint/summary-harvest.d.ts +89 -0
  228. package/dist/core/ingestion/taint/summary-harvest.js +537 -0
  229. package/dist/core/ingestion/taint/summary-model.d.ts +200 -0
  230. package/dist/core/ingestion/taint/summary-model.js +86 -0
  231. package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
  232. package/dist/core/ingestion/taint/typescript-model.js +102 -0
  233. package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
  234. package/dist/core/ingestion/utils/env.d.ts +7 -0
  235. package/dist/core/ingestion/utils/env.js +12 -0
  236. package/dist/core/ingestion/utils/method-props.js +1 -0
  237. package/dist/core/ingestion/workers/parse-worker.d.ts +13 -0
  238. package/dist/core/ingestion/workers/parse-worker.js +76 -17
  239. package/dist/core/ingestion/workers/worker-pool.d.ts +9 -40
  240. package/dist/core/ingestion/workers/worker-pool.js +15 -2
  241. package/dist/core/lbug/csv-generator.d.ts +51 -3
  242. package/dist/core/lbug/csv-generator.js +369 -255
  243. package/dist/core/lbug/lbug-adapter.d.ts +58 -18
  244. package/dist/core/lbug/lbug-adapter.js +346 -84
  245. package/dist/core/lbug/lbug-config.d.ts +19 -0
  246. package/dist/core/lbug/lbug-config.js +29 -0
  247. package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
  248. package/dist/core/lbug/pdg-emit-sink.js +358 -0
  249. package/dist/core/lbug/pool-adapter.d.ts +35 -0
  250. package/dist/core/lbug/pool-adapter.js +90 -1
  251. package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
  252. package/dist/core/lbug/rel-pair-routing.js +140 -0
  253. package/dist/core/lbug/schema.d.ts +2 -2
  254. package/dist/core/lbug/schema.js +3 -0
  255. package/dist/core/logger.d.ts +0 -5
  256. package/dist/core/run-analyze.d.ts +96 -0
  257. package/dist/core/run-analyze.js +207 -3
  258. package/dist/core/tree-sitter/parser-loader.js +5 -4
  259. package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
  260. package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
  261. package/dist/core/tree-sitter/vendored-grammars.js +57 -0
  262. package/dist/core/wiki/generator.js +3 -1
  263. package/dist/core/wiki/graph-queries.d.ts +6 -0
  264. package/dist/core/wiki/graph-queries.js +9 -1
  265. package/dist/mcp/http-transport.d.ts +134 -0
  266. package/dist/mcp/http-transport.js +503 -0
  267. package/dist/mcp/local/local-backend.d.ts +110 -24
  268. package/dist/mcp/local/local-backend.js +1225 -19
  269. package/dist/mcp/local/pdg-impact.d.ts +384 -0
  270. package/dist/mcp/local/pdg-impact.js +1972 -0
  271. package/dist/mcp/resources.js +13 -1
  272. package/dist/mcp/tools.d.ts +12 -0
  273. package/dist/mcp/tools.js +214 -7
  274. package/dist/server/analyze-launch.d.ts +29 -0
  275. package/dist/server/analyze-launch.js +137 -0
  276. package/dist/server/analyze-upload.d.ts +33 -0
  277. package/dist/server/analyze-upload.js +123 -0
  278. package/dist/server/analyze-worker.d.ts +17 -1
  279. package/dist/server/api.d.ts +17 -0
  280. package/dist/server/api.js +132 -168
  281. package/dist/server/git-clone.d.ts +43 -2
  282. package/dist/server/git-clone.js +211 -16
  283. package/dist/server/mcp-http.d.ts +5 -6
  284. package/dist/server/mcp-http.js +9 -82
  285. package/dist/server/middleware.d.ts +40 -0
  286. package/dist/server/middleware.js +92 -0
  287. package/dist/server/private-ip.d.ts +1 -0
  288. package/dist/server/private-ip.js +15 -0
  289. package/dist/server/upload-ingest.d.ts +56 -0
  290. package/dist/server/upload-ingest.js +276 -0
  291. package/dist/server/upload-paths.d.ts +37 -0
  292. package/dist/server/upload-paths.js +57 -0
  293. package/dist/server/upload-sweep.d.ts +20 -0
  294. package/dist/server/upload-sweep.js +57 -0
  295. package/dist/storage/git.js +5 -8
  296. package/dist/storage/parse-cache.d.ts +22 -1
  297. package/dist/storage/parse-cache.js +41 -10
  298. package/dist/storage/repo-manager.d.ts +121 -10
  299. package/dist/storage/repo-manager.js +43 -5
  300. package/dist/types/pipeline.d.ts +9 -0
  301. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
  302. package/hooks/claude/gitnexus-hook.cjs +110 -13
  303. package/hooks/claude/hook-db-lock-probe.cjs +513 -26
  304. package/package.json +8 -2
  305. package/scripts/assert-publish-grammar-coverage.cjs +31 -0
  306. package/scripts/build-tree-sitter-grammars.cjs +16 -10
  307. package/scripts/cross-platform-tests.ts +1 -0
  308. package/skills/gitnexus-debugging.md +16 -4
  309. package/skills/gitnexus-exploring.md +3 -3
  310. package/skills/gitnexus-guide.md +33 -0
  311. package/skills/gitnexus-pdg-query.md +89 -0
  312. package/skills/gitnexus-refactoring.md +1 -1
  313. package/skills/gitnexus-taint-analysis.md +178 -0
  314. package/vendor/tree-sitter-c/package.json +1 -1
  315. package/vendor/tree-sitter-dart/package.json +1 -1
  316. package/vendor/tree-sitter-kotlin/package.json +1 -1
  317. package/vendor/tree-sitter-proto/package.json +1 -1
  318. package/vendor/tree-sitter-swift/package.json +1 -1
  319. package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
  320. package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
  321. package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
  322. package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
  323. package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
  324. package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
  325. package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
  326. package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
  327. package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
  328. package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
  329. package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
  330. package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
  331. package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
  332. package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
  333. package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
  334. package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
  335. package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
  336. package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
  337. package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
  338. package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
  339. package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
  340. package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
  341. package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
  342. package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
  343. package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
  344. package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
  345. package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
  346. package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
  347. package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
  348. package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
  349. package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
  350. package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
  351. package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
  352. package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
  353. package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
  354. package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
  355. package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
  356. package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
  357. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
  358. package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
  359. package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
  360. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
  361. package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
  362. package/web/assets/index-BvYev1UJ.js +635 -0
  363. package/web/assets/index-_lgn7hs5.css +2 -0
  364. package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
  365. package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
  366. package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
  367. package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
  368. package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
  369. package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
  370. package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
  371. package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
  372. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
  373. package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
  374. package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
  375. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
  376. package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
  377. package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
  378. package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
  379. package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
  380. package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
  381. package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
  382. package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
  383. package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
  384. package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
  385. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
  386. package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
  387. package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
  388. package/web/index.html +13 -15
  389. package/scripts/materialize-vendor-grammars.cjs +0 -97
  390. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
  391. package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
  392. package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
  393. package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
  394. package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
  395. package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
  396. package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
  397. package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
  398. package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
  399. package/web/assets/chunk-CilyBKbf.js +0 -1
  400. package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
  401. package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
  402. package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
  403. package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
  404. package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
  405. package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
  406. package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
  407. package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
  408. package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
  409. package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
  410. package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
  411. package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
  412. package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
  413. package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
  414. package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
  415. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
  416. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
  417. package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
  418. package/web/assets/index-BKWA-m7o.css +0 -2
  419. package/web/assets/index-CG6q8eTs.js +0 -626
  420. package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
  421. package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
  422. package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
  423. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
  424. package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
  425. package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
  426. package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
  427. package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
  428. package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
  429. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
  430. /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
@@ -89,6 +89,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
89
89
  if (fnDef === undefined) {
90
90
  fnDef = pickImplicitThisOverload(site, scopes, workspaceIndex, model, {
91
91
  conversionRankFn: options.conversionRankFn,
92
+ conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
92
93
  constraintCompatibility: options.constraintCompatibility,
93
94
  });
94
95
  fnDefFromImplicitThis = fnDef !== undefined;
@@ -112,6 +113,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
112
113
  const narrowed = narrowOverloadCandidates(allCallables, site.arity, site.argumentTypes, {
113
114
  argumentTypeClasses: site.argumentTypeClasses,
114
115
  conversionRankFn: options.conversionRankFn,
116
+ conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
115
117
  constraintCompatibility: options.constraintCompatibility,
116
118
  });
117
119
  if (narrowed.length === 1) {
@@ -190,6 +192,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
190
192
  const narrowed = narrowOverloadCandidates(ordinary, site.arity, site.argumentTypes, {
191
193
  argumentTypeClasses: site.argumentTypeClasses,
192
194
  conversionRankFn: options.conversionRankFn,
195
+ conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
193
196
  constraintCompatibility: options.constraintCompatibility,
194
197
  });
195
198
  if (narrowed.length === 1) {
@@ -240,6 +243,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
240
243
  const narrowed = narrowOverloadCandidates(merged, site.arity, site.argumentTypes, {
241
244
  argumentTypeClasses: site.argumentTypeClasses,
242
245
  conversionRankFn: options.conversionRankFn,
246
+ conversionOnlyArgTypePrefixes: options.conversionOnlyArgTypePrefixes,
243
247
  constraintCompatibility: options.constraintCompatibility,
244
248
  });
245
249
  if (narrowed.length === 1) {
@@ -285,10 +289,22 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
285
289
  callerScope: site.inScope,
286
290
  scopes,
287
291
  })
288
- : undefined, site.argumentTypes, site.argumentTypeClasses, options.conversionRankFn, scopeDefsCache);
292
+ : undefined, site.argumentTypes, site.argumentTypeClasses, options.conversionRankFn, scopeDefsCache, options.conversionOnlyArgTypePrefixes);
289
293
  }
290
294
  if (fnDef === undefined)
291
295
  continue;
296
+ if (fnDef.isDeleted === true) {
297
+ recordSuppressedOutcome(options.recordResolutionOutcome, {
298
+ phase: 'free-call-fallback',
299
+ filePath: parsed.filePath,
300
+ name: site.name,
301
+ range: site.atRange,
302
+ reason: 'selected-callable-deleted',
303
+ candidates: [fnDef],
304
+ });
305
+ handledSites.add(siteKey(parsed.filePath, site));
306
+ continue;
307
+ }
292
308
  if ((fnDefFromImplicitThis || fnDef.type === 'Method' || fnDef.type === 'Constructor') &&
293
309
  options.isCallableVisibleFromCaller !== undefined &&
294
310
  !options.isCallableVisibleFromCaller({
@@ -310,6 +326,13 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
310
326
  // means we don't add a new edge — so `emit-references` skips its
311
327
  // potentially-wrong fallback for the same site.
312
328
  handledSites.add(siteKey(parsed.filePath, site));
329
+ // Resolved-callee-id capture (#2227 U2/KTD6/R8): record this CALLS site's
330
+ // resolved target BEFORE the collapsed `seen` dedup. The free-call dedup
331
+ // key drops the line (one edge per caller→target), so capturing after
332
+ // `seen.has` would lose every same-target call past the first — capture
333
+ // here, per site, keyed on `site.atRange` (byte-equal to U1's
334
+ // SiteRecord.at: 1-based line / 0-based col).
335
+ options.calleeIdSink?.add(parsed.filePath, site.atRange.startLine, site.atRange.startCol, tgtGraphId);
313
336
  const relId = `rel:CALLS:${callerGraphId}->${tgtGraphId}`;
314
337
  if (seen.has(relId))
315
338
  continue;
@@ -430,7 +453,7 @@ export function buildGlobalClassIndex(scopes) {
430
453
  * order. Exported for unit testing — the `scopeDefsCache` equivalence is
431
454
  * exercised via synthetic stubs in `pick-unique-global-callable.test.ts`.
432
455
  */
433
- export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleName, callerFilePath, isFileLocalDef, callArity, isCallerVisible, callArgTypes, callArgTypeClasses, conversionRankFn, scopeDefsCache) {
456
+ export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleName, callerFilePath, isFileLocalDef, callArity, isCallerVisible, callArgTypes, callArgTypeClasses, conversionRankFn, scopeDefsCache, conversionOnlyArgTypePrefixes) {
434
457
  // The scope-index candidate list is a pure function of (name, callerFilePath):
435
458
  // the same-name bucket is fixed for the pass, the file-local filter depends
436
459
  // only on the candidate + callerFilePath, and the logical-key dedup is
@@ -492,6 +515,7 @@ export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleNam
492
515
  const narrowed = narrowOverloadCandidates(scopeDefs, callArity, callArgTypes, {
493
516
  argumentTypeClasses: callArgTypeClasses,
494
517
  conversionRankFn,
518
+ conversionOnlyArgTypePrefixes,
495
519
  });
496
520
  if (narrowed.length === 1)
497
521
  return narrowed[0];
@@ -533,6 +557,7 @@ export function pickUniqueGlobalCallable(name, model, globalCallablesBySimpleNam
533
557
  const narrowed = narrowOverloadCandidates(defs, callArity, callArgTypes, {
534
558
  argumentTypeClasses: callArgTypeClasses,
535
559
  conversionRankFn,
560
+ conversionOnlyArgTypePrefixes,
536
561
  });
537
562
  if (narrowed.length === 1)
538
563
  return narrowed[0];
@@ -675,6 +700,7 @@ export function pickImplicitThisOverload(site, scopes, workspaceIndex, model, ho
675
700
  const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
676
701
  argumentTypeClasses: site.argumentTypeClasses,
677
702
  conversionRankFn: hookCtx?.conversionRankFn,
703
+ conversionOnlyArgTypePrefixes: hookCtx?.conversionOnlyArgTypePrefixes,
678
704
  constraintCompatibility: hookCtx?.constraintCompatibility,
679
705
  });
680
706
  if (candidates.length !== 1)
@@ -69,6 +69,10 @@ export interface OverloadNarrowingHookCtx {
69
69
  /** Conversion-rank scoring fallback (step 4b). Engages when the
70
70
  * exact-type filter rejects every candidate. */
71
71
  readonly conversionRankFn?: ConversionRankFn;
72
+ /** Per-language argument-type prefixes whose conversion-rank failures
73
+ * should suppress genuinely ambiguous multi-overload sets instead of
74
+ * falling back to arity-only candidates. */
75
+ readonly conversionOnlyArgTypePrefixes?: readonly string[];
72
76
  /** Constraint filter (step 4c). Drops candidates whose template
73
77
  * guards (SFINAE `enable_if_t`, C++20 `requires`, future Rust
74
78
  * trait bounds, etc.) provably fail at the call site. Three-valued
@@ -106,6 +106,10 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes, hookCtx)
106
106
  const ranked = rankByConversion(candidates, argTypes, hookCtx.conversionRankFn, hookCtx.argumentTypeClasses);
107
107
  if (ranked.length > 0)
108
108
  result = ranked;
109
+ else if (candidates.length > 1 &&
110
+ hasConversionOnlyArgType(argTypes, hookCtx.conversionOnlyArgTypePrefixes)) {
111
+ result = [];
112
+ }
109
113
  }
110
114
  }
111
115
  // Constraint filter (step 4c; Tier-A — SFINAE / `requires` clauses).
@@ -145,6 +149,11 @@ export function narrowOverloadCandidates(overloads, argCount, argTypes, hookCtx)
145
149
  }
146
150
  return result;
147
151
  }
152
+ function hasConversionOnlyArgType(argTypes, prefixes) {
153
+ if (prefixes === undefined || prefixes.length === 0)
154
+ return false;
155
+ return argTypes.some((type) => prefixes.some((prefix) => type.startsWith(prefix)));
156
+ }
148
157
  function exactTypeSlotMatches(argType, paramType, argTypeClass, paramTypeClass) {
149
158
  if (argType !== paramType)
150
159
  return false;
@@ -43,13 +43,18 @@ import type { SemanticModel } from '../../model/semantic-model.js';
43
43
  import type { ScopeResolver } from '../contract/scope-resolver.js';
44
44
  import type { GraphNodeLookup } from '../graph-bridge/node-lookup.js';
45
45
  import type { WorkspaceResolutionIndex } from '../workspace-index.js';
46
+ import type { CalleeIdSink } from '../graph-bridge/callee-id-sink.js';
46
47
  import type { ResolutionOutcomeRecorder } from '../resolution-outcome.js';
47
48
  /** Subset of `ScopeResolver` consumed by this pass. Accepting the
48
49
  * subset rather than the full provider keeps tests and partial
49
50
  * refactors lighter — callers only need to populate what we read. */
50
- type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'unwrapCollectionAccessor' | 'hoistTypeBindingsToModule' | 'resolveQualifiedReceiverMember' | 'resolveReceiverMember' | 'resolveThisViaEnclosingClass' | 'conversionRankFn' | 'constraintCompatibility' | 'isStaticOnly'>;
51
+ type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'unwrapCollectionAccessor' | 'hoistTypeBindingsToModule' | 'resolveQualifiedReceiverMember' | 'resolveReceiverMember' | 'resolveThisViaEnclosingClass' | 'conversionRankFn' | 'conversionOnlyArgTypePrefixes' | 'constraintCompatibility' | 'isStaticOnly'>;
51
52
  export declare function emitReceiverBoundCalls(graph: KnowledgeGraph, scopes: ScopeResolutionIndexes, parsedFiles: readonly ParsedFile[], nodeLookup: GraphNodeLookup, handledSites: Set<string>, provider: ReceiverBoundProviderSubset, index: WorkspaceResolutionIndex, model: SemanticModel, options?: {
52
53
  readonly recordResolutionOutcome?: ResolutionOutcomeRecorder;
54
+ /** Resolved-callee-id capture sink (#2227 U2). Threaded in only under
55
+ * `--pdg`; `undefined` ⇒ zero overhead, byte-identity (R4). Per-file
56
+ * capture contexts are built from this + `parsed.filePath` in the loop. */
57
+ readonly calleeIdSink?: CalleeIdSink;
53
58
  }): number;
54
59
  /**
55
60
  * Sentinel returned by `pickOverload` when narrowing leaves >1 candidate
@@ -38,7 +38,7 @@
38
38
  */
39
39
  import { collectNamespaceTargets } from '../scope/namespace-targets.js';
40
40
  import { findClassBindingInScope, findEnclosingClassDef, findExportedDef, findOwnedMember, findReceiverTypeBinding, findValueBindingInScope, isClassLike, } from '../scope/walkers.js';
41
- import { tryEmitEdge, tryEmitEdgeWithExplicitTargetId } from '../graph-bridge/edges.js';
41
+ import { tryEmitEdge, tryEmitEdgeWithExplicitTargetId, } from '../graph-bridge/edges.js';
42
42
  import { resolveCompoundReceiverClass } from '../passes/compound-receiver.js';
43
43
  import { resolveDefGraphId } from '../graph-bridge/ids.js';
44
44
  import { narrowOverloadCandidates, isOverloadAmbiguousAfterNormalization, } from './overload-narrowing.js';
@@ -130,7 +130,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
130
130
  * when the primary receiver-typed edge targeted an Interface's
131
131
  * method. Each implementing class's same-named method gets a
132
132
  * secondary edge (excluding the primary target itself). */
133
- const emitInterfaceDispatchFor = (ownerDef, memberName, primaryMemberDef, site, confidence) => {
133
+ const emitInterfaceDispatchFor = (ownerDef, memberName, primaryMemberDef, site, confidence, calleeCapture) => {
134
134
  if (ownerDef.type !== 'Interface')
135
135
  return 0;
136
136
  const impls = implementorsByInterfaceDefId.get(ownerDef.nodeId);
@@ -138,12 +138,15 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
138
138
  return 0;
139
139
  let n = 0;
140
140
  for (const implDef of impls) {
141
- const implMember = findOwnedMember(implDef.nodeId, memberName, model);
142
- if (implMember === undefined)
141
+ const implMember = pickOverload(implDef.nodeId, memberName, site, model, provider);
142
+ if (implMember === undefined ||
143
+ implMember === OVERLOAD_AMBIGUOUS ||
144
+ implMember.isDeleted === true) {
143
145
  continue;
146
+ }
144
147
  if (implMember.nodeId === primaryMemberDef.nodeId)
145
148
  continue;
146
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, implMember, 'interface-dispatch', seen, confidence, collapse);
149
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, implMember, 'interface-dispatch', seen, confidence, collapse, calleeCapture);
147
150
  if (ok)
148
151
  n++;
149
152
  }
@@ -151,6 +154,12 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
151
154
  };
152
155
  for (const parsed of parsedFiles) {
153
156
  const namespaceTargets = collectNamespaceTargets(parsed, scopes);
157
+ // Per-file resolved-callee-id capture context (#2227 U2). Built once per
158
+ // file; `undefined` when the sink is absent (pdg off) so the `tryEmitEdge`
159
+ // capture is a no-op and emission stays byte-identical (R4).
160
+ const calleeCapture = options.calleeIdSink !== undefined
161
+ ? { sink: options.calleeIdSink, filePath: parsed.filePath }
162
+ : undefined;
154
163
  for (const site of parsed.referenceSites) {
155
164
  if (site.kind !== 'call' && site.kind !== 'read' && site.kind !== 'write')
156
165
  continue;
@@ -179,12 +188,30 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
179
188
  ? extendsOnly(enclosingClass.nodeId)
180
189
  : scopes.methodDispatch.mroFor(enclosingClass.nodeId);
181
190
  let memberDef;
191
+ let ambiguousOwnerId;
182
192
  for (const ownerId of ancestors) {
183
- memberDef = findOwnedMember(ownerId, memberName, model);
184
- if (memberDef !== undefined)
193
+ const picked = site.kind === 'call'
194
+ ? pickOverload(ownerId, memberName, site, model, provider)
195
+ : findOwnedMember(ownerId, memberName, model);
196
+ if (picked === OVERLOAD_AMBIGUOUS) {
197
+ ambiguousOwnerId = ownerId;
198
+ break;
199
+ }
200
+ if (picked !== undefined) {
201
+ memberDef = picked;
185
202
  break;
203
+ }
204
+ }
205
+ if (ambiguousOwnerId !== undefined) {
206
+ recordReceiverOverloadSuppression(options.recordResolutionOutcome, parsed.filePath, site, ambiguousOwnerId, memberName, model, provider);
207
+ handledSites.add(siteKey);
208
+ continue;
186
209
  }
187
210
  if (memberDef !== undefined) {
211
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
212
+ handledSites.add(siteKey);
213
+ continue;
214
+ }
188
215
  // Super/base calls resolve through the MRO chain, not
189
216
  // through imports — the ancestor method is found by
190
217
  // walking `methodDispatch.mroFor(enclosingClass)`, which
@@ -201,7 +228,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
201
228
  // superclass via its `import`/`from … import …` binding.
202
229
  // Closing that gap requires realigning the legacy tier
203
230
  // classifier and is tracked separately.
204
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, 'global', seen, 0.85, collapse);
231
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, 'global', seen, 0.85, collapse, calleeCapture);
205
232
  if (ok)
206
233
  emitted++;
207
234
  // Always mark handled when the site was resolved, even
@@ -219,9 +246,9 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
219
246
  if (currentClass !== undefined) {
220
247
  const chain = [currentClass.nodeId, ...scopes.methodDispatch.mroFor(currentClass.nodeId)];
221
248
  let memberDef;
249
+ let ambiguousOwnerId;
222
250
  // Static-only filter (#1756 / U3): same shape as Case 4's
223
- // chain walk (skip-and-walk-on) but without overload
224
- // narrowing — Case 0 uses `findOwnedMember` directly. When
251
+ // overload-aware chain walk (skip-and-walk-on). When
225
252
  // an owner's resolved candidate is static-only (Kotlin
226
253
  // companion-promoted), continue to the next ancestor in
227
254
  // the MRO chain so a legitimate instance member can bind.
@@ -233,18 +260,30 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
233
260
  // shapes like `Logger.create("a")`), so there's no wrong
234
261
  // target to suppress.
235
262
  for (const ownerId of chain) {
236
- const candidate = findOwnedMember(ownerId, memberName, model);
237
- if (candidate === undefined)
238
- continue;
239
- if (provider.isStaticOnly?.(candidate) === true) {
240
- // Skip static-only candidate; walk to next ancestor.
263
+ const picked = site.kind === 'call'
264
+ ? pickFirstNonStaticOnly(ownerId, memberName, site, model, provider)
265
+ : findOwnedMember(ownerId, memberName, model);
266
+ if (picked === OVERLOAD_AMBIGUOUS) {
267
+ ambiguousOwnerId = ownerId;
268
+ break;
269
+ }
270
+ if (picked === STATIC_ONLY_FILTERED || picked === undefined) {
241
271
  continue;
242
272
  }
243
- memberDef = candidate;
273
+ memberDef = picked;
244
274
  break;
245
275
  }
276
+ if (ambiguousOwnerId !== undefined) {
277
+ recordReceiverOverloadSuppression(options.recordResolutionOutcome, parsed.filePath, site, ambiguousOwnerId, memberName, model, provider);
278
+ handledSites.add(siteKey);
279
+ continue;
280
+ }
246
281
  if (memberDef !== undefined) {
247
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse);
282
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
283
+ handledSites.add(siteKey);
284
+ continue;
285
+ }
286
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse, calleeCapture);
248
287
  if (ok)
249
288
  emitted++;
250
289
  // Always mark handled when the site was resolved, even
@@ -290,13 +329,17 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
290
329
  }
291
330
  if (languageResolution?.kind === 'resolved') {
292
331
  const memberDef = languageResolution.definition;
332
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
333
+ handledSites.add(siteKey);
334
+ continue;
335
+ }
293
336
  const reason = site.kind === 'write' || site.kind === 'read'
294
337
  ? site.kind
295
338
  : memberDef.filePath !== parsed.filePath
296
339
  ? 'import-resolved'
297
340
  : 'global';
298
341
  const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
299
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse);
342
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse, calleeCapture);
300
343
  if (ok)
301
344
  emitted++;
302
345
  handledSites.add(siteKey);
@@ -315,6 +358,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
315
358
  const narrowed = narrowOverloadCandidates(methodOverloads, site.arity, site.argumentTypes, {
316
359
  argumentTypeClasses: site.argumentTypeClasses,
317
360
  conversionRankFn: provider.conversionRankFn,
361
+ conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
318
362
  constraintCompatibility: provider.constraintCompatibility,
319
363
  });
320
364
  if (isOverloadAmbiguousAfterNormalization(narrowed, site.arity)) {
@@ -357,13 +401,17 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
357
401
  continue;
358
402
  }
359
403
  if (memberDef !== undefined) {
404
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
405
+ handledSites.add(siteKey);
406
+ continue;
407
+ }
360
408
  const reason = site.kind === 'write' || site.kind === 'read'
361
409
  ? site.kind
362
410
  : memberDef.filePath !== parsed.filePath
363
411
  ? 'import-resolved'
364
412
  : 'global';
365
413
  const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
366
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse);
414
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse, calleeCapture);
367
415
  if (ok)
368
416
  emitted++;
369
417
  handledSites.add(siteKey);
@@ -373,12 +421,17 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
373
421
  }
374
422
  // ── Case 1: namespace receiver ───────────────────────────────
375
423
  const targetFiles = namespaceTargets.get(receiverName);
376
- if (targetFiles !== undefined) {
424
+ if (targetFiles !== undefined && provider.resolveQualifiedReceiverMember === undefined) {
377
425
  let found = false;
378
426
  for (const targetFile of targetFiles) {
379
427
  const memberDef = findExportedDef(targetFile, memberName, index);
380
428
  if (memberDef !== undefined) {
381
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse);
429
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
430
+ handledSites.add(siteKey);
431
+ found = true;
432
+ break;
433
+ }
434
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse, calleeCapture);
382
435
  if (ok)
383
436
  emitted++;
384
437
  handledSites.add(siteKey);
@@ -413,7 +466,11 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
413
466
  continue;
414
467
  }
415
468
  if (memberDef !== undefined) {
416
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse);
469
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
470
+ handledSites.add(siteKey);
471
+ continue;
472
+ }
473
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse, calleeCapture);
417
474
  if (ok)
418
475
  emitted++;
419
476
  handledSites.add(siteKey);
@@ -425,9 +482,17 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
425
482
  if (classDef !== undefined) {
426
483
  const chain = [classDef.nodeId, ...scopes.methodDispatch.mroFor(classDef.nodeId)];
427
484
  let memberDef;
485
+ let ambiguousOwnerId;
428
486
  for (const ownerId of chain) {
429
- memberDef = findOwnedMember(ownerId, memberName, model);
430
- if (memberDef !== undefined) {
487
+ const picked = site.kind === 'call'
488
+ ? pickOverload(ownerId, memberName, site, model, provider)
489
+ : findOwnedMember(ownerId, memberName, model);
490
+ if (picked === OVERLOAD_AMBIGUOUS) {
491
+ ambiguousOwnerId = ownerId;
492
+ break;
493
+ }
494
+ if (picked !== undefined) {
495
+ memberDef = picked;
431
496
  // The MRO chain is most-derived-first ([classDef, ...ancestors]).
432
497
  // If the most-derived definition is arity-incompatible with the
433
498
  // call site, PHP throws ArgumentCountError at runtime — it does
@@ -441,14 +506,23 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
441
506
  break;
442
507
  }
443
508
  }
509
+ if (ambiguousOwnerId !== undefined) {
510
+ recordReceiverOverloadSuppression(options.recordResolutionOutcome, parsed.filePath, site, ambiguousOwnerId, memberName, model, provider);
511
+ handledSites.add(siteKey);
512
+ continue;
513
+ }
444
514
  if (memberDef !== undefined) {
515
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
516
+ handledSites.add(siteKey);
517
+ continue;
518
+ }
445
519
  const reason = site.kind === 'write' || site.kind === 'read'
446
520
  ? site.kind
447
521
  : memberDef.filePath !== parsed.filePath
448
522
  ? 'import-resolved'
449
523
  : 'global';
450
524
  const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
451
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse);
525
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse, calleeCapture);
452
526
  if (ok)
453
527
  emitted++;
454
528
  handledSites.add(siteKey);
@@ -466,9 +540,26 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
466
540
  for (const targetFile3 of targetFiles3) {
467
541
  const classDef3 = findExportedDef(targetFile3, className, index);
468
542
  if (classDef3 !== undefined) {
469
- const memberDef = findOwnedMember(classDef3.nodeId, memberName, model);
470
- if (memberDef !== undefined) {
471
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen);
543
+ const picked = site.kind === 'call'
544
+ ? pickOverload(classDef3.nodeId, memberName, site, model, provider)
545
+ : findOwnedMember(classDef3.nodeId, memberName, model);
546
+ if (picked === OVERLOAD_AMBIGUOUS) {
547
+ recordReceiverOverloadSuppression(options.recordResolutionOutcome, parsed.filePath, site, classDef3.nodeId, memberName, model, provider);
548
+ handledSites.add(siteKey);
549
+ found3 = true;
550
+ break;
551
+ }
552
+ if (picked !== undefined) {
553
+ const memberDef = picked;
554
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
555
+ handledSites.add(siteKey);
556
+ found3 = true;
557
+ break;
558
+ }
559
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen,
560
+ // Explicit defaults so the trailing capture ctx (#2227 U2) can
561
+ // be threaded without changing dedup/confidence behavior.
562
+ 0.85, false, calleeCapture);
472
563
  if (ok) {
473
564
  emitted++;
474
565
  handledSites.add(siteKey);
@@ -504,8 +595,9 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
504
595
  if (ownerDef !== undefined) {
505
596
  const chain = [ownerDef.nodeId, ...scopes.methodDispatch.mroFor(ownerDef.nodeId)];
506
597
  let memberDef;
507
- // Static-only filter (#1756 / U3): mirrors Case 0's chain
508
- // walk `findOwnedMember` without overload narrowing. When
598
+ let ambiguousOwnerId;
599
+ // Static-only filter (#1756 / U3): mirrors Case 0's
600
+ // overload-aware chain walk. When
509
601
  // a static-only candidate is found at an ancestor, walk on
510
602
  // so a legitimate instance member can bind. If the entire
511
603
  // chain is static-only, no edge is emitted (Case 3b is fed
@@ -513,17 +605,30 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
513
605
  // `emitReferencesViaLookup` for compound shapes, so no
514
606
  // handled-site marker is needed for chain-only-static).
515
607
  for (const ownerId of chain) {
516
- const candidate = findOwnedMember(ownerId, memberName, model);
517
- if (candidate === undefined)
518
- continue;
519
- if (provider.isStaticOnly?.(candidate) === true) {
608
+ const picked = site.kind === 'call'
609
+ ? pickFirstNonStaticOnly(ownerId, memberName, site, model, provider)
610
+ : findOwnedMember(ownerId, memberName, model);
611
+ if (picked === OVERLOAD_AMBIGUOUS) {
612
+ ambiguousOwnerId = ownerId;
613
+ break;
614
+ }
615
+ if (picked === STATIC_ONLY_FILTERED || picked === undefined) {
520
616
  continue;
521
617
  }
522
- memberDef = candidate;
618
+ memberDef = picked;
523
619
  break;
524
620
  }
621
+ if (ambiguousOwnerId !== undefined) {
622
+ recordReceiverOverloadSuppression(options.recordResolutionOutcome, parsed.filePath, site, ambiguousOwnerId, memberName, model, provider);
623
+ handledSites.add(siteKey);
624
+ continue;
625
+ }
525
626
  if (memberDef !== undefined) {
526
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse);
627
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
628
+ handledSites.add(siteKey);
629
+ continue;
630
+ }
631
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, memberDef.filePath !== parsed.filePath ? 'import-resolved' : 'global', seen, 0.85, collapse, calleeCapture);
527
632
  if (ok)
528
633
  emitted++;
529
634
  // Always mark handled when the site was resolved, even
@@ -574,13 +679,17 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
574
679
  }
575
680
  if (languageResolution?.kind === 'resolved') {
576
681
  const memberDef = languageResolution.definition;
682
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
683
+ handledSites.add(siteKey);
684
+ continue;
685
+ }
577
686
  const reason = site.kind === 'write' || site.kind === 'read'
578
687
  ? site.kind
579
688
  : memberDef.filePath !== parsed.filePath
580
689
  ? 'import-resolved'
581
690
  : 'global';
582
691
  const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
583
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse);
692
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse, calleeCapture);
584
693
  if (ok)
585
694
  emitted++;
586
695
  handledSites.add(siteKey);
@@ -657,6 +766,10 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
657
766
  continue;
658
767
  }
659
768
  if (memberDef !== undefined) {
769
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, memberDef)) {
770
+ handledSites.add(siteKey);
771
+ continue;
772
+ }
660
773
  // For read/write ACCESSES, mirror the legacy DAG's reason
661
774
  // convention so consumers asserting `reason === 'write'`
662
775
  // keep working.
@@ -666,13 +779,13 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
666
779
  ? 'import-resolved'
667
780
  : 'global';
668
781
  const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
669
- const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse);
782
+ const ok = tryEmitEdge(graph, scopes, nodeLookup, site, memberDef, reason, seen, confidence, collapse, calleeCapture);
670
783
  if (ok)
671
784
  emitted++;
672
785
  // Interface dispatch: when the primary owner is an
673
786
  // Interface, emit secondary CALLS edges to every
674
787
  // implementing class's same-named method.
675
- emitted += emitInterfaceDispatchFor(ownerDef, memberName, memberDef, site, confidence);
788
+ emitted += emitInterfaceDispatchFor(ownerDef, memberName, memberDef, site, confidence, calleeCapture);
676
789
  // Always mark handled when the site was resolved, even
677
790
  // if the edge was deduplicated (collapse mode), so
678
791
  // `emitReferencesViaLookup` doesn't re-emit from the
@@ -713,6 +826,10 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
713
826
  continue;
714
827
  }
715
828
  if (picked !== undefined) {
829
+ if (suppressDeletedCallTarget(options.recordResolutionOutcome, parsed.filePath, site, picked)) {
830
+ handledSites.add(siteKey);
831
+ continue;
832
+ }
716
833
  // Static-only filter (#1756 / U3): unlike Case 4 there's no
717
834
  // MRO chain to walk here — Case 5 dispatches on a single
718
835
  // owner via `pickOverload`. When the picked candidate is
@@ -732,7 +849,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
732
849
  ? 'import-resolved'
733
850
  : 'global';
734
851
  const confidence = site.kind === 'write' || site.kind === 'read' ? 1.0 : 0.85;
735
- const ok = tryEmitEdgeWithExplicitTargetId(graph, scopes, nodeLookup, site, picked.nodeId, reason, seen, confidence, collapse);
852
+ const ok = tryEmitEdgeWithExplicitTargetId(graph, scopes, nodeLookup, site, picked.nodeId, reason, seen, confidence, collapse, calleeCapture);
736
853
  if (ok)
737
854
  emitted++;
738
855
  handledSites.add(siteKey);
@@ -760,6 +877,7 @@ function pickOverload(ownerId, memberName, site, model, provider) {
760
877
  const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
761
878
  argumentTypeClasses: site.argumentTypeClasses,
762
879
  conversionRankFn: provider.conversionRankFn,
880
+ conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
763
881
  constraintCompatibility: provider.constraintCompatibility,
764
882
  });
765
883
  // When narrowing leaves >1 candidate that share identical normalized
@@ -860,6 +978,7 @@ function pickFirstNonStaticOnly(ownerId, memberName, site, model, provider) {
860
978
  const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
861
979
  argumentTypeClasses: site.argumentTypeClasses,
862
980
  conversionRankFn: provider.conversionRankFn,
981
+ conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
863
982
  constraintCompatibility: provider.constraintCompatibility,
864
983
  });
865
984
  // Same ambiguity handling as `pickOverload`: when normalization
@@ -873,6 +992,20 @@ function pickFirstNonStaticOnly(ownerId, memberName, site, model, provider) {
873
992
  return OVERLOAD_AMBIGUOUS;
874
993
  return candidates[0] ?? overloads[0];
875
994
  }
995
+ function suppressDeletedCallTarget(record, filePath, site, target) {
996
+ if (site.kind !== 'call' || target.isDeleted !== true)
997
+ return false;
998
+ record?.({
999
+ kind: 'suppressed',
1000
+ phase: 'receiver-bound-calls',
1001
+ filePath,
1002
+ name: site.name,
1003
+ range: site.atRange,
1004
+ reason: 'selected-callable-deleted',
1005
+ candidateIds: [target.nodeId],
1006
+ });
1007
+ return true;
1008
+ }
876
1009
  function recordReceiverOverloadSuppression(record, filePath, site, ownerId, memberName, model, provider) {
877
1010
  if (record === undefined)
878
1011
  return;
@@ -880,6 +1013,7 @@ function recordReceiverOverloadSuppression(record, filePath, site, ownerId, memb
880
1013
  const candidates = narrowOverloadCandidates(overloads, site.arity, site.argumentTypes, {
881
1014
  argumentTypeClasses: site.argumentTypeClasses,
882
1015
  conversionRankFn: provider.conversionRankFn,
1016
+ conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
883
1017
  constraintCompatibility: provider.constraintCompatibility,
884
1018
  });
885
1019
  const reason = isOverloadAmbiguousAfterNormalization(candidates, site.arity)