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,739 @@
1
+ import { CallSiteFactAccumulator as FactAccumulator, finalizeChain } 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(['function_definition', 'lambda']);
4
+ /** LHS pattern containers whose identifier/splat leaves are assignment targets. */
5
+ const PATTERN_LIST_TYPES = new Set(['pattern_list', 'tuple_pattern', 'list_pattern']);
6
+ export class PythonHarvester {
7
+ fnNode;
8
+ bindings = [];
9
+ /** Single function-scope name → binding index (Python has no block scope). */
10
+ table = new Map();
11
+ synthetic = new Map();
12
+ /** Names declared `global`/`nonlocal` — resolve to the synthetic module binding. */
13
+ globalNames = new Set();
14
+ fnId;
15
+ /** >0 while walking a conditionally-evaluated subexpression — defs become may-defs. */
16
+ conditionalDepth = 0;
17
+ /**
18
+ * `call` node id → binding indices its single-target result is assigned to
19
+ * (`x = f()` ⇒ `[x]`). Populated just before the value walk reaches the call
20
+ * (see {@link registerResultDefs}) and consumed by {@link visitCall}. Mirrors
21
+ * the Go 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
+ const body = this.bodyOf(fnNode);
29
+ if (body)
30
+ this.prescan(body);
31
+ }
32
+ /** The completed binding table — pass to `CfgBuilder.finish`. */
33
+ bindingTable() {
34
+ return this.bindings;
35
+ }
36
+ /** The function/lambda body node (a `block` for `def`, an expression for `lambda`). */
37
+ bodyOf(fnNode) {
38
+ return fnNode.childForFieldName('body') ?? undefined;
39
+ }
40
+ // ── phase 1: declaration pre-scan ────────────────────────────────────────
41
+ declare(nameNode, kind) {
42
+ const name = nameNode.text;
43
+ if (!name || name === '_' || this.table.has(name) || this.globalNames.has(name))
44
+ return;
45
+ this.table.set(name, this.bindings.length);
46
+ this.bindings.push({
47
+ name,
48
+ declLine: nameNode.startPosition.row + 1,
49
+ declColumn: nameNode.startPosition.column,
50
+ kind,
51
+ });
52
+ }
53
+ /** Declare every parameter binder (incl. defaults, typed, `*args`, `**kwargs`). */
54
+ declareParams(fnNode) {
55
+ const params = fnNode.childForFieldName('parameters') ??
56
+ fnNode.namedChildren.find((c) => c.type === 'parameters' || c.type === 'lambda_parameters');
57
+ if (!params)
58
+ return;
59
+ for (let i = 0; i < params.namedChildCount; i++) {
60
+ const p = params.namedChild(i);
61
+ if (p)
62
+ this.declareParam(p);
63
+ }
64
+ }
65
+ /** Declare the binder identifier(s) of one parameter node. */
66
+ declareParam(p) {
67
+ switch (p.type) {
68
+ case 'identifier':
69
+ this.declare(p, 'param');
70
+ return;
71
+ case 'default_parameter':
72
+ case 'typed_default_parameter': {
73
+ const name = p.childForFieldName('name');
74
+ if (name)
75
+ this.declareParamBinder(name);
76
+ return;
77
+ }
78
+ case 'typed_parameter': {
79
+ // No `name` field — the binder is the first non-`type` named child
80
+ // (an identifier or a splat pattern).
81
+ const typeNode = p.childForFieldName('type');
82
+ for (let i = 0; i < p.namedChildCount; i++) {
83
+ const c = p.namedChild(i);
84
+ if (c && c.id !== typeNode?.id) {
85
+ this.declareParamBinder(c);
86
+ break;
87
+ }
88
+ }
89
+ return;
90
+ }
91
+ case 'list_splat_pattern':
92
+ case 'dictionary_splat_pattern':
93
+ this.declareParamBinder(p);
94
+ return;
95
+ default:
96
+ // tuple-grouped params and the like — declare any identifier leaves.
97
+ this.declareParamBinder(p);
98
+ }
99
+ }
100
+ /** Declare a binder that may be an identifier or a `*`/`**` splat pattern. */
101
+ declareParamBinder(node) {
102
+ if (node.type === 'identifier') {
103
+ this.declare(node, 'param');
104
+ return;
105
+ }
106
+ if (node.type === 'list_splat_pattern' || node.type === 'dictionary_splat_pattern') {
107
+ const id = node.namedChild(0);
108
+ if (id?.type === 'identifier')
109
+ this.declare(id, 'param');
110
+ return;
111
+ }
112
+ // Nested grouping — declare identifier descendants up to the next binder.
113
+ for (let i = 0; i < node.namedChildCount; i++) {
114
+ const c = node.namedChild(i);
115
+ if (c?.type === 'identifier')
116
+ this.declare(c, 'param');
117
+ }
118
+ }
119
+ /**
120
+ * Pre-scan the function body once, declaring every in-function name. Recurses
121
+ * into compound statements but NOT into nested `function_definition` / `lambda`
122
+ * bodies (opaque). `global`/`nonlocal` are processed FIRST in a sibling sweep
123
+ * so a later assignment to a global name does not mint a function-local.
124
+ */
125
+ prescan(node) {
126
+ const t = node.type;
127
+ if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
128
+ return;
129
+ switch (t) {
130
+ case 'global_statement':
131
+ case 'nonlocal_statement': {
132
+ for (let i = 0; i < node.namedChildCount; i++) {
133
+ const c = node.namedChild(i);
134
+ if (c?.type === 'identifier')
135
+ this.globalNames.add(c.text);
136
+ }
137
+ return;
138
+ }
139
+ case 'assignment': {
140
+ const left = node.childForFieldName('left');
141
+ if (left)
142
+ this.declareTargets(left);
143
+ break;
144
+ }
145
+ case 'augmented_assignment': {
146
+ const left = node.childForFieldName('left');
147
+ if (left)
148
+ this.declareTargets(left);
149
+ break;
150
+ }
151
+ case 'named_expression': {
152
+ const name = node.childForFieldName('name');
153
+ if (name?.type === 'identifier')
154
+ this.declare(name, 'let');
155
+ break;
156
+ }
157
+ case 'for_statement':
158
+ case 'for_in_clause': {
159
+ const left = node.childForFieldName('left');
160
+ if (left)
161
+ this.declareTargets(left);
162
+ break;
163
+ }
164
+ case 'with_item': {
165
+ this.declareWithItem(node);
166
+ break;
167
+ }
168
+ case 'except_clause':
169
+ case 'except_group_clause': {
170
+ this.declareExceptAlias(node);
171
+ break;
172
+ }
173
+ default:
174
+ break;
175
+ }
176
+ for (let i = 0; i < node.namedChildCount; i++) {
177
+ const c = node.namedChild(i);
178
+ if (c)
179
+ this.prescan(c);
180
+ }
181
+ }
182
+ /** Declare identifier/splat leaves of an assignment / loop target pattern. */
183
+ declareTargets(target) {
184
+ const t = target.type;
185
+ if (t === 'identifier') {
186
+ this.declare(target, 'let');
187
+ return;
188
+ }
189
+ if (PATTERN_LIST_TYPES.has(t)) {
190
+ for (let i = 0; i < target.namedChildCount; i++) {
191
+ const c = target.namedChild(i);
192
+ if (c)
193
+ this.declareTargets(c);
194
+ }
195
+ return;
196
+ }
197
+ if (t === 'list_splat_pattern') {
198
+ const id = target.namedChild(0);
199
+ if (id?.type === 'identifier')
200
+ this.declare(id, 'let');
201
+ return;
202
+ }
203
+ // attribute / subscript target — not a scalar def (root is a use only).
204
+ }
205
+ /** `with EXPR as TARGET` — declare the alias target(s). */
206
+ declareWithItem(item) {
207
+ const value = item.childForFieldName('value') ?? item.namedChild(0);
208
+ if (value?.type !== 'as_pattern')
209
+ return;
210
+ const alias = value.childForFieldName('alias') ?? this.asPatternTarget(value);
211
+ if (alias)
212
+ this.declareAsTarget(alias);
213
+ }
214
+ /** `except E as e` — declare `e`. */
215
+ declareExceptAlias(clause) {
216
+ for (let i = 0; i < clause.namedChildCount; i++) {
217
+ const c = clause.namedChild(i);
218
+ if (c?.type === 'as_pattern') {
219
+ const alias = c.childForFieldName('alias') ?? this.asPatternTarget(c);
220
+ if (alias)
221
+ this.declareAsTarget(alias, 'catch');
222
+ }
223
+ }
224
+ }
225
+ /** The `as_pattern_target` child of an `as_pattern` (when no `alias` field). */
226
+ asPatternTarget(asPattern) {
227
+ return asPattern.namedChildren.find((c) => c.type === 'as_pattern_target');
228
+ }
229
+ /** Declare an `as_pattern_target` (or its identifier child) as a binding. */
230
+ declareAsTarget(target, kind = 'let') {
231
+ if (target.type === 'identifier') {
232
+ this.declare(target, kind);
233
+ return;
234
+ }
235
+ // `as_pattern_target` wraps an identifier (or a tuple pattern).
236
+ const inner = target.namedChild(0);
237
+ if (inner?.type === 'identifier')
238
+ this.declare(inner, kind);
239
+ else if (inner)
240
+ this.declareTargets(inner);
241
+ else
242
+ this.declare(target, kind); // a bare `as_pattern_target` text IS the name
243
+ }
244
+ // ── phase 2: per-statement fact extraction ───────────────────────────────
245
+ /** Def/use facts for one statement (or construct-header expression) node. */
246
+ facts(node) {
247
+ const acc = new FactAccumulator(node.startPosition.row + 1);
248
+ this.walkValue(node, acc);
249
+ return acc.finish();
250
+ }
251
+ /** Facts for an expression whose WHOLE evaluation is conditional (case tests). */
252
+ factsConditional(node) {
253
+ const acc = new FactAccumulator(node.startPosition.row + 1);
254
+ this.conditional(() => this.walkValue(node, acc));
255
+ return acc.finish();
256
+ }
257
+ /**
258
+ * Facts for a `for TARGET in ITER` / `for_in_clause` head: the loop target(s)
259
+ * are defs, the iterated expression is a use.
260
+ */
261
+ loopHeadFacts(headNode) {
262
+ const acc = new FactAccumulator(headNode.startPosition.row + 1);
263
+ const left = headNode.childForFieldName('left');
264
+ const right = headNode.childForFieldName('right');
265
+ if (right)
266
+ this.walkValue(right, acc);
267
+ if (left)
268
+ this.defTargets(left, acc);
269
+ return acc.finish();
270
+ }
271
+ /** Facts for a `with_item`: the `as` alias is a def, the value an use. */
272
+ withItemFacts(item) {
273
+ const acc = new FactAccumulator(item.startPosition.row + 1);
274
+ const value = item.childForFieldName('value') ?? item.namedChild(0);
275
+ if (!value)
276
+ return acc.finish();
277
+ if (value.type === 'as_pattern') {
278
+ const inner = value.namedChild(0);
279
+ if (inner)
280
+ this.walkValue(inner, acc);
281
+ const alias = value.childForFieldName('alias') ?? this.asPatternTarget(value);
282
+ if (alias)
283
+ this.defAsTarget(alias, acc);
284
+ }
285
+ else {
286
+ this.walkValue(value, acc);
287
+ }
288
+ return acc.finish();
289
+ }
290
+ /** Facts for an `except E as e:` header: `e` is a def, `E` a use. */
291
+ exceptHeadFacts(clause) {
292
+ const acc = new FactAccumulator(clause.startPosition.row + 1);
293
+ const block = clause.namedChildren.find((c) => c.type === 'block');
294
+ for (let i = 0; i < clause.namedChildCount; i++) {
295
+ const c = clause.namedChild(i);
296
+ if (!c || c.id === block?.id)
297
+ continue;
298
+ if (c.type === 'as_pattern') {
299
+ const exc = c.namedChild(0);
300
+ if (exc)
301
+ this.walkValue(exc, acc);
302
+ const alias = c.childForFieldName('alias') ?? this.asPatternTarget(c);
303
+ if (alias)
304
+ this.defAsTarget(alias, acc);
305
+ }
306
+ else {
307
+ this.walkValue(c, acc);
308
+ }
309
+ }
310
+ return acc.finish();
311
+ }
312
+ /** ENTRY-block facts for the parameters (defs only — incl. default-value uses). */
313
+ paramFacts() {
314
+ const params = this.fnNode.childForFieldName('parameters') ??
315
+ this.fnNode.namedChildren.find((c) => c.type === 'parameters' || c.type === 'lambda_parameters');
316
+ if (!params)
317
+ return undefined;
318
+ const acc = new FactAccumulator(this.fnNode.startPosition.row + 1);
319
+ for (let i = 0; i < params.namedChildCount; i++) {
320
+ const p = params.namedChild(i);
321
+ if (p)
322
+ this.defParam(p, acc);
323
+ }
324
+ return acc.defCount() || acc.finish().uses.length ? acc.finish() : undefined;
325
+ }
326
+ /** Def the binder(s) of one parameter node and use any default-value expr. */
327
+ defParam(p, acc) {
328
+ switch (p.type) {
329
+ case 'identifier':
330
+ this.def(p, acc);
331
+ return;
332
+ case 'default_parameter':
333
+ case 'typed_default_parameter': {
334
+ const value = p.childForFieldName('value');
335
+ if (value)
336
+ this.walkValue(value, acc);
337
+ const name = p.childForFieldName('name');
338
+ if (name)
339
+ this.defParamBinder(name, acc);
340
+ return;
341
+ }
342
+ case 'typed_parameter': {
343
+ const typeNode = p.childForFieldName('type');
344
+ for (let i = 0; i < p.namedChildCount; i++) {
345
+ const c = p.namedChild(i);
346
+ if (c && c.id !== typeNode?.id) {
347
+ this.defParamBinder(c, acc);
348
+ break;
349
+ }
350
+ }
351
+ return;
352
+ }
353
+ case 'list_splat_pattern':
354
+ case 'dictionary_splat_pattern':
355
+ this.defParamBinder(p, acc);
356
+ return;
357
+ default:
358
+ this.defParamBinder(p, acc);
359
+ }
360
+ }
361
+ defParamBinder(node, acc) {
362
+ if (node.type === 'identifier') {
363
+ this.def(node, acc);
364
+ return;
365
+ }
366
+ if (node.type === 'list_splat_pattern' || node.type === 'dictionary_splat_pattern') {
367
+ const id = node.namedChild(0);
368
+ if (id?.type === 'identifier')
369
+ this.def(id, acc);
370
+ return;
371
+ }
372
+ for (let i = 0; i < node.namedChildCount; i++) {
373
+ const c = node.namedChild(i);
374
+ if (c?.type === 'identifier')
375
+ this.def(c, acc);
376
+ }
377
+ }
378
+ resolve(nameNode) {
379
+ const name = nameNode.text;
380
+ if (!this.globalNames.has(name)) {
381
+ const idx = this.table.get(name);
382
+ if (idx !== undefined)
383
+ return idx;
384
+ }
385
+ let idx = this.synthetic.get(name);
386
+ if (idx === undefined) {
387
+ idx = this.bindings.length;
388
+ this.synthetic.set(name, idx);
389
+ this.bindings.push({ name, declLine: 0, declColumn: 0, kind: 'module', synthetic: true });
390
+ }
391
+ return idx;
392
+ }
393
+ def(nameNode, acc) {
394
+ if (nameNode.text === '_')
395
+ return; // blank target defines nothing of interest
396
+ if (this.conditionalDepth > 0)
397
+ acc.addMayDef(this.resolve(nameNode));
398
+ else
399
+ acc.addDef(this.resolve(nameNode));
400
+ }
401
+ use(nameNode, acc) {
402
+ if (nameNode.text === '_')
403
+ return;
404
+ acc.addUse(this.resolve(nameNode));
405
+ }
406
+ /** Run `fn` with defs demoted to may-defs (conditionally-evaluated context). */
407
+ conditional(fn) {
408
+ this.conditionalDepth++;
409
+ try {
410
+ fn();
411
+ }
412
+ finally {
413
+ this.conditionalDepth--;
414
+ }
415
+ }
416
+ /**
417
+ * Def each identifier/splat leaf of an assignment / loop target pattern; route
418
+ * attribute / subscript targets to the value walk (root identifier is a use).
419
+ */
420
+ defTargets(target, acc) {
421
+ const t = target.type;
422
+ if (t === 'identifier') {
423
+ this.def(target, acc);
424
+ return;
425
+ }
426
+ if (PATTERN_LIST_TYPES.has(t)) {
427
+ for (let i = 0; i < target.namedChildCount; i++) {
428
+ const c = target.namedChild(i);
429
+ if (c)
430
+ this.defTargets(c, acc);
431
+ }
432
+ return;
433
+ }
434
+ if (t === 'list_splat_pattern') {
435
+ const id = target.namedChild(0);
436
+ if (id?.type === 'identifier')
437
+ this.def(id, acc);
438
+ else if (id)
439
+ this.defTargets(id, acc);
440
+ return;
441
+ }
442
+ // attribute / subscript / call target — uses only (the root identifier).
443
+ this.walkValue(target, acc);
444
+ }
445
+ /** Def an `as_pattern_target` (or its identifier child). */
446
+ defAsTarget(target, acc) {
447
+ if (target.type === 'identifier') {
448
+ this.def(target, acc);
449
+ return;
450
+ }
451
+ const inner = target.namedChild(0);
452
+ if (inner?.type === 'identifier')
453
+ this.def(inner, acc);
454
+ else if (inner)
455
+ this.defTargets(inner, acc);
456
+ else
457
+ this.def(target, acc);
458
+ }
459
+ /** Value-position walk: collect uses; route def positions to the target handler. */
460
+ walkValue(node, acc) {
461
+ const t = node.type;
462
+ if (NESTED_FUNCTION_TYPES.has(t) && node.id !== this.fnId)
463
+ return; // opaque
464
+ switch (t) {
465
+ case 'identifier':
466
+ this.use(node, acc);
467
+ return;
468
+ case 'assignment': {
469
+ const left = node.childForFieldName('left');
470
+ const right = node.childForFieldName('right');
471
+ // Register result-defs BEFORE walking the value so the nested call site
472
+ // (reached during the value walk) carries them — single identifier
473
+ // target only (`x = f()`); a tuple/attribute LHS attaches nothing.
474
+ if (left?.type === 'identifier' && right)
475
+ this.registerResultDefs(right, [left]);
476
+ if (right)
477
+ this.walkValue(right, acc);
478
+ if (left)
479
+ this.defTargets(left, acc);
480
+ return;
481
+ }
482
+ case 'augmented_assignment': {
483
+ const left = node.childForFieldName('left');
484
+ const right = node.childForFieldName('right');
485
+ if (right)
486
+ this.walkValue(right, acc);
487
+ if (left) {
488
+ // `x += v` reads AND writes a plain-identifier lvalue.
489
+ if (left.type === 'identifier') {
490
+ this.use(left, acc);
491
+ this.def(left, acc);
492
+ }
493
+ else {
494
+ this.walkValue(left, acc); // attribute/subscript lvalue — use only
495
+ }
496
+ }
497
+ return;
498
+ }
499
+ case 'named_expression': {
500
+ // walrus `(n := v)` — `n` is a def, `v` a use.
501
+ const name = node.childForFieldName('name');
502
+ const value = node.childForFieldName('value');
503
+ if (name?.type === 'identifier' && value)
504
+ this.registerResultDefs(value, [name]);
505
+ if (value)
506
+ this.walkValue(value, acc);
507
+ if (name?.type === 'identifier')
508
+ this.def(name, acc);
509
+ return;
510
+ }
511
+ case 'boolean_operator': {
512
+ // `a or b` / `a and b` — the right operand is conditionally evaluated, so
513
+ // any def inside it (a walrus) is a may-def; uses are still recorded.
514
+ const left = node.childForFieldName('left');
515
+ const right = node.childForFieldName('right');
516
+ if (left)
517
+ this.walkValue(left, acc);
518
+ if (right)
519
+ this.conditional(() => this.walkValue(right, acc));
520
+ return;
521
+ }
522
+ case 'conditional_expression': {
523
+ // `consequent if condition else alternative`. The condition always
524
+ // evaluates; each arm is conditional (its walrus defs are may-defs).
525
+ const children = node.namedChildren;
526
+ const [consequent, condition, alternative] = children;
527
+ if (condition)
528
+ this.walkValue(condition, acc);
529
+ if (consequent)
530
+ this.conditional(() => this.walkValue(consequent, acc));
531
+ if (alternative)
532
+ this.conditional(() => this.walkValue(alternative, acc));
533
+ return;
534
+ }
535
+ case 'attribute': {
536
+ // `a.b` — value read of the operand root only; the attribute name is not
537
+ // a scalar binding. Records the chain-root use plus at most ONE
538
+ // member-read site (the innermost identifier-rooted access), mirroring
539
+ // the Go harvester's value-position `walkChain`.
540
+ this.walkChain(node, acc, false);
541
+ return;
542
+ }
543
+ case 'subscript': {
544
+ // `a[i]` — both the container root and the index are uses.
545
+ const value = node.childForFieldName('value');
546
+ const sub = node.childForFieldName('subscript');
547
+ if (value)
548
+ this.walkValue(value, acc);
549
+ if (sub)
550
+ this.walkValue(sub, acc);
551
+ return;
552
+ }
553
+ case 'call':
554
+ // #2227 follow-up: explicit case (previously default-descended) — same
555
+ // uses, plus a taint-site record. Python has no `new` (constructor calls
556
+ // are plain `call`s). Defs/uses stay byte-identical.
557
+ this.visitCall(node, acc);
558
+ return;
559
+ case 'list_comprehension':
560
+ case 'set_comprehension':
561
+ case 'dictionary_comprehension':
562
+ case 'generator_expression': {
563
+ this.walkComprehension(node, acc);
564
+ return;
565
+ }
566
+ case 'keyword_argument': {
567
+ // `f(k=v)` — `k` is a parameter name, not a use; only `v` is a use.
568
+ const value = node.childForFieldName('value');
569
+ if (value)
570
+ this.walkValue(value, acc);
571
+ return;
572
+ }
573
+ default:
574
+ for (let i = 0; i < node.namedChildCount; i++) {
575
+ const c = node.namedChild(i);
576
+ if (c)
577
+ this.walkValue(c, acc);
578
+ }
579
+ }
580
+ }
581
+ /**
582
+ * A comprehension (`[body for t in src if g]`): each `for_in_clause` target is
583
+ * a def, its source a use; the `body` and any `if_clause` are uses. Kept INLINE
584
+ * (no separate CFG blocks) per the plan — the target binding is harvested so it
585
+ * is a real def. The `for_in_clause` source is walked in the ENCLOSING context
586
+ * (it reads outer names), the body/filter after the targets are bound.
587
+ */
588
+ walkComprehension(node, acc) {
589
+ const body = node.childForFieldName('body');
590
+ for (let i = 0; i < node.namedChildCount; i++) {
591
+ const c = node.namedChild(i);
592
+ if (!c)
593
+ continue;
594
+ if (c.type === 'for_in_clause') {
595
+ const left = c.childForFieldName('left');
596
+ const right = c.childForFieldName('right');
597
+ if (right)
598
+ this.walkValue(right, acc);
599
+ if (left)
600
+ this.defTargets(left, acc);
601
+ }
602
+ else if (c.id !== body?.id) {
603
+ // `if_clause` filter (and any other auxiliary clause) — uses only.
604
+ this.walkValue(c, acc);
605
+ }
606
+ }
607
+ if (body)
608
+ this.walkValue(body, acc);
609
+ }
610
+ // ── taint-site harvest (#2227 follow-up) ─────────────────────────────────
611
+ /**
612
+ * When `value`'s root (after stripping parens) is a `call`, remember that
613
+ * call site should carry `resultDefs` — the binding indices of `targets`
614
+ * (def-position identifiers). Consumed by {@link visitCall} once the value
615
+ * walk reaches the node. Single-target only (the caller restricts to a plain
616
+ * identifier LHS); the blank identifier (`_`) binds nothing and is skipped.
617
+ */
618
+ registerResultDefs(value, targets) {
619
+ const root = this.unwrapValue(value);
620
+ if (root.type !== 'call')
621
+ return;
622
+ const defs = [];
623
+ for (const target of targets) {
624
+ if (target.type !== 'identifier' || target.text === '_')
625
+ continue;
626
+ defs.push(this.resolve(target));
627
+ }
628
+ if (defs.length > 0)
629
+ this.resultDefTargets.set(root.id, defs);
630
+ }
631
+ /** Strip `parenthesized_expression` wrappers around a value (`(f())`). */
632
+ unwrapValue(node) {
633
+ let n = node;
634
+ let hops = 8;
635
+ while (n.type === 'parenthesized_expression' && hops-- > 0) {
636
+ const inner = n.namedChild(0);
637
+ if (!inner)
638
+ break;
639
+ n = inner;
640
+ }
641
+ return n;
642
+ }
643
+ /**
644
+ * Explicit `call` handler. Records a call site (callee path, receiver, per-arg
645
+ * occurrence entries, result defs, spread marker) while reproducing EXACTLY
646
+ * the uses the old default descent recorded (callee chain root + arguments).
647
+ * Python has no `new` — every site is `kind: 'call'`.
648
+ */
649
+ visitCall(node, acc) {
650
+ const calleeNode = node.childForFieldName('function');
651
+ const argsNode = node.childForFieldName('arguments');
652
+ // `node` IS the `call` — the SAME node the scope-extractor anchors
653
+ // `@reference.call.free/.member` on (its `atRange`), so the resolved-id join
654
+ // lands by exact position.
655
+ const siteIdx = acc.openCallSite('call', [
656
+ node.startPosition.row + 1,
657
+ node.startPosition.column,
658
+ ]);
659
+ acc.pushFrame(siteIdx);
660
+ if (calleeNode) {
661
+ const callee = this.unwrapValue(calleeNode);
662
+ if (callee.type === 'identifier') {
663
+ if (callee.text !== '_')
664
+ acc.addUseWithoutOccurrence(this.resolve(callee));
665
+ acc.setSiteCallee(siteIdx, callee.text);
666
+ }
667
+ else if (callee.type === 'attribute') {
668
+ // skipFinalRead: the final `.attr` IS the callee, carried by the path.
669
+ const chain = this.walkChain(callee, acc, true);
670
+ if (chain.path !== undefined)
671
+ acc.setSiteCallee(siteIdx, chain.path);
672
+ if (chain.rootIdx !== undefined)
673
+ acc.setSiteReceiver(siteIdx, chain.rootIdx);
674
+ }
675
+ else {
676
+ // Call-rooted chains (`a().b()`), subscripts (`d[k]()`) — the walk still
677
+ // records uses and nested sites; the callee path is not statically known.
678
+ this.walkValue(callee, acc);
679
+ }
680
+ }
681
+ const resultDefs = this.resultDefTargets.get(node.id);
682
+ if (resultDefs !== undefined)
683
+ acc.setSiteResultDefs(siteIdx, resultDefs);
684
+ if (argsNode) {
685
+ let pos = 0;
686
+ for (let i = 0; i < argsNode.namedChildCount; i++) {
687
+ const arg = argsNode.namedChild(i);
688
+ if (!arg || arg.type === 'comment')
689
+ continue;
690
+ if (arg.type === 'list_splat' || arg.type === 'dictionary_splat') {
691
+ // `f(*args)` / `f(**kw)` — a spread. Mark the first spread position so
692
+ // the matcher degrades soundly; the inner value still walks.
693
+ acc.setFrameArg(pos);
694
+ acc.setSiteSpread(siteIdx, pos);
695
+ const inner = arg.namedChild(0);
696
+ if (inner)
697
+ this.walkValue(inner, acc);
698
+ }
699
+ else {
700
+ // Positional or `keyword_argument` — the `keyword_argument` case in
701
+ // `walkValue` walks only its `value`, so the key name is not a use.
702
+ acc.setFrameArg(pos);
703
+ this.walkValue(arg, acc);
704
+ }
705
+ pos++;
706
+ }
707
+ }
708
+ acc.popFrame();
709
+ }
710
+ /**
711
+ * `attribute` chain walk shared by value position and callee position. Records
712
+ * the chain-root identifier as a use (identical to the old default descent)
713
+ * plus at most ONE member-read site — the INNERMOST access — when the root is
714
+ * an identifier; `skipFinalRead` suppresses it when that access is the callee
715
+ * (carried by the dotted path instead). Mirrors the Go harvester's `walkChain`.
716
+ */
717
+ walkChain(node, acc, skipFinalRead) {
718
+ const accesses = [];
719
+ let cur = this.unwrapValue(node);
720
+ for (;;) {
721
+ if (cur.type === 'attribute') {
722
+ const field = cur.childForFieldName('attribute');
723
+ accesses.unshift(field?.text ?? '');
724
+ const operand = cur.childForFieldName('object');
725
+ if (!operand)
726
+ break;
727
+ cur = this.unwrapValue(operand);
728
+ }
729
+ else {
730
+ break;
731
+ }
732
+ }
733
+ // The shared terminal: root-use record + innermost member-read + path-join.
734
+ return finalizeChain(acc, cur, accesses, skipFinalRead, (t) => t === 'identifier', {
735
+ resolve: (n) => this.resolve(n),
736
+ walkRoot: (n) => this.walkValue(n, acc),
737
+ });
738
+ }
739
+ }