gitnexus 1.6.8-rc.8 → 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 (439) 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 +23 -2
  135. package/dist/core/ingestion/languages/c-cpp.js +17 -5
  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 +8 -1
  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 +44 -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/clone-safety.d.ts +109 -0
  238. package/dist/core/ingestion/workers/clone-safety.js +465 -0
  239. package/dist/core/ingestion/workers/parse-worker.d.ts +23 -0
  240. package/dist/core/ingestion/workers/parse-worker.js +81 -53
  241. package/dist/core/ingestion/workers/post-result.d.ts +22 -0
  242. package/dist/core/ingestion/workers/post-result.js +87 -0
  243. package/dist/core/ingestion/workers/result-merge.d.ts +20 -0
  244. package/dist/core/ingestion/workers/result-merge.js +43 -0
  245. package/dist/core/ingestion/workers/worker-pool.d.ts +15 -40
  246. package/dist/core/ingestion/workers/worker-pool.js +43 -16
  247. package/dist/core/lbug/csv-generator.d.ts +51 -3
  248. package/dist/core/lbug/csv-generator.js +369 -255
  249. package/dist/core/lbug/lbug-adapter.d.ts +58 -18
  250. package/dist/core/lbug/lbug-adapter.js +346 -84
  251. package/dist/core/lbug/lbug-config.d.ts +19 -0
  252. package/dist/core/lbug/lbug-config.js +29 -0
  253. package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
  254. package/dist/core/lbug/pdg-emit-sink.js +358 -0
  255. package/dist/core/lbug/pool-adapter.d.ts +35 -0
  256. package/dist/core/lbug/pool-adapter.js +90 -1
  257. package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
  258. package/dist/core/lbug/rel-pair-routing.js +140 -0
  259. package/dist/core/lbug/schema.d.ts +2 -2
  260. package/dist/core/lbug/schema.js +3 -0
  261. package/dist/core/logger.d.ts +0 -5
  262. package/dist/core/run-analyze.d.ts +96 -0
  263. package/dist/core/run-analyze.js +207 -3
  264. package/dist/core/tree-sitter/parser-loader.js +5 -4
  265. package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
  266. package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
  267. package/dist/core/tree-sitter/vendored-grammars.js +57 -0
  268. package/dist/core/wiki/generator.js +3 -1
  269. package/dist/core/wiki/graph-queries.d.ts +6 -0
  270. package/dist/core/wiki/graph-queries.js +9 -1
  271. package/dist/mcp/http-transport.d.ts +134 -0
  272. package/dist/mcp/http-transport.js +503 -0
  273. package/dist/mcp/local/local-backend.d.ts +110 -24
  274. package/dist/mcp/local/local-backend.js +1225 -19
  275. package/dist/mcp/local/pdg-impact.d.ts +384 -0
  276. package/dist/mcp/local/pdg-impact.js +1972 -0
  277. package/dist/mcp/resources.js +13 -1
  278. package/dist/mcp/tools.d.ts +12 -0
  279. package/dist/mcp/tools.js +214 -7
  280. package/dist/server/analyze-launch.d.ts +29 -0
  281. package/dist/server/analyze-launch.js +137 -0
  282. package/dist/server/analyze-upload.d.ts +33 -0
  283. package/dist/server/analyze-upload.js +123 -0
  284. package/dist/server/analyze-worker-ipc.d.ts +58 -0
  285. package/dist/server/analyze-worker-ipc.js +16 -0
  286. package/dist/server/analyze-worker.d.ts +17 -1
  287. package/dist/server/analyze-worker.js +7 -1
  288. package/dist/server/api.d.ts +17 -0
  289. package/dist/server/api.js +132 -168
  290. package/dist/server/git-clone.d.ts +43 -2
  291. package/dist/server/git-clone.js +211 -16
  292. package/dist/server/mcp-http.d.ts +5 -6
  293. package/dist/server/mcp-http.js +9 -82
  294. package/dist/server/middleware.d.ts +40 -0
  295. package/dist/server/middleware.js +92 -0
  296. package/dist/server/private-ip.d.ts +1 -0
  297. package/dist/server/private-ip.js +15 -0
  298. package/dist/server/upload-ingest.d.ts +56 -0
  299. package/dist/server/upload-ingest.js +276 -0
  300. package/dist/server/upload-paths.d.ts +37 -0
  301. package/dist/server/upload-paths.js +57 -0
  302. package/dist/server/upload-sweep.d.ts +20 -0
  303. package/dist/server/upload-sweep.js +57 -0
  304. package/dist/storage/git.js +5 -8
  305. package/dist/storage/parse-cache.d.ts +22 -1
  306. package/dist/storage/parse-cache.js +44 -10
  307. package/dist/storage/repo-manager.d.ts +121 -10
  308. package/dist/storage/repo-manager.js +43 -5
  309. package/dist/types/pipeline.d.ts +9 -0
  310. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
  311. package/hooks/claude/gitnexus-hook.cjs +110 -13
  312. package/hooks/claude/hook-db-lock-probe.cjs +513 -26
  313. package/package.json +8 -2
  314. package/scripts/assert-publish-grammar-coverage.cjs +31 -0
  315. package/scripts/build-tree-sitter-grammars.cjs +16 -10
  316. package/scripts/cross-platform-tests.ts +1 -0
  317. package/skills/gitnexus-debugging.md +16 -4
  318. package/skills/gitnexus-exploring.md +3 -3
  319. package/skills/gitnexus-guide.md +33 -0
  320. package/skills/gitnexus-pdg-query.md +89 -0
  321. package/skills/gitnexus-refactoring.md +1 -1
  322. package/skills/gitnexus-taint-analysis.md +178 -0
  323. package/vendor/tree-sitter-c/package.json +1 -1
  324. package/vendor/tree-sitter-dart/package.json +1 -1
  325. package/vendor/tree-sitter-kotlin/package.json +1 -1
  326. package/vendor/tree-sitter-proto/package.json +1 -1
  327. package/vendor/tree-sitter-swift/package.json +1 -1
  328. package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
  329. package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
  330. package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
  331. package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
  332. package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
  333. package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
  334. package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
  335. package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
  336. package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
  337. package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
  338. package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
  339. package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
  340. package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
  341. package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
  342. package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
  343. package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
  344. package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
  345. package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
  346. package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
  347. package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
  348. package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
  349. package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
  350. package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
  351. package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
  352. package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
  353. package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
  354. package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
  355. package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
  356. package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
  357. package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
  358. package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
  359. package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
  360. package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
  361. package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
  362. package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
  363. package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
  364. package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
  365. package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
  366. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
  367. package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
  368. package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
  369. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
  370. package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
  371. package/web/assets/index-BvYev1UJ.js +635 -0
  372. package/web/assets/index-_lgn7hs5.css +2 -0
  373. package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
  374. package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
  375. package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
  376. package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
  377. package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
  378. package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
  379. package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
  380. package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
  381. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
  382. package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
  383. package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
  384. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
  385. package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
  386. package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
  387. package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
  388. package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
  389. package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
  390. package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
  391. package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
  392. package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
  393. package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
  394. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
  395. package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
  396. package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
  397. package/web/index.html +13 -15
  398. package/scripts/materialize-vendor-grammars.cjs +0 -97
  399. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
  400. package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
  401. package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
  402. package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
  403. package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
  404. package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
  405. package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
  406. package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
  407. package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
  408. package/web/assets/chunk-CilyBKbf.js +0 -1
  409. package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
  410. package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
  411. package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
  412. package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
  413. package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
  414. package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
  415. package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
  416. package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
  417. package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
  418. package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
  419. package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
  420. package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
  421. package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
  422. package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
  423. package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
  424. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
  425. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
  426. package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
  427. package/web/assets/index-BKWA-m7o.css +0 -2
  428. package/web/assets/index-CG6q8eTs.js +0 -626
  429. package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
  430. package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
  431. package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
  432. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
  433. package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
  434. package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
  435. package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
  436. package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
  437. package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
  438. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
  439. /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
@@ -27,6 +27,9 @@ import type { KnowledgeGraph } from '../../../graph/types.js';
27
27
  import type { MutableSemanticModel } from '../../model/semantic-model.js';
28
28
  import { type ResolveStats } from '../../resolve-references.js';
29
29
  import { buildGraphNodeLookup } from '../graph-bridge/node-lookup.js';
30
+ import { type FunctionNodeIndex } from '../../taint/summary-harvest-driver.js';
31
+ import type { FunctionSummary } from '../../taint/summary-model.js';
32
+ import type { CallSummary } from '../../taint/call-summary-model.js';
30
33
  import type { ScopeResolver } from '../contract/scope-resolver.js';
31
34
  import type { ResolutionOutcome, ResolutionOutcomeRecorder } from '../resolution-outcome.js';
32
35
  export type ScopeResolutionSubPhase = 'extracting' | 'analyzing types' | 'resolving references' | 'linking symbols';
@@ -58,6 +61,54 @@ interface RunScopeResolutionInput {
58
61
  readonly treeCache?: {
59
62
  get(filePath: string): unknown;
60
63
  };
64
+ /**
65
+ * CFG/PDG opt-in (#2081 M1). When true, emit BasicBlock nodes + CFG edges
66
+ * from each ParsedFile's worker-built `cfgSideChannel` during Phase-4 graph
67
+ * emission (while the disk store is still live). Default/false ⇒ no CFG
68
+ * nodes or edges and a byte-identical graph.
69
+ */
70
+ readonly pdg?: boolean;
71
+ /** Per-function CFG edge cap. `undefined` ⇒ {@link DEFAULT_MAX_CFG_EDGES_PER_FUNCTION};
72
+ * `0` ⇒ no cap (unlimited). */
73
+ readonly pdgMaxEdgesPerFunction?: number;
74
+ /** Per-function REACHING_DEF edge cap (#2082 M2). `undefined` ⇒
75
+ * {@link DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION}; `0` ⇒ no cap. */
76
+ readonly pdgMaxReachingDefEdgesPerFunction?: number;
77
+ /** Per-function CDG (control-dependence) edge cap (#2085 M5). `undefined` ⇒
78
+ * {@link DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION}; `0` ⇒ no cap. */
79
+ readonly pdgMaxCdgEdgesPerFunction?: number;
80
+ /** Per-function taint findings cap (#2083 M3, consumed by the U4 taint
81
+ * emit step in the pdg window). `undefined` ⇒
82
+ * `DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION` (200); `0` ⇒ no cap. */
83
+ readonly pdgMaxTaintFindingsPerFunction?: number;
84
+ /** Per-finding taint hop cap (#2083 M3 KTD6 — bounds the hop-encoded
85
+ * `reason`; consumed by the U4 taint emit step). `undefined` ⇒
86
+ * `DEFAULT_PDG_MAX_TAINT_HOPS` (32); `0` ⇒ no cap. */
87
+ readonly pdgMaxTaintHops?: number;
88
+ /**
89
+ * Streaming PDG-emit sink (#2202). When present (streaming on, full rebuild),
90
+ * the `--pdg` emit routes BasicBlock nodes + intra-file PDG edges to THIS
91
+ * graph-shaped target instead of the in-memory `graph`, so the bulky PDG
92
+ * layer never accumulates in memory (peak RSS O(chunk)). Typed as a plain
93
+ * `KnowledgeGraph` so this module stays decoupled from the persistence layer;
94
+ * the caller (the scope-resolution phase) owns its lifecycle and finalizes it
95
+ * after the last language. Absent ⇒ the emit writes to `graph` as before
96
+ * (byte-identical default).
97
+ */
98
+ readonly pdgEmitSink?: KnowledgeGraph;
99
+ /**
100
+ * Cross-pass per-file dedup set for streaming PDG emit (#2202). Shared across
101
+ * every language pass (owned by the scope-resolution phase). A file imported
102
+ * by more than one language (e.g. a `.ts` module pulled into the Vue context
103
+ * pass) is PDG-emitted in each pass over the same `cfgSideChannel`, producing
104
+ * identical ids; the in-memory graph dedups that by id, but the streaming sink
105
+ * is dedup-free (to stay O(write buffer), not O(total ids)). So when present
106
+ * (streaming on), the emit loop skips a file whose PDG already streamed and
107
+ * records the rest — keeping the streamed set byte-identical to the
108
+ * Map-deduped whole-graph emit, for any language-pass order. Absent ⇒ no skip
109
+ * (the graph Map dedups), so the default path is unchanged.
110
+ */
111
+ readonly pdgEmittedFiles?: Set<string>;
61
112
  /**
62
113
  * Optional graph-node lookup built ONCE by the caller and shared across
63
114
  * every language pass. `buildGraphNodeLookup` scans the whole graph and is
@@ -70,6 +121,14 @@ interface RunScopeResolutionInput {
70
121
  * base is safe.
71
122
  */
72
123
  readonly prebuiltNodeLookup?: ReturnType<typeof buildGraphNodeLookup>;
124
+ /**
125
+ * Functionish-node index built ONCE by the caller and shared across every
126
+ * language pass (#2084 review P2-6). Like `prebuiltNodeLookup`,
127
+ * `buildFunctionNodeIndex` is a whole-graph scan and is language-agnostic, so
128
+ * rebuilding it per language wastes a full scan each time. When omitted
129
+ * (tests / isolated calls) it is built locally for the pdg-enabled language.
130
+ */
131
+ readonly prebuiltFunctionNodeIndex?: FunctionNodeIndex;
73
132
  /**
74
133
  * Opaque per-language import-resolution config (e.g. tsconfig path
75
134
  * aliases for TypeScript). Loaded once by the caller via
@@ -127,6 +186,22 @@ interface RunScopeResolutionStats {
127
186
  readonly referenceEdgesEmitted: number;
128
187
  readonly referenceSkipped: number;
129
188
  readonly resolutionOutcomes: readonly ResolutionOutcome[];
189
+ /**
190
+ * Per-function taint summaries harvested in the pdg window (#2084 M4 U1).
191
+ * Empty unless `input.pdg === true` and the language has a registered taint
192
+ * model. Keyed by resolved `Function`/`Method` node id; the cross-function
193
+ * fixpoint phase composes them over the complete `CALLS` graph.
194
+ */
195
+ readonly functionSummaries: readonly FunctionSummary[];
196
+ /**
197
+ * Per-function RETURN-VALUE ASCENT summaries harvested in the pdg window
198
+ * (PDG FU-C, U-C2). Empty unless `input.pdg === true`. Keyed by resolved
199
+ * `Function`/`Method`/`Constructor` node id; the whole-program CALL_SUMMARY
200
+ * emit phase materialises one self-loop edge per entry once the call graph is
201
+ * known. Unlike {@link functionSummaries} this needs NO taint model — it is
202
+ * pure data-dependence — so it is harvested for every `--pdg` language.
203
+ */
204
+ readonly callSummaries: readonly CallSummary[];
130
205
  }
131
206
  export declare function runScopeResolution(input: RunScopeResolutionInput, provider: ScopeResolver): RunScopeResolutionStats;
132
207
  export {};
@@ -30,12 +30,20 @@ import { extractParsedFile } from '../../scope-extractor-bridge.js';
30
30
  import { finalizeScopeModel } from '../../finalize-orchestrator.js';
31
31
  import { resolveReferenceSites } from '../../resolve-references.js';
32
32
  import { buildGraphNodeLookup } from '../graph-bridge/node-lookup.js';
33
+ import { emitFileCfgs, emitFileReachingDefs, emitFileCdg, isEmitSafeCfg, DEFAULT_MAX_CFG_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION, REACHING_DEF_FACTS_PER_EDGE_CAP, } from '../../cfg/emit.js';
34
+ import { createMemoizedReachingDefs } from '../../cfg/reaching-defs.js';
35
+ import { emitFileTaint, DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from '../../taint/emit.js';
36
+ import { registerBuiltinTaintModels } from '../../taint/typescript-model.js';
37
+ import { getSourceSinkConfig } from '../../taint/source-sink-registry.js';
38
+ import { buildFunctionNodeIndex, harvestFileSummaries, } from '../../taint/summary-harvest-driver.js';
39
+ import { harvestFileCallSummaries } from '../../taint/summary-harvest-driver.js';
33
40
  import { resolveDefGraphId } from '../graph-bridge/ids.js';
34
41
  import { buildPopulatedMethodDispatch } from '../graph-bridge/method-dispatch.js';
35
42
  import { propagateImportedReturnTypes } from '../passes/imported-return-types.js';
36
43
  import { emitReceiverBoundCalls } from '../passes/receiver-bound-calls.js';
37
44
  import { emitFreeCallFallback } from '../passes/free-call-fallback.js';
38
45
  import { emitReferencesViaLookup } from '../graph-bridge/references-to-edges.js';
46
+ import { createCalleeIdAccumulator, } from '../graph-bridge/callee-id-sink.js';
39
47
  import { emitImportEdges } from '../graph-bridge/imports-to-edges.js';
40
48
  import { findEnclosingClassDef, resolveInheritanceBaseInScope } from '../scope/walkers.js';
41
49
  import { buildWorkspaceResolutionIndex } from '../workspace-index.js';
@@ -286,6 +294,8 @@ export function runScopeResolution(input, provider) {
286
294
  referenceEdgesEmitted: 0,
287
295
  referenceSkipped: 0,
288
296
  resolutionOutcomes,
297
+ functionSummaries: [],
298
+ callSummaries: [],
289
299
  };
290
300
  }
291
301
  const tExtract = PROF ? process.hrtime.bigint() : 0n;
@@ -427,8 +437,15 @@ export function runScopeResolution(input, provider) {
427
437
  // ── Phase 4: emit graph edges (LOAD-BEARING ORDER — see I1) ────────────
428
438
  input.onProgress?.('linking symbols', files.length, files.length);
429
439
  const handledSites = new Set(preEmittedInheritanceSites);
440
+ // Resolved-callee-id capture accumulator (#2227 U2). Created ONLY under
441
+ // `--pdg` — `undefined` otherwise so the three emitters do zero work and emit
442
+ // byte-identical output (R4). Populated below at all three CALLS emit paths
443
+ // (each before its dedup, KTD6/R8); consumed by the CFG-emit join (U3) at
444
+ // `emitFileCfgs` below to produce `BasicBlock.calleeIds`.
445
+ const calleeIdAccumulator = input.pdg === true ? createCalleeIdAccumulator() : undefined;
430
446
  const receiverExtras = emitReceiverBoundCalls(graph, indexes, emitParsedFiles, postHeritageNodeLookup, handledSites, provider, workspaceIndex, readonlyModel, {
431
447
  recordResolutionOutcome,
448
+ calleeIdSink: calleeIdAccumulator,
432
449
  });
433
450
  const unresolvedReceiverExtras = provider.emitUnresolvedReceiverEdges !== undefined
434
451
  ? provider.emitUnresolvedReceiverEdges(graph, indexes, emitParsedFiles, postHeritageNodeLookup, handledSites, readonlyModel)
@@ -440,10 +457,12 @@ export function runScopeResolution(input, provider) {
440
457
  isCallableVisibleFromCaller: provider.isCallableVisibleFromCaller,
441
458
  resolveAdlCandidates: provider.resolveAdlCandidates,
442
459
  conversionRankFn: provider.conversionRankFn,
460
+ conversionOnlyArgTypePrefixes: provider.conversionOnlyArgTypePrefixes,
443
461
  constraintCompatibility: provider.constraintCompatibility,
444
462
  recordResolutionOutcome,
463
+ calleeIdSink: calleeIdAccumulator,
445
464
  });
446
- const { emitted, skipped } = emitReferencesViaLookup(graph, indexes, referenceIndex, postHeritageNodeLookup, handledSites);
465
+ const { emitted, skipped } = emitReferencesViaLookup(graph, indexes, referenceIndex, postHeritageNodeLookup, handledSites, calleeIdAccumulator);
447
466
  const importsEmitted = emitImportEdges(graph, indexes.imports, indexes.scopeTree, provider.importEdgeReason);
448
467
  // Language-specific supplementary edges (e.g. Vue template-derived
449
468
  // BINDS_EVENT_HANDLER / EMITS_EVENT / CALLS / ACCESSES edges).
@@ -454,6 +473,330 @@ export function runScopeResolution(input, provider) {
454
473
  resolutionConfig,
455
474
  });
456
475
  }
476
+ // ── CFG/PDG emission (#2081 M1, opt-in via `--pdg`) ──────────────────────
477
+ // Emit BasicBlock nodes + CFG edges from each ParsedFile's worker-built
478
+ // `cfgSideChannel`, HERE — the last point inside scope-resolution where the
479
+ // ParsedFiles are still loaded (`emitParsedFiles` carries the channel; the
480
+ // disk store is cleared right after this orchestrator returns, see phase.ts).
481
+ // A post-`mro` phase would read empty data (KTD1). Off by default ⇒ zero
482
+ // BasicBlock/CFG nodes/edges and a byte-identical graph.
483
+ // Accumulated M2 reaching-defs time (solve + dedup + REACHING_DEF emit),
484
+ // reported as the PROF `pdg=` segment. It is a SUBSET of `emit=` — the M1
485
+ // CFG emit and the M2 solve interleave per file, so a separate checkpoint
486
+ // pair can't bracket them; without this accumulator the M2 cost would
487
+ // silently disappear into `emit=` and field regressions would be invisible.
488
+ let pdgMs = 0;
489
+ // M4 (#2084 U1): per-function taint summaries harvested in the pdg window,
490
+ // returned on the stats for the cross-function fixpoint phase. Function-scoped
491
+ // so the return (below the pdg block) can read it; empty on non-pdg runs.
492
+ const harvestedSummaries = [];
493
+ let summaryUnresolved = 0;
494
+ // FU-C (U-C2): per-function RETURN-VALUE ASCENT summaries harvested in the
495
+ // pdg window for the whole-program CALL_SUMMARY emit phase. Function-scoped
496
+ // (read by the return below the pdg block); empty on non-pdg runs.
497
+ const harvestedCallSummaries = [];
498
+ let callSummaryUnresolved = 0;
499
+ // M3 (#2083 U4): accumulated taint time (match + taint-side solve +
500
+ // propagate + TAINTED/SANITIZES emit), a sibling of `pdgMs` for the same
501
+ // reason — it interleaves per file inside `emit=`, so only an accumulator
502
+ // can bracket it. Printed as the PROF `taint=` segment.
503
+ let taintMs = 0;
504
+ if (input.pdg === true) {
505
+ // Streaming target (#2202): when a sink is provided, BasicBlock nodes +
506
+ // intra-file PDG edges are routed to CSV-on-disk through it instead of
507
+ // accumulating in `graph`. The function-node index below is still built
508
+ // from the real `graph` (Function/Method nodes live there, never the sink).
509
+ const pdgTarget = input.pdgEmitSink ?? graph;
510
+ let cfgBlocks = 0;
511
+ let cfgEdges = 0;
512
+ let cfgDroppedEdges = 0;
513
+ let rdEdges = 0;
514
+ let rdDropped = 0;
515
+ let rdFacts = 0;
516
+ let rdTruncated = 0;
517
+ let cdgEdges = 0;
518
+ let cdgDropped = 0;
519
+ let cdgSkippedUnsound = 0;
520
+ // ── M3 taint setup (#2083 U4) ────────────────────────────────────────
521
+ // Explicit model-registration seam (idempotent, cheap) — the registry
522
+ // stays empty on non-pdg runs, preserving default-run parity. The
523
+ // registry is keyed by `SupportedLanguages` enum VALUES ('typescript' /
524
+ // 'javascript'), and `ScopeResolver.language` IS a `SupportedLanguages`
525
+ // member registered under those same constants — the join is direct
526
+ // equality, no mapping table. A language without a registered spec
527
+ // (python, go, …) skips taint entirely: no work, no warn spam (KTD8).
528
+ registerBuiltinTaintModels();
529
+ const taintSpec = getSourceSinkConfig(provider.language);
530
+ // Taint-side solver fact cap: the SAME derivation emitFileReachingDefs
531
+ // uses for the RD projection (edge cap × headroom factor, 0 ⇒ unlimited),
532
+ // so taint coverage and RD coverage truncate together — a function is
533
+ // never a taint coverage gap while its RD projection computed, and the
534
+ // RD layer's per-function truncation warn already names it.
535
+ const rdEdgeCap = input.pdgMaxReachingDefEdgesPerFunction ?? DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION;
536
+ const taintLimits = {
537
+ maxFindingsPerFunction: input.pdgMaxTaintFindingsPerFunction ?? DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION,
538
+ maxHops: input.pdgMaxTaintHops ?? DEFAULT_PDG_MAX_TAINT_HOPS,
539
+ maxFacts: rdEdgeCap > 0 ? rdEdgeCap * REACHING_DEF_FACTS_PER_EDGE_CAP : 0,
540
+ };
541
+ // Cross-file aggregate of EVERY TaintEmitResult counter (the M2 emit
542
+ // result shipped with two fields dropped on the floor — R4 forbids that
543
+ // here; gaps/drops feed the unconditional warn below, volume feeds the
544
+ // per-language debug line).
545
+ const taintTotals = {
546
+ analyzed: 0,
547
+ noMatch: 0,
548
+ unsafeSites: 0,
549
+ gapTruncated: 0,
550
+ gapOverflow: 0,
551
+ gapNoFacts: 0,
552
+ findings: 0,
553
+ kills: 0,
554
+ dropped: 0,
555
+ hopsTruncated: 0,
556
+ gapExamples: [],
557
+ dropExamples: [],
558
+ };
559
+ // M4 (#2084 U1): per-function summary harvest. The functionish-node index
560
+ // is built ONCE (whole-graph scan) and reused across every file; summaries
561
+ // accumulate here and ride out on the stats for the cross-function fixpoint
562
+ // phase. Only built when the language has a registered taint model.
563
+ // Built whenever pdg is on (NOT gated on taintSpec): the FU-C call-summary
564
+ // harvest needs it for EVERY language (it is pure data-dependence, no taint
565
+ // model), and the taint summary harvest reuses it when taintSpec is present.
566
+ const fnNodeIndex = input.prebuiltFunctionNodeIndex ?? buildFunctionNodeIndex(graph);
567
+ for (const pf of emitParsedFiles) {
568
+ const cfgs = pf.cfgSideChannel;
569
+ // Defensive: cfgSideChannel is opaque (`unknown`) and crosses the cache /
570
+ // durable store. A stale or wrong-shape value (e.g. a pre-SCHEMA_BUMP
571
+ // shard that slipped the version gate) must skip emission, not throw a
572
+ // TypeError mid-graph-build and abort scope-resolution for the language.
573
+ if (!Array.isArray(cfgs) || cfgs.length === 0)
574
+ continue;
575
+ // Cross-pass per-file dedup (#2202): when streaming, a file whose PDG
576
+ // already streamed in a prior language pass (e.g. a `.ts` module pulled
577
+ // into the Vue context pass) would re-emit identical ids from the same
578
+ // cfgSideChannel — the dedup-free streaming sink would double the rows.
579
+ // Skip it here; the in-memory-graph path needs no skip (its Map dedups).
580
+ if (input.pdgEmittedFiles !== undefined) {
581
+ if (input.pdgEmittedFiles.has(pf.filePath))
582
+ continue;
583
+ input.pdgEmittedFiles.add(pf.filePath);
584
+ }
585
+ try {
586
+ // Per-element emit-safety filter (mirrors the parsedfile-store
587
+ // reviver's POLICY: valid elements in a mixed array still emit; junk
588
+ // is warned and skipped). isEmitSafeCfg lives in cfg/emit.ts next to
589
+ // the id templating it defends — see its doc for why anchor-field and
590
+ // endpoint-membership checks are load-bearing. Runs INSIDE the try so
591
+ // even a predicate-time throw (e.g. a hostile getter) is isolated.
592
+ const wellFormed = cfgs.filter(isEmitSafeCfg);
593
+ if (wellFormed.length < cfgs.length) {
594
+ logger.warn(`[cfg] ${pf.filePath}: skipped ${cfgs.length - wellFormed.length} malformed ` +
595
+ `cfgSideChannel element(s) (bad shape, missing id-anchor fields, or edge ` +
596
+ `endpoints matching no block) — CFG for those functions omitted`);
597
+ }
598
+ if (wellFormed.length === 0)
599
+ continue;
600
+ // U3 hook (#2227): the resolved-callee-id map for this file is
601
+ // `calleeIdAccumulator?.get(pf.filePath)` — joined here by exact
602
+ // call-site position to emit `BasicBlock.calleeIds`. Captured above at
603
+ // the three CALLS emit paths (U2); wired into `emitFileCfgs` by U3.
604
+ const emitted = emitFileCfgs(pdgTarget, wellFormed, input.pdgMaxEdgesPerFunction ?? DEFAULT_MAX_CFG_EDGES_PER_FUNCTION,
605
+ // Log cap-overflow drops UNCONDITIONALLY (not via input.onWarn, which is
606
+ // gated behind the semantic-model validator and silent in production) so
607
+ // the per-function edge cap never truncates the CFG silently (R6/KTD6).
608
+ (message) => logger.warn(message),
609
+ // U3 (#2227): the resolved-callee-id map for this file (captured at the
610
+ // three CALLS emit paths in U2), joined by exact call-site position to
611
+ // emit `BasicBlock.calleeIds`. `undefined` when pdg is off (the
612
+ // accumulator is only created under `input.pdg === true`).
613
+ calleeIdAccumulator?.get(pf.filePath));
614
+ cfgBlocks += emitted.blocks;
615
+ cfgEdges += emitted.edges;
616
+ cfgDroppedEdges += emitted.droppedEdges;
617
+ // R6 (#2227 tri-review-2): release this file's captured id map now that
618
+ // emitFileCfgs has consumed it — the CALLS passes fully precede this loop
619
+ // and each file is read exactly once, so this bounds the accumulator to one
620
+ // file's call sites instead of holding the whole repo's for the phase.
621
+ calleeIdAccumulator?.delete(pf.filePath);
622
+ // M2 (#2082 U4): reaching definitions over the same validated CFGs.
623
+ // In-memory facts are computed per function and dropped after the
624
+ // bounded (defBlock, useBlock, binding) projection is persisted —
625
+ // M3 recomputes via the same pure solver in-phase (KTD8). Timing is
626
+ // PROF-gated like every other checkpoint here (zero cost when off).
627
+ // U12: one memoized RD solver per file, shared by the RD-emit + call-
628
+ // summary + taint + summary passes, so the per-function fixpoint runs once
629
+ // per (limits) bucket instead of 3–4× (#2227 tri-review). File-scoped: it
630
+ // is re-created each iteration, so its per-function facts drop with the file.
631
+ const rdSolve = createMemoizedReachingDefs();
632
+ const t0 = PROF ? performance.now() : 0;
633
+ const rd = emitFileReachingDefs(pdgTarget, wellFormed, input.pdgMaxReachingDefEdgesPerFunction ??
634
+ DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION, (message) => logger.warn(message), // unconditional — R7, both layers
635
+ rdSolve);
636
+ if (PROF)
637
+ pdgMs += performance.now() - t0;
638
+ rdEdges += rd.edges;
639
+ rdDropped += rd.droppedEdges;
640
+ rdFacts += rd.facts;
641
+ rdTruncated += rd.truncatedFunctions;
642
+ // M5 (#2085 U5): control dependence over the SAME validated CFGs.
643
+ // Independent of taint — runs for every `--pdg` language (post-dom +
644
+ // Ferrante are language-agnostic, no source/sink model needed). Pure
645
+ // compute; the bounded (controller, dependent, label) projection is
646
+ // persisted and its time folds into the `pdg=` PROF segment next to RD.
647
+ const tCdg = PROF ? performance.now() : 0;
648
+ const cdg = emitFileCdg(pdgTarget, wellFormed, input.pdgMaxCdgEdgesPerFunction ?? DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION, (message) => logger.warn(message));
649
+ if (PROF)
650
+ pdgMs += performance.now() - tCdg;
651
+ cdgEdges += cdg.edges;
652
+ cdgDropped += cdg.droppedEdges;
653
+ cdgSkippedUnsound += cdg.skippedUnsoundFunctions;
654
+ // FU-C (U-C2): RETURN-VALUE ASCENT summaries over the SAME validated
655
+ // CFGs, inside the SAME per-file try. Independent of taint — runs for
656
+ // EVERY `--pdg` language (pure data-dependence, no source/sink model).
657
+ // Reuses the same RD fact cap the RD/taint solves use (coverage parity).
658
+ const callHarvest = harvestFileCallSummaries(fnNodeIndex, wellFormed, taintLimits.maxFacts && taintLimits.maxFacts > 0
659
+ ? taintLimits.maxFacts
660
+ : DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, rdSolve);
661
+ harvestedCallSummaries.push(...callHarvest.summaries);
662
+ callSummaryUnresolved += callHarvest.unresolved;
663
+ // M3 (#2083 U4): taint over the SAME validated CFGs, inside the SAME
664
+ // per-file try (a taint throw costs this file's taint layer only —
665
+ // its CFG/REACHING_DEF edges above are already in the graph). Skipped
666
+ // entirely when the language has no registered model.
667
+ if (taintSpec !== undefined) {
668
+ const t1 = PROF ? performance.now() : 0;
669
+ const taint = emitFileTaint(pdgTarget, wellFormed, pf.parsedImports, taintSpec, taintLimits, (message) => logger.warn(message), // unconditional — R4/R6
670
+ rdSolve);
671
+ if (PROF)
672
+ taintMs += performance.now() - t1;
673
+ taintTotals.analyzed += taint.functionsAnalyzed;
674
+ taintTotals.noMatch += taint.functionsSkippedNoMatch;
675
+ taintTotals.unsafeSites += taint.functionsSkippedUnsafeSites;
676
+ taintTotals.gapTruncated += taint.functionsCoverageGap.truncated;
677
+ taintTotals.gapOverflow += taint.functionsCoverageGap.overflow;
678
+ taintTotals.gapNoFacts += taint.functionsCoverageGap['no-facts'];
679
+ taintTotals.findings += taint.findingsEmitted;
680
+ taintTotals.kills += taint.killsEmitted;
681
+ taintTotals.dropped += taint.findingsDropped;
682
+ taintTotals.hopsTruncated += taint.hopsTruncatedFindings;
683
+ for (const ex of taint.coverageGapExamples) {
684
+ if (taintTotals.gapExamples.length < 5)
685
+ taintTotals.gapExamples.push(ex);
686
+ }
687
+ for (const ex of taint.droppedExamples) {
688
+ if (taintTotals.dropExamples.length < 5)
689
+ taintTotals.dropExamples.push(ex);
690
+ }
691
+ // M4 (#2084 U1): harvest per-function summaries over the SAME
692
+ // emit-safe CFGs, inside the SAME per-file try. Pure aside from the
693
+ // read-only node-index lookup; the cross-function fixpoint phase
694
+ // consumes `harvestedSummaries` once the whole call graph is built.
695
+ if (fnNodeIndex !== undefined) {
696
+ const harvest = harvestFileSummaries(fnNodeIndex, wellFormed, pf.parsedImports, taintSpec,
697
+ // Same fact cap the taint-side RD solve uses (coverage parity).
698
+ taintLimits.maxFacts && taintLimits.maxFacts > 0
699
+ ? taintLimits.maxFacts
700
+ : DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, rdSolve);
701
+ harvestedSummaries.push(...harvest.summaries);
702
+ summaryUnresolved += harvest.unresolved;
703
+ }
704
+ }
705
+ }
706
+ catch (err) {
707
+ // Last-resort isolation, mirroring the worker-side per-file try/catch:
708
+ // a shape the predicate misses must cost this one file's CFG, not
709
+ // abort the language's whole scope-resolution pass mid-graph-build.
710
+ // NOTE a mid-emit throw can leave this file's already-inserted
711
+ // BasicBlock nodes in the graph (addNode is not transactional) —
712
+ // orphaned but inert; the predicate keeps every JSON-representable
713
+ // bad shape from reaching this path at all.
714
+ logger.warn(`[cfg] ${pf.filePath}: CFG emission failed (${err instanceof Error ? err.message : String(err)}) — ` +
715
+ `this file's CFG is partial or absent`);
716
+ }
717
+ }
718
+ if (cfgBlocks > 0) {
719
+ logger.debug(`[scope-resolution] CFG emit (lang=${provider.language}): ` +
720
+ `${cfgBlocks} BasicBlock nodes, ${cfgEdges} CFG edges` +
721
+ (cfgDroppedEdges > 0 ? `, ${cfgDroppedEdges} edges dropped (per-function cap)` : '') +
722
+ `; ${rdEdges} REACHING_DEF edges (${rdFacts} facts)` +
723
+ (rdDropped > 0 ? `, ${rdDropped} REACHING_DEF edges dropped (per-function cap)` : '') +
724
+ (rdTruncated > 0 ? `, ${rdTruncated} function(s) hit the fact limit` : '') +
725
+ `; ${cdgEdges} CDG edges` +
726
+ (cdgDropped > 0 ? `, ${cdgDropped} CDG edges dropped (per-function cap)` : '') +
727
+ (cdgSkippedUnsound > 0
728
+ ? `, ${cdgSkippedUnsound} function(s) CDG-skipped (EXIT not reachable from all blocks)`
729
+ : '') +
730
+ // M3 volume telemetry — only for languages with a registered model.
731
+ (taintSpec !== undefined
732
+ ? `; taint: ${taintTotals.findings} TAINTED, ${taintTotals.kills} SANITIZES ` +
733
+ `(${taintTotals.analyzed} function(s) analyzed, ` +
734
+ `${taintTotals.noMatch} skipped: no source/sink match` +
735
+ (taintTotals.hopsTruncated > 0
736
+ ? `, ${taintTotals.hopsTruncated} finding(s) with truncated hop paths`
737
+ : '') +
738
+ `)`
739
+ : ''));
740
+ }
741
+ // R8 (#2195): CDG soundness skips surface UNCONDITIONALLY (parity with the
742
+ // taint/RD gap warns) — not buried in the logger.debug stats line above. A
743
+ // function whose EXIT is not reverse-reachable from every block gets NO
744
+ // control dependence (an unmodeled non-terminating / multi-terminal CFG
745
+ // shape the synthetic-escape pass could not bridge). Withholding CDG
746
+ // silently would let a language's control dependence erode unnoticed; CFG
747
+ // and REACHING_DEF do not depend on post-dominance and are unaffected.
748
+ if (cdgSkippedUnsound > 0) {
749
+ logger.warn(`[cfg] lang=${provider.language}: ${cdgSkippedUnsound} function(s) had control ` +
750
+ `dependence skipped (EXIT not reverse-reachable from all blocks); ` +
751
+ `CFG and REACHING_DEF are unaffected`);
752
+ }
753
+ // R4: taint coverage gaps and cap drops surface UNCONDITIONALLY (never
754
+ // logger.debug, never input.onWarn) at the per-language aggregate, with
755
+ // counts and up to 5 example functions. Per-function warns above cover
756
+ // the rare/actionable cases (unsafe sites, cap drops); solver-status gaps
757
+ // were already per-function-warned by the RD layer (same solver, same
758
+ // fact cap), so this aggregate is their single taint-side surface.
759
+ if (taintSpec !== undefined) {
760
+ const gapCount = taintTotals.unsafeSites +
761
+ taintTotals.gapTruncated +
762
+ taintTotals.gapOverflow +
763
+ taintTotals.gapNoFacts;
764
+ if (gapCount > 0 || taintTotals.dropped > 0) {
765
+ const parts = [];
766
+ if (gapCount > 0) {
767
+ parts.push(`${gapCount} function(s) skipped for taint ` +
768
+ `(${taintTotals.gapTruncated} fact-limit, ${taintTotals.gapOverflow} overflow, ` +
769
+ `${taintTotals.gapNoFacts} no-facts, ${taintTotals.unsafeSites} malformed sites)` +
770
+ (taintTotals.gapExamples.length > 0
771
+ ? ` — e.g. ${taintTotals.gapExamples.join(', ')}`
772
+ : ''));
773
+ }
774
+ if (taintTotals.dropped > 0) {
775
+ parts.push(`${taintTotals.dropped} finding(s) dropped by the per-function cap` +
776
+ (taintTotals.dropExamples.length > 0
777
+ ? ` — e.g. ${taintTotals.dropExamples.join(', ')}`
778
+ : ''));
779
+ }
780
+ logger.warn(`[taint] lang=${provider.language}: ${parts.join('; ')}`);
781
+ }
782
+ }
783
+ // M4 (#2084 U1): summary harvest volume + anchor-resolution diagnostics.
784
+ if (harvestedSummaries.length > 0 || summaryUnresolved > 0) {
785
+ logger.debug(`[taint-summary] lang=${provider.language}: ${harvestedSummaries.length} function ` +
786
+ `summary/summaries harvested` +
787
+ (summaryUnresolved > 0
788
+ ? `, ${summaryUnresolved} CFG anchor(s) unresolved (same-line collision or missing node)`
789
+ : ''));
790
+ }
791
+ // FU-C (U-C2): call-summary harvest volume + anchor-resolution diagnostics.
792
+ if (harvestedCallSummaries.length > 0 || callSummaryUnresolved > 0) {
793
+ logger.debug(`[call-summary] lang=${provider.language}: ${harvestedCallSummaries.length} function ` +
794
+ `return-ascent summary/summaries harvested` +
795
+ (callSummaryUnresolved > 0
796
+ ? `, ${callSummaryUnresolved} CFG anchor(s) unresolved (same-line collision or missing node)`
797
+ : ''));
798
+ }
799
+ }
457
800
  if (PROF) {
458
801
  const tEnd = process.hrtime.bigint();
459
802
  const ns = (a, b) => Number(b - a) / 1_000_000;
@@ -462,6 +805,9 @@ export function runScopeResolution(input, provider) {
462
805
  ` propagate=${ns(tFinalize, tPropagate).toFixed(0)}ms` +
463
806
  ` resolve=${ns(tPropagate, tResolve).toFixed(0)}ms` +
464
807
  ` emit=${ns(tResolve, tEnd).toFixed(0)}ms` +
808
+ // pdg ⊆ emit: the M2 reaching-defs share of the emit bucket (#2082 U4).
809
+ // taint ⊆ emit likewise: the M3 match+solve+propagate+emit share (#2083 U4).
810
+ (input.pdg === true ? ` pdg=${pdgMs.toFixed(0)}ms taint=${taintMs.toFixed(0)}ms` : '') +
465
811
  ` total=${ns(tStart, tEnd).toFixed(0)}ms` +
466
812
  ` (${parsedFiles.length} files)`);
467
813
  }
@@ -474,5 +820,7 @@ export function runScopeResolution(input, provider) {
474
820
  referenceEdgesEmitted: emitted + receiverExtras + unresolvedReceiverExtras + freeCallExtras,
475
821
  referenceSkipped: skipped,
476
822
  resolutionOutcomes,
823
+ functionSummaries: harvestedSummaries,
824
+ callSummaries: harvestedCallSummaries,
477
825
  };
478
826
  }
@@ -1,5 +1,5 @@
1
1
  import type { Range } from '../../../_shared/index.js';
2
- export type ResolutionSuppressionReason = 'adl-ordinary-lookup-blocked' | 'conversion-rank-tied' | 'inline-ns-ambiguous' | 'member-lookup-ambiguous' | 'overload-ambiguous' | 'overload-ambiguous-normalization';
2
+ export type ResolutionSuppressionReason = 'adl-ordinary-lookup-blocked' | 'conversion-rank-tied' | 'inline-ns-ambiguous' | 'member-lookup-ambiguous' | 'selected-callable-deleted' | 'overload-ambiguous' | 'overload-ambiguous-normalization';
3
3
  export type ResolutionOutcome = {
4
4
  readonly kind: 'resolved';
5
5
  readonly targetId: string;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Call-summary reason codec (PDG FU-C, U-C2) — the ONE shared encoder/decoder
3
+ * for the bitset carried on persisted `CALL_SUMMARY` edges.
4
+ *
5
+ * A `CALL_SUMMARY` edge is a self-loop on a Function/Method/Constructor node
6
+ * recording that callee's RETURN-VALUE ASCENT: for each formal-parameter index,
7
+ * whether that parameter flows to the function's return value. The producer
8
+ * (the whole-program emit phase) writes this; a later consumer phase reads it to
9
+ * ascend a callee's return effect into the caller continuation. Two hand-rolled
10
+ * copies of a wire format drift — both sides MUST import from here (the same
11
+ * discipline `path-codec.ts` documents).
12
+ *
13
+ * ## Wire format (version `1`)
14
+ *
15
+ * ```
16
+ * 1|r:<hexbitset>[|<reserved-segment>…]
17
+ * ```
18
+ *
19
+ * - One-character version prefix ({@link CALL_SUMMARY_CODEC_VERSION}), then `|`,
20
+ * then a `r:` (return) segment whose payload is the param→return bitset as a
21
+ * lowercase hex string (LSB = formal index 0). Bit `i` set ⇒ formal parameter
22
+ * `i` flows to the return value. An empty/zero bitset is the absence of any
23
+ * return-flow (a sound EMPTY summary — never a false claim).
24
+ * - FORWARD COMPATIBILITY: the format reserves space for future facts via
25
+ * additional trailing `|<tag>:<payload>` segments (planned: `o:` out-params,
26
+ * `e:` exception ascent — both deferred: out-params need an alias model,
27
+ * exception ascent needs try/catch CDG). The decoder accepts and ignores any
28
+ * trailing segment whose tag it does not understand, so a future writer's
29
+ * output stays decodable by today's reader (and vice-versa: today's reader
30
+ * only requires the `r:` segment). Reserved tags MUST stay disjoint from `r`.
31
+ *
32
+ * ## Delimiter / round-trip discipline (mirrors path-codec KTD6)
33
+ *
34
+ * Every structural character (`|`, `:`, the version digit, hex digits `[0-9a-f]`)
35
+ * is printable ASCII, so the encoding survives `escapeCSVField ∘ sanitizeUTF8`
36
+ * (csv-generator.ts) byte-exact (pinned by the round-trip test). The hex payload
37
+ * is a non-negative integer rendered via BigInt, so the codec handles functions
38
+ * with arbitrarily many formal parameters without overflow.
39
+ *
40
+ * The decoder NEVER throws — anything malformed yields a typed failure, exactly
41
+ * like `decodeTaintPath`. A decode failure on the consumer side means "no usable
42
+ * ascent fact", which is the sound default (never claim a false return-flow).
43
+ */
44
+ /** One-character format version prefix. Bump on any wire-format change. */
45
+ export declare const CALL_SUMMARY_CODEC_VERSION = "1";
46
+ /** A decoded call summary's facts. Forward-compatible: future facts add fields. */
47
+ export interface DecodedCallSummary {
48
+ readonly ok: true;
49
+ readonly version: string;
50
+ /**
51
+ * Sorted, de-duplicated formal-parameter indices that flow to the return
52
+ * value (ascending). Empty ⇒ no return-flow recorded (sound EMPTY summary).
53
+ */
54
+ readonly returnFlowParams: readonly number[];
55
+ }
56
+ /** Typed parse failure — the decoder never throws. */
57
+ export interface CallSummaryDecodeFailure {
58
+ readonly ok: false;
59
+ readonly error: string;
60
+ }
61
+ export type CallSummaryDecodeResult = DecodedCallSummary | CallSummaryDecodeFailure;
62
+ /**
63
+ * Encode the param→return ascent into the versioned `reason` wire string.
64
+ * Deterministic; never throws. `returnFlowParams` is the set of formal indices
65
+ * that flow to the return value (order/duplication irrelevant — the bitset
66
+ * canonicalises). An empty set encodes as `r:0` (an explicit empty summary).
67
+ */
68
+ export declare function encodeCallSummary(returnFlowParams: Iterable<number>): string;
69
+ /**
70
+ * Decode a `CALL_SUMMARY` reason wire string into its ascent facts. Returns a
71
+ * typed failure for anything that is not a well-formed version-`1` summary —
72
+ * never throws. Unknown trailing segments (future facts) are accepted and
73
+ * ignored (forward compatibility).
74
+ */
75
+ export declare function decodeCallSummary(reason: unknown): CallSummaryDecodeResult;