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
@@ -0,0 +1,125 @@
1
+ /**
2
+ * In-phase taint emission (#2083 M3 U4, plan KTD1/KTD6).
3
+ *
4
+ * Per-file driver for the M3 taint pass: gate → match → solve → propagate →
5
+ * persist sparse `TAINTED` + `SANITIZES` edges. Invoked from the pdg window in
6
+ * scope-resolution (`pipeline/run.ts`), immediately after `emitFileReachingDefs`
7
+ * inside the SAME per-file try — per-file isolation for free (KTD1). Mirrors
8
+ * `emitFileReachingDefs` (cfg/emit.ts) for the budget/dedup/warn discipline and
9
+ * the telemetry-result shape.
10
+ *
11
+ * ## Per-function pipeline (ordering is load-bearing)
12
+ *
13
+ * 1. `hasTaintSafeSites` — a corrupted-store site annotation degrades to
14
+ * SKIP-TAINT-KEEP-RD for this function (counted + warned), never a crash
15
+ * (KTD2; the matcher/propagator dereference indices unvalidated).
16
+ * 2. `matchFunctionSites` against the language spec (the import index is
17
+ * built ONCE per file — imports are a file-level fact).
18
+ * 3. ZERO-MATCH FAST PATH: the solver runs only when the function has at
19
+ * least one matched source AND one matched sink. In a typical repo almost
20
+ * no function has both; an unconditional second `computeReachingDefs` per
21
+ * function would ship a near-2× solve cost to every `--pdg` user.
22
+ * 4. `computeReachingDefs` with the taint `maxFacts` — by DEFAULT the M2
23
+ * derived `DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION` (deliberate
24
+ * reuse, not a new constant: the fact-materialization envelope is a
25
+ * memory question, O(defs×uses), orthogonal to the findings cap, and M2
26
+ * already validated exactly this envelope on the same solver in the same
27
+ * window). The run.ts caller derives `limits.maxFacts` from the SAME
28
+ * RD-edge-cap formula `emitFileReachingDefs` uses, so taint coverage and
29
+ * RD coverage truncate together — a function is never `truncated` for one
30
+ * layer and `computed` for the other.
31
+ * 5. `computeTaintFlows` — a non-`computed` status is a per-function
32
+ * COVERAGE GAP (R4: counted by `gapReason`, function skipped entirely,
33
+ * never partially analyzed).
34
+ * 6. Emit one `TAINTED` edge per finding and one `SANITIZES` edge per kill.
35
+ * Kills are emitted even when findings are zero — a fully-sanitized
36
+ * function's kills are exactly its evidence of safety.
37
+ *
38
+ * ## Identity, dedup, budget (KTD6)
39
+ *
40
+ * Findings carry STATEMENT-LEVEL identity — function anchor + sink kind +
41
+ * source occurrence (point/site/object-binding/property) + sink occurrence
42
+ * (point/site/arg/binding) — NOT the REACHING_DEF block-level key (block-pair
43
+ * conflation would drop `exec(req.body, req.query)`'s second finding). The
44
+ * propagation engine dedups by this exact key BEFORE its deterministic cap
45
+ * (`maxFindingsPerFunction`) and counts the overflow; this module templates
46
+ * the same coordinates into the edge id (binding identity via the shared
47
+ * `bindingKey`; the free-text `property` rides LAST so it can never collide
48
+ * into another component) and warns with the drop count on truncation.
49
+ *
50
+ * `reason` carries the versioned hop encoding (`taint/path-codec.ts` — U6's
51
+ * `explain` decodes the same module) for `TAINTED`, and the killed binding's
52
+ * plain name for `SANITIZES` (M0/S1 queryability verdict, like REACHING_DEF).
53
+ *
54
+ * ## Warn split (R4 vs noise)
55
+ *
56
+ * Unsafe-site skips and cap drops warn PER FUNCTION here (rare, actionable —
57
+ * mirrors `emitFileReachingDefs`' malformed/cap warns). Solver coverage gaps
58
+ * (`truncated`/`overflow`) do NOT re-warn per function: the RD layer already
59
+ * warned for the same function with the same solver status (same `maxFacts`
60
+ * derivation — see step 4), and a duplicate `[taint]` line per mega-function
61
+ * would be pure spam. They are counted (+ exampled) in the result and the
62
+ * run.ts caller aggregates them into ONE unconditional `logger.warn` per
63
+ * language (R4) — never dropped on the floor (the M2 lesson).
64
+ */
65
+ import type { ParsedImport } from '../../../_shared/index.js';
66
+ import type { KnowledgeGraph } from '../../graph/types.js';
67
+ import { type ReachingDefsSolver } from '../cfg/reaching-defs.js';
68
+ import type { FunctionCfg } from '../cfg/types.js';
69
+ export { DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from './propagate.js';
70
+ import type { SourceSinkSanitizerSpec } from './source-sink-config.js';
71
+ export interface TaintEmitLimits {
72
+ /** Per-function findings cap (post-dedup). `undefined` ⇒
73
+ * {@link DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION}; `0` ⇒ unlimited. */
74
+ readonly maxFindingsPerFunction?: number;
75
+ /** Per-finding hop cap (source-side prefix kept). `undefined` ⇒
76
+ * {@link DEFAULT_PDG_MAX_TAINT_HOPS}; `0` ⇒ unlimited. */
77
+ readonly maxHops?: number;
78
+ /**
79
+ * Solver fact-materialization cap for the taint-side `computeReachingDefs`
80
+ * call. `undefined` ⇒ {@link DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION}
81
+ * (the M2 derived default — see the module doc for why it is REUSED rather
82
+ * than derived from the findings cap); `0` ⇒ unlimited.
83
+ */
84
+ readonly maxFacts?: number;
85
+ }
86
+ /**
87
+ * Full taint-emit telemetry for one file. EVERY counter is surfaced by the
88
+ * run.ts aggregate (the M2 emit result had two fields dropped on the floor —
89
+ * the plan names that mistake; don't repeat it).
90
+ */
91
+ export interface TaintEmitResult {
92
+ /** Functions fully propagated (`computeTaintFlows` returned `computed`). */
93
+ functionsAnalyzed: number;
94
+ /** Functions skipped by the zero-match fast path (no solver call). */
95
+ functionsSkippedNoMatch: number;
96
+ /** Functions whose `sites` failed {@link hasTaintSafeSites} (skip-taint-keep-RD). */
97
+ functionsSkippedUnsafeSites: number;
98
+ /** Source+sink functions skipped on a non-`computed` solver status (R4). */
99
+ functionsCoverageGap: {
100
+ truncated: number;
101
+ overflow: number;
102
+ 'no-facts': number;
103
+ };
104
+ /** TAINTED edges persisted. */
105
+ findingsEmitted: number;
106
+ /** SANITIZES edges persisted (emitted even when findings are zero). */
107
+ killsEmitted: number;
108
+ /** Findings dropped by the per-function cap (post-dedup), summed. */
109
+ findingsDropped: number;
110
+ /** Findings whose persisted hop path is a truncated prefix (hop/byte cap). */
111
+ hopsTruncatedFindings: number;
112
+ /** ≤{@link MAX_EXAMPLES} `file:line` anchors of gap/unsafe-site functions. */
113
+ coverageGapExamples: string[];
114
+ /** ≤{@link MAX_EXAMPLES} `file:line` anchors of cap-dropped functions. */
115
+ droppedExamples: string[];
116
+ }
117
+ /**
118
+ * Run the taint pass over one file's emit-safe CFGs and persist TAINTED +
119
+ * SANITIZES edges. `cfgs` MUST already be `isEmitSafeCfg`-filtered (the same
120
+ * `wellFormed` array the caller fed `emitFileCfgs`/`emitFileReachingDefs`) —
121
+ * block/edge anchors are trusted here; only the M3 `sites` layer is
122
+ * re-validated (`hasTaintSafeSites`). Never throws on well-formed input;
123
+ * the caller's per-file try isolates the rest.
124
+ */
125
+ export declare function emitFileTaint(graph: KnowledgeGraph, cfgs: readonly FunctionCfg[], parsedImports: readonly ParsedImport[], spec: SourceSinkSanitizerSpec, limits?: TaintEmitLimits, onWarn?: (message: string) => void, solve?: ReachingDefsSolver): TaintEmitResult;
@@ -0,0 +1,208 @@
1
+ /**
2
+ * In-phase taint emission (#2083 M3 U4, plan KTD1/KTD6).
3
+ *
4
+ * Per-file driver for the M3 taint pass: gate → match → solve → propagate →
5
+ * persist sparse `TAINTED` + `SANITIZES` edges. Invoked from the pdg window in
6
+ * scope-resolution (`pipeline/run.ts`), immediately after `emitFileReachingDefs`
7
+ * inside the SAME per-file try — per-file isolation for free (KTD1). Mirrors
8
+ * `emitFileReachingDefs` (cfg/emit.ts) for the budget/dedup/warn discipline and
9
+ * the telemetry-result shape.
10
+ *
11
+ * ## Per-function pipeline (ordering is load-bearing)
12
+ *
13
+ * 1. `hasTaintSafeSites` — a corrupted-store site annotation degrades to
14
+ * SKIP-TAINT-KEEP-RD for this function (counted + warned), never a crash
15
+ * (KTD2; the matcher/propagator dereference indices unvalidated).
16
+ * 2. `matchFunctionSites` against the language spec (the import index is
17
+ * built ONCE per file — imports are a file-level fact).
18
+ * 3. ZERO-MATCH FAST PATH: the solver runs only when the function has at
19
+ * least one matched source AND one matched sink. In a typical repo almost
20
+ * no function has both; an unconditional second `computeReachingDefs` per
21
+ * function would ship a near-2× solve cost to every `--pdg` user.
22
+ * 4. `computeReachingDefs` with the taint `maxFacts` — by DEFAULT the M2
23
+ * derived `DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION` (deliberate
24
+ * reuse, not a new constant: the fact-materialization envelope is a
25
+ * memory question, O(defs×uses), orthogonal to the findings cap, and M2
26
+ * already validated exactly this envelope on the same solver in the same
27
+ * window). The run.ts caller derives `limits.maxFacts` from the SAME
28
+ * RD-edge-cap formula `emitFileReachingDefs` uses, so taint coverage and
29
+ * RD coverage truncate together — a function is never `truncated` for one
30
+ * layer and `computed` for the other.
31
+ * 5. `computeTaintFlows` — a non-`computed` status is a per-function
32
+ * COVERAGE GAP (R4: counted by `gapReason`, function skipped entirely,
33
+ * never partially analyzed).
34
+ * 6. Emit one `TAINTED` edge per finding and one `SANITIZES` edge per kill.
35
+ * Kills are emitted even when findings are zero — a fully-sanitized
36
+ * function's kills are exactly its evidence of safety.
37
+ *
38
+ * ## Identity, dedup, budget (KTD6)
39
+ *
40
+ * Findings carry STATEMENT-LEVEL identity — function anchor + sink kind +
41
+ * source occurrence (point/site/object-binding/property) + sink occurrence
42
+ * (point/site/arg/binding) — NOT the REACHING_DEF block-level key (block-pair
43
+ * conflation would drop `exec(req.body, req.query)`'s second finding). The
44
+ * propagation engine dedups by this exact key BEFORE its deterministic cap
45
+ * (`maxFindingsPerFunction`) and counts the overflow; this module templates
46
+ * the same coordinates into the edge id (binding identity via the shared
47
+ * `bindingKey`; the free-text `property` rides LAST so it can never collide
48
+ * into another component) and warns with the drop count on truncation.
49
+ *
50
+ * `reason` carries the versioned hop encoding (`taint/path-codec.ts` — U6's
51
+ * `explain` decodes the same module) for `TAINTED`, and the killed binding's
52
+ * plain name for `SANITIZES` (M0/S1 queryability verdict, like REACHING_DEF).
53
+ *
54
+ * ## Warn split (R4 vs noise)
55
+ *
56
+ * Unsafe-site skips and cap drops warn PER FUNCTION here (rare, actionable —
57
+ * mirrors `emitFileReachingDefs`' malformed/cap warns). Solver coverage gaps
58
+ * (`truncated`/`overflow`) do NOT re-warn per function: the RD layer already
59
+ * warned for the same function with the same solver status (same `maxFacts`
60
+ * derivation — see step 4), and a duplicate `[taint]` line per mega-function
61
+ * would be pure spam. They are counted (+ exampled) in the result and the
62
+ * run.ts caller aggregates them into ONE unconditional `logger.warn` per
63
+ * language (R4) — never dropped on the floor (the M2 lesson).
64
+ */
65
+ import { generateId } from '../../../lib/utils.js';
66
+ import { basicBlockId, bindingKey, DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION, } from '../cfg/emit.js';
67
+ import { computeReachingDefs, pointKey, } from '../cfg/reaching-defs.js';
68
+ import { hasTaintSafeSites } from './site-safety.js';
69
+ import { buildTaintImportIndex, matchFunctionSites } from './match.js';
70
+ import { computeTaintFlows, DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from './propagate.js';
71
+ // Re-exported so the pipeline (run.ts) sources the taint default caps through
72
+ // this orchestration module rather than reaching into propagate.ts directly.
73
+ export { DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from './propagate.js';
74
+ import { encodeTaintPath } from './path-codec.js';
75
+ /** Cap on example anchors carried per result (aggregate-warn material, R4). */
76
+ const MAX_EXAMPLES = 5;
77
+ const pushExample = (list, anchor) => {
78
+ if (list.length < MAX_EXAMPLES)
79
+ list.push(anchor);
80
+ };
81
+ /**
82
+ * Run the taint pass over one file's emit-safe CFGs and persist TAINTED +
83
+ * SANITIZES edges. `cfgs` MUST already be `isEmitSafeCfg`-filtered (the same
84
+ * `wellFormed` array the caller fed `emitFileCfgs`/`emitFileReachingDefs`) —
85
+ * block/edge anchors are trusted here; only the M3 `sites` layer is
86
+ * re-validated (`hasTaintSafeSites`). Never throws on well-formed input;
87
+ * the caller's per-file try isolates the rest.
88
+ */
89
+ export function emitFileTaint(graph, cfgs, parsedImports, spec, limits, onWarn,
90
+ // U12: shared per-file memoized solver (harvest/taint bucket — no maxBlockVisits).
91
+ // The zero-match fast path below still skips the solve entirely; only MATCHED
92
+ // functions request it, hitting the cache the call-summary harvest warmed.
93
+ solve = computeReachingDefs) {
94
+ const result = {
95
+ functionsAnalyzed: 0,
96
+ functionsSkippedNoMatch: 0,
97
+ functionsSkippedUnsafeSites: 0,
98
+ functionsCoverageGap: { truncated: 0, overflow: 0, 'no-facts': 0 },
99
+ findingsEmitted: 0,
100
+ killsEmitted: 0,
101
+ findingsDropped: 0,
102
+ hopsTruncatedFindings: 0,
103
+ coverageGapExamples: [],
104
+ droppedExamples: [],
105
+ };
106
+ // Imports are a FILE-level fact — build the index once, not per function.
107
+ const importIndex = buildTaintImportIndex(parsedImports);
108
+ const maxFindingsPerFunction = limits?.maxFindingsPerFunction ?? DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION;
109
+ const maxHops = limits?.maxHops ?? DEFAULT_PDG_MAX_TAINT_HOPS;
110
+ const maxFacts = limits?.maxFacts ?? DEFAULT_PDG_MAX_REACHING_DEF_FACTS_PER_FUNCTION;
111
+ // Defensive cross-CFG id guard: finding identity is unique WITHIN a
112
+ // function by construction (the propagation engine dedups), so a repeat can
113
+ // only mean two CFGs sharing an anchor — skip, never double-insert.
114
+ const seenEdgeIds = new Set();
115
+ for (const cfg of cfgs) {
116
+ const { filePath, functionStartLine, functionStartColumn } = cfg;
117
+ const anchor = `${filePath}:${functionStartLine}`;
118
+ if (!hasTaintSafeSites(cfg)) {
119
+ result.functionsSkippedUnsafeSites++;
120
+ pushExample(result.coverageGapExamples, anchor);
121
+ onWarn?.(`[taint] ${anchor}: malformed site annotations (out-of-range binding/site ` +
122
+ `indices) — taint skipped for this function; its CFG and REACHING_DEF ` +
123
+ `layers are unaffected`);
124
+ continue;
125
+ }
126
+ const matches = matchFunctionSites(cfg, spec, importIndex);
127
+ if (!matches.hasSource || !matches.hasSink) {
128
+ // Zero-match fast path: no solver call (see module doc step 3).
129
+ result.functionsSkippedNoMatch++;
130
+ continue;
131
+ }
132
+ const defUse = solve(cfg, { maxFacts });
133
+ const flows = computeTaintFlows(cfg, defUse, matches, { maxFindingsPerFunction, maxHops });
134
+ if (flows.status === 'coverage-gap') {
135
+ // R4: skipped entirely, counted by reason; aggregate-warned by the
136
+ // caller (the RD layer already per-function-warned this solver status).
137
+ result.functionsCoverageGap[flows.gapReason ?? 'no-facts']++;
138
+ pushExample(result.coverageGapExamples, anchor);
139
+ continue;
140
+ }
141
+ result.functionsAnalyzed++;
142
+ const bindings = cfg.bindings ?? [];
143
+ const fnAnchor = `${filePath}:${functionStartLine}:${functionStartColumn}`;
144
+ const blockId = (p) => basicBlockId(filePath, functionStartLine, functionStartColumn, p.blockIndex);
145
+ const bKey = (idx) => {
146
+ const b = bindings[idx];
147
+ return b === undefined ? `#${idx}` : bindingKey(b);
148
+ };
149
+ // SANITIZES — one edge per kill, REGARDLESS of findings (kills can and do
150
+ // exist with zero findings: a fully-sanitized flow IS the kill evidence).
151
+ for (const kill of flows.kills) {
152
+ const id = generateId('SANITIZES', `${fnAnchor}:${pointKey(kill.sanitizer)}->${pointKey(kill.killedDef)}:` +
153
+ bKey(kill.bindingIdx));
154
+ if (seenEdgeIds.has(id))
155
+ continue;
156
+ seenEdgeIds.add(id);
157
+ graph.addRelationship({
158
+ id,
159
+ type: 'SANITIZES',
160
+ sourceId: blockId(kill.sanitizer),
161
+ targetId: blockId(kill.killedDef),
162
+ confidence: 1.0,
163
+ reason: bindings[kill.bindingIdx]?.name ?? `#${kill.bindingIdx}`,
164
+ });
165
+ result.killsEmitted++;
166
+ }
167
+ // TAINTED — one edge per finding (already deduped + capped upstream).
168
+ for (const finding of flows.findings) {
169
+ const { source, sink } = finding;
170
+ // KTD6 statement-level identity: function anchor + kind + source
171
+ // occurrence + sink occurrence + binding keys. The rule-(b) occurrence
172
+ // coordinates (site index / arg index) distinguish
173
+ // `exec(req.body, req.query)`'s two findings; `property` is free-text
174
+ // (string-literal subscripts) and rides LAST so it cannot collide into
175
+ // another component.
176
+ const id = generateId('TAINTED', `${fnAnchor}:${finding.sinkKind}:` +
177
+ `${pointKey(source.point)}.${source.siteIndex}:${bKey(source.objectBindingIdx)}:` +
178
+ `${pointKey(sink.point)}.${sink.siteIndex}.${sink.argIndex}:${bKey(sink.bindingIdx)}:` +
179
+ `${sink.entryName}:${source.property}`);
180
+ if (seenEdgeIds.has(id))
181
+ continue;
182
+ seenEdgeIds.add(id);
183
+ // `kind` rides the reason's `;<kind>` header — the only persisted
184
+ // channel for the finding's category (the edge id embedding it is not a
185
+ // stored column; `step` is INT32). U6's `explain` decodes it back.
186
+ const encoded = encodeTaintPath(finding.hops.map((h) => ({ name: h.name, line: h.point.line, viaCall: h.viaCall })), { truncated: finding.hopsTruncated === true, kind: finding.sinkKind });
187
+ if (encoded.truncated)
188
+ result.hopsTruncatedFindings++;
189
+ graph.addRelationship({
190
+ id,
191
+ type: 'TAINTED',
192
+ sourceId: blockId(source.point),
193
+ targetId: blockId(sink.point),
194
+ confidence: 1.0,
195
+ reason: encoded.reason,
196
+ });
197
+ result.findingsEmitted++;
198
+ }
199
+ if (flows.droppedFindings > 0) {
200
+ result.findingsDropped += flows.droppedFindings;
201
+ pushExample(result.droppedExamples, anchor);
202
+ onWarn?.(`[taint] ${anchor}: per-function taint findings cap ` +
203
+ `(${maxFindingsPerFunction}) reached — dropped ${flows.droppedFindings} of ` +
204
+ `${flows.findings.length + flows.droppedFindings} deduped findings`);
205
+ }
206
+ }
207
+ return result;
208
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Interprocedural taint emission (#2084 M4 U4) — materialise `TAINT_PATH`.
3
+ *
4
+ * Persists each cross-function {@link InterprocFinding} as ONE `TAINT_PATH`
5
+ * edge from the source function node to the sink function node, with the
6
+ * function-level hop chain + sink kind encoded in `reason` via the SHARED
7
+ * `path-codec` (the same versioned wire format M3's intra-procedural `TAINTED`
8
+ * edges use — never a second hand-rolled codec). The MCP `explain` tool decodes
9
+ * it for cross-function path rendering (U7).
10
+ *
11
+ * `TAINT_PATH` was reserved at M0 (the RelationshipType + the `CodeRelation`
12
+ * Function/Method node-pairs already exist), so materialisation needs zero
13
+ * schema work. Like `TAINTED`, it stays out of `VALID_RELATION_TYPES` and the
14
+ * web schema — `explain` is the discovery surface.
15
+ *
16
+ * Boundedness mirrors the M3 emit driver: dedup-before-cap (the solver already
17
+ * deduped by `(source, sink, kind)`), a per-run findings cap, and unconditional
18
+ * truncate-and-warn — never a silent drop.
19
+ */
20
+ import type { KnowledgeGraph } from '../../graph/types.js';
21
+ import type { InterprocFinding } from './interproc-solver.js';
22
+ /** Confidence stamped on interprocedural `TAINT_PATH` edges. Lower than the
23
+ * intra-procedural `TAINTED` 1.0 — context-insensitive composition is a
24
+ * coarser signal (return/call-site merging). */
25
+ export declare const INTERPROC_TAINT_CONFIDENCE = 0.6;
26
+ /**
27
+ * Default per-run cap on emitted `TAINT_PATH` edges (#2084 review P1-3).
28
+ * Resolved into `RepoMeta.pdg` like the other pdg caps; `0` ⇒ unlimited.
29
+ */
30
+ export declare const DEFAULT_PDG_MAX_INTERPROC_EDGES = 1000;
31
+ export interface InterprocEmitLimits {
32
+ /** Max `TAINT_PATH` edges per run (post-dedup). `undefined`/0 ⇒ unlimited. */
33
+ readonly maxEdges?: number;
34
+ }
35
+ export interface InterprocEmitResult {
36
+ /** TAINT_PATH edges persisted. */
37
+ edgesEmitted: number;
38
+ /** Findings dropped by the per-run cap. */
39
+ edgesDropped: number;
40
+ /** Findings whose persisted hop path is a truncated prefix. */
41
+ hopsTruncated: number;
42
+ /** Findings skipped because an endpoint node was missing from the graph. */
43
+ skippedMissingEndpoint: number;
44
+ }
45
+ /**
46
+ * Persist cross-function findings as `TAINT_PATH` edges. `findings` is assumed
47
+ * deduped + deterministically ordered (the solver's contract). Never throws on
48
+ * valid input.
49
+ */
50
+ export declare function emitInterprocTaint(graph: KnowledgeGraph, findings: readonly InterprocFinding[], limits?: InterprocEmitLimits, onWarn?: (message: string) => void): InterprocEmitResult;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Interprocedural taint emission (#2084 M4 U4) — materialise `TAINT_PATH`.
3
+ *
4
+ * Persists each cross-function {@link InterprocFinding} as ONE `TAINT_PATH`
5
+ * edge from the source function node to the sink function node, with the
6
+ * function-level hop chain + sink kind encoded in `reason` via the SHARED
7
+ * `path-codec` (the same versioned wire format M3's intra-procedural `TAINTED`
8
+ * edges use — never a second hand-rolled codec). The MCP `explain` tool decodes
9
+ * it for cross-function path rendering (U7).
10
+ *
11
+ * `TAINT_PATH` was reserved at M0 (the RelationshipType + the `CodeRelation`
12
+ * Function/Method node-pairs already exist), so materialisation needs zero
13
+ * schema work. Like `TAINTED`, it stays out of `VALID_RELATION_TYPES` and the
14
+ * web schema — `explain` is the discovery surface.
15
+ *
16
+ * Boundedness mirrors the M3 emit driver: dedup-before-cap (the solver already
17
+ * deduped by `(source, sink, kind)`), a per-run findings cap, and unconditional
18
+ * truncate-and-warn — never a silent drop.
19
+ */
20
+ import { encodeTaintPath } from './path-codec.js';
21
+ /** Confidence stamped on interprocedural `TAINT_PATH` edges. Lower than the
22
+ * intra-procedural `TAINTED` 1.0 — context-insensitive composition is a
23
+ * coarser signal (return/call-site merging). */
24
+ export const INTERPROC_TAINT_CONFIDENCE = 0.6;
25
+ /**
26
+ * Default per-run cap on emitted `TAINT_PATH` edges (#2084 review P1-3).
27
+ * Resolved into `RepoMeta.pdg` like the other pdg caps; `0` ⇒ unlimited.
28
+ */
29
+ export const DEFAULT_PDG_MAX_INTERPROC_EDGES = 1000;
30
+ /**
31
+ * Persist cross-function findings as `TAINT_PATH` edges. `findings` is assumed
32
+ * deduped + deterministically ordered (the solver's contract). Never throws on
33
+ * valid input.
34
+ */
35
+ export function emitInterprocTaint(graph, findings, limits, onWarn) {
36
+ const result = {
37
+ edgesEmitted: 0,
38
+ edgesDropped: 0,
39
+ hopsTruncated: 0,
40
+ skippedMissingEndpoint: 0,
41
+ };
42
+ const maxEdges = limits?.maxEdges && limits.maxEdges > 0 ? limits.maxEdges : Infinity;
43
+ const seen = new Set();
44
+ for (const finding of findings) {
45
+ if (result.edgesEmitted >= maxEdges) {
46
+ result.edgesDropped++;
47
+ continue;
48
+ }
49
+ const sourceNode = graph.getNode(finding.sourceFnId);
50
+ const sinkNode = graph.getNode(finding.sinkFnId);
51
+ if (!sourceNode || !sinkNode) {
52
+ result.skippedMissingEndpoint++;
53
+ continue;
54
+ }
55
+ // Map function hops → codec hops. The hop "name" is the function's display
56
+ // name (identifier charset — codec-safe); the line is its start line.
57
+ const hops = finding.hops.map((h) => {
58
+ const node = graph.getNode(h.fnId);
59
+ const name = typeof node?.properties.name === 'string' ? node.properties.name : 'fn';
60
+ const line = typeof node?.properties.startLine === 'number' ? node.properties.startLine : 0;
61
+ return { name, line };
62
+ });
63
+ const encoded = encodeTaintPath(hops, {
64
+ kind: finding.sinkKind,
65
+ truncated: finding.hopsTruncated,
66
+ });
67
+ if (encoded.truncated)
68
+ result.hopsTruncated++;
69
+ const id = `rel:TAINT_PATH:${finding.sinkKind}:${finding.sourceFnId}=>${finding.sinkFnId}`;
70
+ if (seen.has(id))
71
+ continue;
72
+ seen.add(id);
73
+ graph.addRelationship({
74
+ id,
75
+ sourceId: finding.sourceFnId,
76
+ targetId: finding.sinkFnId,
77
+ type: 'TAINT_PATH',
78
+ confidence: INTERPROC_TAINT_CONFIDENCE,
79
+ reason: encoded.reason,
80
+ });
81
+ result.edgesEmitted++;
82
+ }
83
+ if (result.edgesDropped > 0) {
84
+ onWarn?.(`[taint-interproc] ${result.edgesDropped} cross-function finding(s) dropped by the ` +
85
+ `per-run TAINT_PATH cap (${maxEdges})`);
86
+ }
87
+ return result;
88
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Interprocedural taint fixpoint (#2084 M4 U3).
3
+ *
4
+ * Composes per-function {@link FunctionSummary} objects over the resolved
5
+ * `CALLS` graph to find source→sink flows that cross function and file
6
+ * boundaries. PURE AND DETERMINISTIC (no graph, no I/O, no logger) — the phase
7
+ * builds the inputs from `ctx.graph` and persists the outputs.
8
+ *
9
+ * ## The model — whole-parameter taint reachability
10
+ *
11
+ * The unit of taint is `(function, parameter)`. The fixpoint computes the set
12
+ * of parameters that can hold source-derived data, then fires a finding
13
+ * whenever a tainted parameter feeds a modelled sink (`paramToSink`).
14
+ *
15
+ * - **Seeds** — every `sourceToCallArg` edge: a function generates a source and
16
+ * passes it into argument `argIndex` of a call at `callLine`. Resolving that
17
+ * call site against the caller's outgoing `CALLS` edges yields the callee;
18
+ * the callee's parameter `argIndex` becomes tainted, with the generating
19
+ * function recorded as the flow's source.
20
+ * - **Propagation** — every `paramToCallArg` edge of a function whose parameter
21
+ * is ALREADY tainted: `param i → arg j of callee` taints the callee's
22
+ * parameter `j` (TITO composition). Iterated to a fixpoint.
23
+ * - **Findings** — whenever a parameter becomes tainted and the owning
24
+ * function's `paramToSink` contains that parameter, a cross-function finding
25
+ * is emitted (source function → sink function, with the kind).
26
+ *
27
+ * ## Cycle safety (recursion)
28
+ *
29
+ * The tainted-parameter set is monotone over a FINITE lattice (`Σ functions ×
30
+ * params`), so the worklist fixpoint converges: a recursive or mutually
31
+ * recursive call merely re-proposes an already-tainted parameter, which the
32
+ * visited-set absorbs — no infinite descent. This is the functional/summary
33
+ * method's standard termination argument (Sharir-Pnueli; Pysa, Mariana Trench,
34
+ * and Infer all rely on it). SCC condensation would only refine the PROCESSING
35
+ * ORDER; correctness and termination do not require it.
36
+ *
37
+ * ## Context-insensitivity & the name-join over-approximation
38
+ *
39
+ * One summary per function, applied at every call site — return/param merging
40
+ * is accepted (the security-conservative direction). The call-arg→callee join
41
+ * is by callee NAME (not line), so when one caller invokes two DISTINCT
42
+ * same-named callees (`x.handler(src)` and `y.handler(clean)`), a source that
43
+ * flowed into ONE of them taints BOTH callees' parameter — an extra finding on
44
+ * the callee the source did not reach. This is sound (over-attribution, never a
45
+ * missed flow — the conservative direction for a security tool) and is the
46
+ * documented price of dropping the fragile line-based join; the `explain` tool
47
+ * surfaces it ("may over-attribute among same-named callees"). Other known
48
+ * precision losses (call-site conflation, shared dispatch, callbacks) are the
49
+ * documented M4 trade-offs; refinements are deferred (plan KTD).
50
+ */
51
+ import type { SinkKind } from './source-sink-config.js';
52
+ import type { FunctionSummary } from './summary-model.js';
53
+ /**
54
+ * One resolved call edge from the `CALLS` graph. The join to a summary's
55
+ * call-arg edge is by CALLEE NAME (the callee node's declared name), NOT by
56
+ * call-site line — line-base parity between the CFG harvest (1-based) and the
57
+ * reference site is fragile, while the callee identity is exact and the
58
+ * context-insensitive model tatints the callee's parameter the same way at
59
+ * every call site to it.
60
+ */
61
+ export interface InterprocCallEdge {
62
+ readonly callerId: string;
63
+ readonly calleeId: string;
64
+ /** The callee node's declared name (`helper`, `process`) — the join key. */
65
+ readonly calleeName: string;
66
+ }
67
+ /** One hop of a cross-function flow: the function entered, and how. */
68
+ export interface InterprocHop {
69
+ readonly fnId: string;
70
+ /** The call-site line in the PREVIOUS function that entered this one. */
71
+ readonly callLine?: number;
72
+ /** Argument position the taint entered through (undefined for the source fn). */
73
+ readonly argIndex?: number;
74
+ }
75
+ export interface InterprocFinding {
76
+ readonly sourceFnId: string;
77
+ readonly sinkFnId: string;
78
+ readonly sinkKind: SinkKind;
79
+ /** Ordered source→sink hop chain (functions). A prefix when `truncated`. */
80
+ readonly hops: readonly InterprocHop[];
81
+ readonly hopsTruncated: boolean;
82
+ }
83
+ export interface InterprocLimits {
84
+ /** Max functions in a single flow's hop chain. `undefined`/0 ⇒ default 32. */
85
+ readonly maxHops?: number;
86
+ /** Max findings overall (post-dedup). `undefined`/0 ⇒ unlimited. */
87
+ readonly maxFindings?: number;
88
+ }
89
+ export interface InterprocResult {
90
+ readonly findings: readonly InterprocFinding[];
91
+ /** Findings dropped by `maxFindings` (post-dedup). */
92
+ readonly droppedFindings: number;
93
+ /** Call edges whose call-site line matched no summary edge (diagnostics). */
94
+ readonly unmatchedCallSites: number;
95
+ }
96
+ export declare const DEFAULT_MAX_INTERPROC_HOPS = 32;
97
+ /**
98
+ * Default per-run cap on cross-function findings (#2084 review P1-3). Like the
99
+ * other pdg caps it is resolved into `RepoMeta.pdg` so `pdgModeMismatch`
100
+ * stamps it; `0` ⇒ unlimited. 2000 is generous for a real repo — more deduped
101
+ * `(source, sink, kind)` findings than that is a fixture or a runaway fan-in,
102
+ * and the overflow is deterministic + counted (`droppedFindings`).
103
+ */
104
+ export declare const DEFAULT_PDG_MAX_INTERPROC_FINDINGS = 2000;
105
+ /**
106
+ * Run the interprocedural taint fixpoint. `summaries` is keyed by function node
107
+ * id; `callEdges` is the resolved `CALLS` graph (caller→callee with call-site
108
+ * lines). Deterministic: inputs in, sorted findings out.
109
+ */
110
+ export declare function solveInterprocTaint(summaries: ReadonlyMap<string, FunctionSummary>, callEdges: readonly InterprocCallEdge[], limits?: InterprocLimits): InterprocResult;