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
@@ -0,0 +1,626 @@
1
+ import { CallSiteFactAccumulator } from './call-site-harvest.js';
2
+ /** Node types that own a nested CFG — their subtrees are opaque to harvesting. */
3
+ const NESTED_FUNCTION_TYPES = new Set([
4
+ 'function_definition',
5
+ 'method_declaration',
6
+ 'anonymous_function',
7
+ 'arrow_function',
8
+ ]);
9
+ export class PhpHarvester {
10
+ fnNode;
11
+ bindings = [];
12
+ /** PHP is function-scoped: one flat table, name → binding index. */
13
+ table = new Map();
14
+ synthetic = new Map();
15
+ fnId;
16
+ /** >0 while walking a conditionally-evaluated subexpression — defs become may-defs. */
17
+ conditionalDepth = 0;
18
+ /**
19
+ * Call/new node id → bindings whose declarator/assignment VALUE is exactly
20
+ * that call. Registered before the value walk, consumed by {@link visitCall} /
21
+ * {@link visitNew} (mirrors the Java harvester's `resultDefTargets`).
22
+ */
23
+ resultDefTargets = new Map();
24
+ constructor(fnNode) {
25
+ this.fnNode = fnNode;
26
+ this.fnId = fnNode.id;
27
+ this.declareParams(fnNode);
28
+ this.declareUseClause(fnNode);
29
+ const body = this.bodyOf(fnNode);
30
+ if (body)
31
+ this.prescan(body);
32
+ }
33
+ /** The completed binding table — pass to `CfgBuilder.finish`. */
34
+ bindingTable() {
35
+ return this.bindings;
36
+ }
37
+ /** The function/closure body node (a `compound_statement`, or an expression). */
38
+ bodyOf(fnNode) {
39
+ return fnNode.childForFieldName('body') ?? undefined;
40
+ }
41
+ // ── phase 1: declaration pre-scan ────────────────────────────────────────
42
+ declare(name, declNode, kind) {
43
+ if (!name || this.table.has(name))
44
+ return;
45
+ this.table.set(name, this.bindings.length);
46
+ this.bindings.push({
47
+ name,
48
+ declLine: declNode.startPosition.row + 1,
49
+ declColumn: declNode.startPosition.column,
50
+ kind,
51
+ });
52
+ }
53
+ /** The `$name` text of a parameter's `name` field (a `variable_name` or `by_ref`). */
54
+ paramVarName(param) {
55
+ const name = param.childForFieldName('name');
56
+ if (!name)
57
+ return undefined;
58
+ if (name.type === 'by_ref') {
59
+ return name.namedChildren.find((c) => c.type === 'variable_name');
60
+ }
61
+ return name.type === 'variable_name' ? name : undefined;
62
+ }
63
+ declareParams(fnNode) {
64
+ const params = fnNode.childForFieldName('parameters');
65
+ if (!params)
66
+ return;
67
+ for (let i = 0; i < params.namedChildCount; i++) {
68
+ const p = params.namedChild(i);
69
+ if (!p)
70
+ continue;
71
+ if (p.type !== 'simple_parameter' &&
72
+ p.type !== 'variadic_parameter' &&
73
+ p.type !== 'property_promotion_parameter') {
74
+ continue;
75
+ }
76
+ const varName = this.paramVarName(p);
77
+ if (varName)
78
+ this.declare(varName.text, varName, 'param');
79
+ }
80
+ }
81
+ /** `anonymous_function ... use ($a, &$b)` — each captured var binds in the closure. */
82
+ declareUseClause(fnNode) {
83
+ if (fnNode.type !== 'anonymous_function')
84
+ return;
85
+ const clause = fnNode.namedChildren.find((c) => c.type === 'anonymous_function_use_clause');
86
+ if (!clause)
87
+ return;
88
+ for (const v of this.useClauseVars(clause))
89
+ this.declare(v.text, v, 'param');
90
+ }
91
+ /** The captured `variable_name`s of a `use (...)` clause (unwrapping `by_ref`). */
92
+ useClauseVars(clause) {
93
+ const out = [];
94
+ for (let i = 0; i < clause.namedChildCount; i++) {
95
+ const c = clause.namedChild(i);
96
+ if (!c)
97
+ continue;
98
+ if (c.type === 'variable_name')
99
+ out.push(c);
100
+ else if (c.type === 'by_ref') {
101
+ const inner = c.namedChildren.find((x) => x.type === 'variable_name');
102
+ if (inner)
103
+ out.push(inner);
104
+ }
105
+ }
106
+ return out;
107
+ }
108
+ /**
109
+ * Walk the function body once, declaring every assigned / foreach / catch
110
+ * variable into the FLAT function scope (PHP has no block scoping). Nested
111
+ * function/closure bodies are NOT descended (opaque).
112
+ */
113
+ prescan(node) {
114
+ const t = node.type;
115
+ if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
116
+ return;
117
+ switch (t) {
118
+ case 'assignment_expression': {
119
+ const left = node.childForFieldName('left');
120
+ if (left)
121
+ this.declareLvalue(left);
122
+ break;
123
+ }
124
+ case 'augmented_assignment_expression': {
125
+ const left = node.childForFieldName('left');
126
+ if (left && left.type === 'variable_name')
127
+ this.declare(left.text, left, 'var');
128
+ break;
129
+ }
130
+ case 'update_expression': {
131
+ const arg = node.childForFieldName('argument');
132
+ if (arg && arg.type === 'variable_name')
133
+ this.declare(arg.text, arg, 'var');
134
+ break;
135
+ }
136
+ case 'foreach_statement': {
137
+ for (const v of this.foreachTargets(node))
138
+ this.declare(v.text, v, 'var');
139
+ break;
140
+ }
141
+ case 'catch_clause': {
142
+ const name = node.childForFieldName('name');
143
+ if (name && name.type === 'variable_name')
144
+ this.declare(name.text, name, 'catch');
145
+ break;
146
+ }
147
+ default:
148
+ break;
149
+ }
150
+ for (let i = 0; i < node.namedChildCount; i++) {
151
+ const c = node.namedChild(i);
152
+ if (c)
153
+ this.prescan(c);
154
+ }
155
+ }
156
+ /**
157
+ * Declare the variable(s) named by an assignment lvalue: a plain
158
+ * `variable_name`, or a `list_literal` destructure (`[$a,$b]` / `list($a,$b)`,
159
+ * possibly keyed `["x" => $e]`). Member / subscript targets bind nothing.
160
+ */
161
+ declareLvalue(left) {
162
+ if (left.type === 'variable_name') {
163
+ this.declare(left.text, left, 'var');
164
+ }
165
+ else if (left.type === 'list_literal') {
166
+ for (const v of this.listTargets(left))
167
+ this.declare(v.text, v, 'var');
168
+ }
169
+ }
170
+ /** Every `variable_name` bound by a `list_literal` (including keyed entries). */
171
+ listTargets(list) {
172
+ const out = [];
173
+ const walk = (n) => {
174
+ if (n.type === 'variable_name') {
175
+ out.push(n);
176
+ return;
177
+ }
178
+ // Keyed (`"x" => $e`) entries and nested lists descend; non-variable keys
179
+ // (the string/int key) are not lvalues and carry no `variable_name`.
180
+ for (let i = 0; i < n.namedChildCount; i++) {
181
+ const c = n.namedChild(i);
182
+ if (c)
183
+ walk(c);
184
+ }
185
+ };
186
+ for (let i = 0; i < list.namedChildCount; i++) {
187
+ const c = list.namedChild(i);
188
+ if (c)
189
+ walk(c);
190
+ }
191
+ return out;
192
+ }
193
+ /**
194
+ * The bound variable(s) of a `foreach ($it as [$k =>] $v)`: the value (and key)
195
+ * `variable_name`s. The structure is positional — the FIRST named child is the
196
+ * iterable, then either a bare `variable_name` (value) or a `pair` ($k => $v).
197
+ */
198
+ foreachTargets(stmt) {
199
+ const out = [];
200
+ // Skip the iterable (first named child); collect value / pair targets after.
201
+ for (let i = 1; i < stmt.namedChildCount; i++) {
202
+ const c = stmt.namedChild(i);
203
+ if (!c)
204
+ continue;
205
+ if (c.type === 'variable_name')
206
+ out.push(c);
207
+ else if (c.type === 'pair') {
208
+ for (let j = 0; j < c.namedChildCount; j++) {
209
+ const v = c.namedChild(j);
210
+ if (v?.type === 'variable_name')
211
+ out.push(v);
212
+ }
213
+ }
214
+ // `body` (compound_statement / colon_block) is not a target — it has its
215
+ // own non-variable_name/non-pair type, so it is skipped here.
216
+ }
217
+ return out;
218
+ }
219
+ // ── phase 2: per-statement fact extraction ───────────────────────────────
220
+ /** Def/use facts for one statement (or construct-header expression) node. */
221
+ facts(node) {
222
+ const acc = new FactAccumulator(node.startPosition.row + 1);
223
+ this.walkValue(node, acc);
224
+ return acc.finish();
225
+ }
226
+ /** Facts for an expression whose WHOLE evaluation is conditional (case tests). */
227
+ factsConditional(node) {
228
+ const acc = new FactAccumulator(node.startPosition.row + 1);
229
+ this.conditional(() => this.walkValue(node, acc));
230
+ return acc.finish();
231
+ }
232
+ /**
233
+ * Def-ONLY facts for a value-position assignment carrier (`$x = match($v) {…}`,
234
+ * #2207): just the LHS target(s), attached to the continuation block the match
235
+ * arms rejoin. The match condition + arm-value USES are already harvested onto
236
+ * the branch's own blocks (visitMatch), so this must NOT re-walk the RHS. A
237
+ * member/subscript target (`$this->x = match …`) has no scalar def → undefined.
238
+ */
239
+ assignmentDefFacts(assignExpr) {
240
+ const acc = new FactAccumulator(assignExpr.startPosition.row + 1);
241
+ const left = assignExpr.childForFieldName('left');
242
+ if (left) {
243
+ const lv = this.unwrapParen(left);
244
+ if (lv.type === 'variable_name')
245
+ this.def(lv, acc);
246
+ else if (lv.type === 'list_literal')
247
+ for (const v of this.listTargets(lv))
248
+ this.def(v, acc);
249
+ }
250
+ return acc.defCount() ? acc.finish() : undefined;
251
+ }
252
+ /** Facts for a `foreach ($it as [$k =>] $v)` head: targets bind, iterable used. */
253
+ foreachHeadFacts(stmt) {
254
+ const acc = new FactAccumulator(stmt.startPosition.row + 1);
255
+ const iterable = stmt.namedChild(0);
256
+ if (iterable)
257
+ this.walkValue(iterable, acc);
258
+ for (const v of this.foreachTargets(stmt))
259
+ this.def(v, acc);
260
+ return acc.finish();
261
+ }
262
+ /** ENTRY-block facts for the function's parameters (defs only). */
263
+ paramFacts() {
264
+ const acc = new FactAccumulator(this.fnNode.startPosition.row + 1);
265
+ const params = this.fnNode.childForFieldName('parameters');
266
+ if (params) {
267
+ for (let i = 0; i < params.namedChildCount; i++) {
268
+ const p = params.namedChild(i);
269
+ if (!p)
270
+ continue;
271
+ if (p.type !== 'simple_parameter' &&
272
+ p.type !== 'variadic_parameter' &&
273
+ p.type !== 'property_promotion_parameter') {
274
+ continue;
275
+ }
276
+ const varName = this.paramVarName(p);
277
+ if (varName)
278
+ this.def(varName, acc);
279
+ }
280
+ }
281
+ // A closure's `use (...)` captures are live on entry too — model as defs.
282
+ if (this.fnNode.type === 'anonymous_function') {
283
+ const clause = this.fnNode.namedChildren.find((c) => c.type === 'anonymous_function_use_clause');
284
+ if (clause)
285
+ for (const v of this.useClauseVars(clause))
286
+ this.def(v, acc);
287
+ }
288
+ return acc.defCount() ? acc.finish() : undefined;
289
+ }
290
+ /** Def fact for a `catch (T $e)` parameter — prepend to the handler entry block. */
291
+ catchParamFacts(catchClause) {
292
+ const name = catchClause.childForFieldName('name');
293
+ if (!name || name.type !== 'variable_name')
294
+ return undefined;
295
+ const acc = new FactAccumulator(catchClause.startPosition.row + 1);
296
+ this.def(name, acc);
297
+ return acc.defCount() ? acc.finish() : undefined;
298
+ }
299
+ resolve(nameNode) {
300
+ const name = nameNode.text;
301
+ const idx = this.table.get(name);
302
+ if (idx !== undefined)
303
+ return idx;
304
+ let syn = this.synthetic.get(name);
305
+ if (syn === undefined) {
306
+ syn = this.bindings.length;
307
+ this.synthetic.set(name, syn);
308
+ this.bindings.push({ name, declLine: 0, declColumn: 0, kind: 'module', synthetic: true });
309
+ }
310
+ return syn;
311
+ }
312
+ def(nameNode, acc) {
313
+ if (this.conditionalDepth > 0)
314
+ acc.addMayDef(this.resolve(nameNode));
315
+ else
316
+ acc.addDef(this.resolve(nameNode));
317
+ }
318
+ use(nameNode, acc) {
319
+ acc.addUse(this.resolve(nameNode));
320
+ }
321
+ /** Run `fn` with defs demoted to may-defs (conditionally-evaluated context). */
322
+ conditional(fn) {
323
+ this.conditionalDepth++;
324
+ try {
325
+ fn();
326
+ }
327
+ finally {
328
+ this.conditionalDepth--;
329
+ }
330
+ }
331
+ /** Strip parenthesized wrappers around an lvalue (`($x) = 1`). */
332
+ unwrapParen(node) {
333
+ let n = node;
334
+ let hops = 8;
335
+ while (n.type === 'parenthesized_expression' && hops-- > 0) {
336
+ const inner = n.namedChildren.find((c) => c.type !== 'comment');
337
+ if (!inner)
338
+ break;
339
+ n = inner;
340
+ }
341
+ return n;
342
+ }
343
+ /** Value-position walk: collect uses; route def positions to the lvalue handler. */
344
+ walkValue(node, acc) {
345
+ const t = node.type;
346
+ if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId) {
347
+ // Opaque nested function / closure — captured reads/writes are invisible.
348
+ return;
349
+ }
350
+ switch (t) {
351
+ case 'variable_name':
352
+ this.use(node, acc);
353
+ return;
354
+ case 'assignment_expression': {
355
+ const left = node.childForFieldName('left');
356
+ const right = node.childForFieldName('right');
357
+ if (left) {
358
+ const lv = this.unwrapParen(left);
359
+ if (lv.type === 'variable_name') {
360
+ const snap = acc.defSnapshot();
361
+ this.def(lv, acc);
362
+ if (right)
363
+ this.registerResultDefs(right, acc.defsSince(snap));
364
+ }
365
+ else if (lv.type === 'list_literal') {
366
+ // Destructure: every target binds; non-variable keys are uses.
367
+ for (const v of this.listTargets(lv))
368
+ this.def(v, acc);
369
+ }
370
+ else {
371
+ this.walkValue(lv, acc); // member / subscript target — uses only
372
+ }
373
+ }
374
+ if (right)
375
+ this.walkValue(right, acc);
376
+ return;
377
+ }
378
+ case 'augmented_assignment_expression': {
379
+ const left = node.childForFieldName('left');
380
+ const right = node.childForFieldName('right');
381
+ if (left) {
382
+ const lv = this.unwrapParen(left);
383
+ if (lv.type === 'variable_name') {
384
+ this.def(lv, acc);
385
+ this.use(lv, acc); // compound assign reads too
386
+ }
387
+ else {
388
+ this.walkValue(lv, acc);
389
+ }
390
+ }
391
+ if (right)
392
+ this.walkValue(right, acc);
393
+ return;
394
+ }
395
+ case 'update_expression': {
396
+ const arg = node.childForFieldName('argument');
397
+ const lv = arg ? this.unwrapParen(arg) : null;
398
+ if (lv?.type === 'variable_name') {
399
+ this.def(lv, acc);
400
+ this.use(lv, acc);
401
+ }
402
+ else if (arg) {
403
+ this.walkValue(arg, acc);
404
+ }
405
+ return;
406
+ }
407
+ case 'binary_expression': {
408
+ const left = node.childForFieldName('left');
409
+ const right = node.childForFieldName('right');
410
+ const op = node.childForFieldName('operator')?.text ?? '';
411
+ if (left)
412
+ this.walkValue(left, acc);
413
+ if (right) {
414
+ if (op === '&&' || op === '||' || op === '??' || op === 'and' || op === 'or') {
415
+ this.conditional(() => this.walkValue(right, acc));
416
+ }
417
+ else {
418
+ this.walkValue(right, acc);
419
+ }
420
+ }
421
+ return;
422
+ }
423
+ case 'conditional_expression': {
424
+ const cond = node.childForFieldName('condition');
425
+ const body = node.childForFieldName('body');
426
+ const alt = node.childForFieldName('alternative');
427
+ if (cond)
428
+ this.walkValue(cond, acc);
429
+ if (body)
430
+ this.conditional(() => this.walkValue(body, acc));
431
+ if (alt)
432
+ this.conditional(() => this.walkValue(alt, acc));
433
+ return;
434
+ }
435
+ case 'function_call_expression':
436
+ this.visitCall(node, acc, 'function');
437
+ return;
438
+ case 'member_call_expression':
439
+ case 'nullsafe_member_call_expression':
440
+ this.visitCall(node, acc, 'member');
441
+ return;
442
+ case 'scoped_call_expression':
443
+ this.visitCall(node, acc, 'scoped');
444
+ return;
445
+ case 'object_creation_expression':
446
+ this.visitNew(node, acc);
447
+ return;
448
+ case 'member_access_expression':
449
+ case 'nullsafe_member_access_expression': {
450
+ // `$o->p` — value read of the object root only (the property name is not
451
+ // a scalar binding); record the innermost identifier-rooted member read.
452
+ this.walkChain(node, acc);
453
+ return;
454
+ }
455
+ default:
456
+ for (let i = 0; i < node.namedChildCount; i++) {
457
+ const c = node.namedChild(i);
458
+ if (c)
459
+ this.walkValue(c, acc);
460
+ }
461
+ }
462
+ }
463
+ // ── taint-site harvest ───────────────────────────────────────────────────
464
+ /**
465
+ * When `value`'s root (after stripping parens) is a call / object-creation
466
+ * node, remember its site should carry `resultDefs: defs`.
467
+ */
468
+ registerResultDefs(value, defs) {
469
+ if (defs.length === 0)
470
+ return;
471
+ const root = this.unwrapParen(value);
472
+ if (root.type === 'function_call_expression' ||
473
+ root.type === 'member_call_expression' ||
474
+ root.type === 'nullsafe_member_call_expression' ||
475
+ root.type === 'scoped_call_expression' ||
476
+ root.type === 'object_creation_expression') {
477
+ this.resultDefTargets.set(root.id, [...defs]);
478
+ }
479
+ }
480
+ /**
481
+ * Call-site handler for the three PHP call shapes:
482
+ * - `function`: `function_call_expression` (`function` field = name, no receiver)
483
+ * - `member`: `member_call_expression` (`object` receiver, `name` method)
484
+ * - `scoped`: `scoped_call_expression` (`scope` class, `name` method)
485
+ * Reproduces the same uses the default descent recorded plus the call site.
486
+ */
487
+ visitCall(node, acc, shape) {
488
+ const argsNode = node.childForFieldName('arguments');
489
+ // `node` IS the call expression — the SAME node the scope-extractor anchors
490
+ // `@reference.call.*` (its `atRange`) on (KTD7).
491
+ const siteIdx = acc.openCallSite('call', [
492
+ node.startPosition.row + 1,
493
+ node.startPosition.column,
494
+ ]);
495
+ acc.pushFrame(siteIdx);
496
+ if (shape === 'function') {
497
+ const fnNode = node.childForFieldName('function');
498
+ if (fnNode) {
499
+ if (fnNode.type === 'name' || fnNode.type === 'qualified_name') {
500
+ acc.setSiteCallee(siteIdx, fnNode.text);
501
+ }
502
+ else {
503
+ // dynamic callee (`$fn()`, `($obj->cb)()`) — record uses, no static path
504
+ this.walkValue(fnNode, acc);
505
+ }
506
+ }
507
+ }
508
+ else if (shape === 'member') {
509
+ const objectNode = node.childForFieldName('object');
510
+ const nameNode = node.childForFieldName('name');
511
+ let receiverPath;
512
+ if (objectNode) {
513
+ const chain = this.walkChain(objectNode, acc);
514
+ receiverPath = chain.path;
515
+ if (chain.rootIdx !== undefined)
516
+ acc.setSiteReceiver(siteIdx, chain.rootIdx);
517
+ }
518
+ if (nameNode && nameNode.type === 'name') {
519
+ const callee = receiverPath !== undefined ? `${receiverPath}.${nameNode.text}` : nameNode.text;
520
+ acc.setSiteCallee(siteIdx, callee);
521
+ }
522
+ }
523
+ else {
524
+ // scoped: `C::method(...)` — scope is a class name (not a binding).
525
+ const scopeNode = node.childForFieldName('scope');
526
+ const nameNode = node.childForFieldName('name');
527
+ const scopeText = scopeNode && (scopeNode.type === 'name' || scopeNode.type === 'qualified_name')
528
+ ? scopeNode.text
529
+ : undefined;
530
+ if (nameNode && nameNode.type === 'name') {
531
+ const callee = scopeText !== undefined ? `${scopeText}.${nameNode.text}` : nameNode.text;
532
+ acc.setSiteCallee(siteIdx, callee);
533
+ }
534
+ }
535
+ const resultDefs = this.resultDefTargets.get(node.id);
536
+ if (resultDefs !== undefined)
537
+ acc.setSiteResultDefs(siteIdx, resultDefs);
538
+ this.walkArgs(argsNode, acc);
539
+ acc.popFrame();
540
+ }
541
+ /** Explicit `object_creation_expression` (`new Foo($x)`) handler. */
542
+ visitNew(node, acc) {
543
+ const argsNode = node.childForFieldName('arguments');
544
+ // `node` IS the object_creation_expression — the SAME node the
545
+ // scope-extractor anchors `@reference.call.constructor` (its `atRange`) on.
546
+ const siteIdx = acc.openCallSite('new', [
547
+ node.startPosition.row + 1,
548
+ node.startPosition.column,
549
+ ]);
550
+ acc.pushFrame(siteIdx);
551
+ // The class name is the first `name`/`qualified_name` child (not a binding).
552
+ const className = node.namedChildren.find((c) => c.type === 'name' || c.type === 'qualified_name');
553
+ if (className)
554
+ acc.setSiteCallee(siteIdx, className.text.replace(/\s+/g, ''));
555
+ const resultDefs = this.resultDefTargets.get(node.id);
556
+ if (resultDefs !== undefined)
557
+ acc.setSiteResultDefs(siteIdx, resultDefs);
558
+ this.walkArgs(argsNode, acc);
559
+ acc.popFrame();
560
+ }
561
+ /** Walk an `arguments` node, tagging each positional `argument` for occurrences. */
562
+ walkArgs(argsNode, acc) {
563
+ if (!argsNode)
564
+ return;
565
+ let pos = 0;
566
+ for (let i = 0; i < argsNode.namedChildCount; i++) {
567
+ const arg = argsNode.namedChild(i);
568
+ if (!arg || arg.type === 'comment')
569
+ continue;
570
+ if (arg.type !== 'argument') {
571
+ // A spread (`...$xs`) or other non-`argument` child — still walk for uses.
572
+ this.walkValue(arg, acc);
573
+ continue;
574
+ }
575
+ acc.setFrameArg(pos);
576
+ this.walkValue(arg, acc);
577
+ pos++;
578
+ }
579
+ }
580
+ /**
581
+ * Member-access chain walk shared by value position and a method-call receiver.
582
+ * Records the chain-root `variable_name` as a use plus at most ONE member-read
583
+ * site — the innermost access — when the root is a variable.
584
+ */
585
+ walkChain(node, acc) {
586
+ const accesses = [];
587
+ let cur = this.unwrapParen(node);
588
+ for (;;) {
589
+ if (cur.type === 'member_access_expression' ||
590
+ cur.type === 'nullsafe_member_access_expression') {
591
+ const field = cur.childForFieldName('name');
592
+ accesses.unshift(field?.text ?? '');
593
+ const obj = cur.childForFieldName('object');
594
+ if (!obj)
595
+ break;
596
+ cur = this.unwrapParen(obj);
597
+ }
598
+ else {
599
+ break;
600
+ }
601
+ }
602
+ let rootIdx;
603
+ let rootSegment;
604
+ if (cur.type === 'variable_name') {
605
+ rootIdx = this.resolve(cur);
606
+ acc.addUse(rootIdx);
607
+ rootSegment = cur.text;
608
+ }
609
+ else {
610
+ this.walkValue(cur, acc);
611
+ }
612
+ const innermost = accesses[0];
613
+ if (rootIdx !== undefined && innermost)
614
+ acc.addMemberRead(rootIdx, innermost);
615
+ const path = rootSegment !== undefined && accesses.every((a) => a !== '')
616
+ ? [rootSegment, ...accesses].join('.')
617
+ : undefined;
618
+ return { path, rootIdx };
619
+ }
620
+ }
621
+ /**
622
+ * Ordered, deduplicating def/use + call-site collector for one statement record.
623
+ * The shared {@link CallSiteFactAccumulator} carries the def/use machinery plus
624
+ * the taint-site harvest.
625
+ */
626
+ const FactAccumulator = CallSiteFactAccumulator;