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,638 @@
1
+ import { CfgBuilder } from '../cfg-builder.js';
2
+ import { ControlFlowContext, drainFinalizerPending, wireJumpThroughFinalizers, } from '../control-flow-context.js';
3
+ import { GoHarvester } from './go-harvest.js';
4
+ /** Go node types that own a CFG-bearing function body. */
5
+ const GO_FUNCTION_TYPES = new Set(['function_declaration', 'method_declaration', 'func_literal']);
6
+ /** Statement node types that break a basic block (everything else coalesces). */
7
+ const CONTROL_FLOW_TYPES = new Set([
8
+ 'if_statement',
9
+ 'for_statement',
10
+ 'expression_switch_statement',
11
+ 'type_switch_statement',
12
+ 'select_statement',
13
+ 'return_statement',
14
+ 'break_statement',
15
+ 'continue_statement',
16
+ 'goto_statement',
17
+ 'labeled_statement',
18
+ 'fallthrough_statement',
19
+ 'defer_statement',
20
+ 'block',
21
+ ]);
22
+ const startLineOf = (n) => n.startPosition.row + 1;
23
+ const endLineOf = (n) => n.endPosition.row + 1;
24
+ /**
25
+ * Per-function Go walk state. One instance per function so the
26
+ * {@link ControlFlowContext}, the `defer` finalizer chain, and the label tables
27
+ * are scoped to that function and never leak across functions.
28
+ */
29
+ class GoCfgWalk {
30
+ builder;
31
+ harvest;
32
+ cfc = new ControlFlowContext();
33
+ /** label name → its `labeled_statement` body's entry block (resolved on demand). */
34
+ labelBlocks = new Map();
35
+ /** Pending gotos to a label not yet seen: label → list of source blocks. */
36
+ pendingGotos = new Map();
37
+ /** Label(s) pending attachment to the NEXT pushed loop/switch/select frame. */
38
+ pendingLabels = [];
39
+ /**
40
+ * Active `defer` finalizer frames in source (push) order. Innermost-LIFO is the
41
+ * REVERSE of this list — `finalizersForReturn()` already yields innermost-first,
42
+ * matching Go's LIFO defer execution. Frames stay active for the whole function
43
+ * tail and are drained once at the top-level walk's end.
44
+ */
45
+ deferFrames = [];
46
+ constructor(builder, harvest) {
47
+ this.builder = builder;
48
+ this.harvest = harvest;
49
+ }
50
+ /** Statements of a block node, ignoring comments. */
51
+ statementsOf(block) {
52
+ return block.namedChildren.filter((c) => c.type !== 'comment');
53
+ }
54
+ /** The `body` block of a node. */
55
+ bodyBlockOf(node) {
56
+ return node.childForFieldName('body') ?? node.namedChildren.find((c) => c.type === 'block');
57
+ }
58
+ /** Visit a body that may be a `block` or a single statement. */
59
+ visitBody(node) {
60
+ return this.builder.withNesting(() => {
61
+ if (!node)
62
+ return null;
63
+ if (node.type === 'block')
64
+ return this.visitSeq(this.statementsOf(node));
65
+ return this.visitStmt(node);
66
+ });
67
+ }
68
+ /** Wire a sequence of statements, coalescing straight-line runs into blocks. */
69
+ visitSeq(stmts) {
70
+ return this.builder.withNesting(() => {
71
+ let entry;
72
+ let dangling = [];
73
+ let openSimple;
74
+ for (const stmt of stmts) {
75
+ if (CONTROL_FLOW_TYPES.has(stmt.type)) {
76
+ openSimple = undefined; // close any open straight-line block
77
+ const res = this.visitStmt(stmt);
78
+ if (res === null)
79
+ continue; // transparent (empty nested block)
80
+ if (entry === undefined)
81
+ entry = res.entry;
82
+ else
83
+ this.builder.connect(dangling, res.entry, 'seq');
84
+ dangling = [...res.exits];
85
+ }
86
+ else {
87
+ if (openSimple === undefined) {
88
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text, 'normal', this.harvest.facts(stmt));
89
+ if (entry === undefined)
90
+ entry = idx;
91
+ else
92
+ this.builder.connect(dangling, idx, 'seq');
93
+ openSimple = idx;
94
+ dangling = [idx];
95
+ }
96
+ else {
97
+ this.builder.extendBlock(openSimple, endLineOf(stmt), stmt.text, this.harvest.facts(stmt));
98
+ }
99
+ }
100
+ }
101
+ if (entry === undefined)
102
+ return null;
103
+ return { entry, exits: dangling };
104
+ });
105
+ }
106
+ /** Dispatch one statement to its handler. Non-null except for empty blocks. */
107
+ visitStmt(stmt) {
108
+ switch (stmt.type) {
109
+ case 'if_statement':
110
+ return this.visitIf(stmt);
111
+ case 'for_statement':
112
+ return this.visitFor(stmt);
113
+ case 'expression_switch_statement':
114
+ return this.visitExprSwitch(stmt);
115
+ case 'type_switch_statement':
116
+ return this.visitTypeSwitch(stmt);
117
+ case 'select_statement':
118
+ return this.visitSelect(stmt);
119
+ case 'return_statement':
120
+ return this.visitReturn(stmt);
121
+ case 'break_statement':
122
+ return this.visitBreak(stmt);
123
+ case 'continue_statement':
124
+ return this.visitContinue(stmt);
125
+ case 'goto_statement':
126
+ return this.visitGoto(stmt);
127
+ case 'labeled_statement':
128
+ return this.visitLabeled(stmt);
129
+ case 'fallthrough_statement':
130
+ return this.visitFallthrough(stmt);
131
+ case 'defer_statement':
132
+ return this.visitDefer(stmt);
133
+ case 'block':
134
+ return this.visitSeq(this.statementsOf(stmt));
135
+ default:
136
+ return this.visitSimple(stmt);
137
+ }
138
+ }
139
+ visitSimple(stmt) {
140
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text, 'normal', this.harvest.facts(stmt));
141
+ return { entry: idx, exits: [idx] };
142
+ }
143
+ /**
144
+ * `return [expr…]` — threads through EVERY active `defer` (innermost-first =
145
+ * LIFO) before EXIT. `finalizersForReturn()` yields the active finalizer frames
146
+ * innermost-first, which is exactly Go's defer execution order.
147
+ */
148
+ visitReturn(stmt) {
149
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text, 'normal', this.harvest.facts(stmt));
150
+ wireJumpThroughFinalizers(this.builder, idx, this.cfc.finalizersForReturn(), this.builder.exitIndex, 'return');
151
+ return { entry: idx, exits: [] };
152
+ }
153
+ visitBreak(stmt) {
154
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text);
155
+ const label = this.jumpLabel(stmt);
156
+ const res = this.cfc.resolveBreak(label);
157
+ const { target, finalizers } = res ?? {
158
+ target: this.builder.exitIndex,
159
+ finalizers: this.cfc.finalizersForReturn(),
160
+ };
161
+ wireJumpThroughFinalizers(this.builder, idx, finalizers, target, 'break');
162
+ return { entry: idx, exits: [] };
163
+ }
164
+ visitContinue(stmt) {
165
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text);
166
+ const label = this.jumpLabel(stmt);
167
+ const res = this.cfc.resolveContinue(label);
168
+ const { target, finalizers } = res ?? {
169
+ target: this.builder.exitIndex,
170
+ finalizers: this.cfc.finalizersForReturn(),
171
+ };
172
+ wireJumpThroughFinalizers(this.builder, idx, finalizers, target, 'continue');
173
+ return { entry: idx, exits: [] };
174
+ }
175
+ /** The trailing `label_name` of a `break`/`continue`, if any. */
176
+ jumpLabel(stmt) {
177
+ const id = stmt.namedChildren.find((c) => c.type === 'label_name');
178
+ return id?.text;
179
+ }
180
+ /** `goto label;` — route to the label block if known, else defer / EXIT. */
181
+ visitGoto(stmt) {
182
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text);
183
+ const label = stmt.namedChildren.find((c) => c.type === 'label_name')?.text;
184
+ if (label === undefined) {
185
+ this.builder.edge(idx, this.builder.exitIndex, 'seq'); // malformed — single-exit
186
+ return { entry: idx, exits: [] };
187
+ }
188
+ const target = this.labelBlocks.get(label);
189
+ if (target !== undefined) {
190
+ this.builder.edge(idx, target, 'seq'); // backward goto: label already built
191
+ }
192
+ else {
193
+ const list = this.pendingGotos.get(label);
194
+ if (list)
195
+ list.push(idx);
196
+ else
197
+ this.pendingGotos.set(label, [idx]);
198
+ }
199
+ return { entry: idx, exits: [] };
200
+ }
201
+ /**
202
+ * `label: <statement>` — the label names the construct it directly wraps. For a
203
+ * loop / switch / select we forward the label so its pushed frame carries it
204
+ * (`break outer;` then resolves to it); for any other labeled statement we
205
+ * register the label block so a `goto label` reaches it.
206
+ */
207
+ visitLabeled(stmt) {
208
+ const labelNode = stmt.childForFieldName('label');
209
+ const label = labelNode?.text;
210
+ const body = stmt.namedChildren.find((c) => c.id !== labelNode?.id && c.type !== 'comment') ?? null;
211
+ if (label !== undefined && body && this.isBreakableStatement(body)) {
212
+ // Forward the label to the loop/switch/select frame this statement pushes.
213
+ this.pendingLabels = [...this.pendingLabels, label];
214
+ const res = this.visitStmt(body);
215
+ this.registerLabel(label, res?.entry ?? this.synthLabelBlock(stmt));
216
+ return res ?? { entry: this.labelBlocks.get(label), exits: [] };
217
+ }
218
+ const res = this.visitBody(body);
219
+ if (label !== undefined) {
220
+ const entry = res?.entry ?? this.synthLabelBlock(stmt);
221
+ this.registerLabel(label, entry);
222
+ if (!res)
223
+ return { entry, exits: [entry] };
224
+ }
225
+ return res;
226
+ }
227
+ synthLabelBlock(stmt) {
228
+ return this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
229
+ }
230
+ /** Register a resolved label block and wire any forward gotos that waited on it. */
231
+ registerLabel(label, entry) {
232
+ this.labelBlocks.set(label, entry);
233
+ const pending = this.pendingGotos.get(label);
234
+ if (pending) {
235
+ for (const from of pending)
236
+ this.builder.edge(from, entry, 'seq');
237
+ this.pendingGotos.delete(label);
238
+ }
239
+ }
240
+ isBreakableStatement(node) {
241
+ return (node.type === 'for_statement' ||
242
+ node.type === 'expression_switch_statement' ||
243
+ node.type === 'type_switch_statement' ||
244
+ node.type === 'select_statement');
245
+ }
246
+ /** Take and clear the labels queued by an enclosing `labeled_statement`. */
247
+ takeLabels() {
248
+ const labels = this.pendingLabels;
249
+ this.pendingLabels = [];
250
+ return labels;
251
+ }
252
+ /**
253
+ * `fallthrough` — EXPLICIT transfer to the next case body (Go cases do not fall
254
+ * through implicitly). Recorded as a marker block; the enclosing switch wires
255
+ * the `fallthrough` edge from a case body whose dangling exit is this block.
256
+ * It carries no normal exit (control leaves to the next case).
257
+ */
258
+ visitFallthrough(stmt) {
259
+ const idx = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text);
260
+ this.fallthroughBlocks.add(idx);
261
+ return { entry: idx, exits: [idx] };
262
+ }
263
+ /** Blocks that are an explicit `fallthrough` terminator (per-function). */
264
+ fallthroughBlocks = new Set();
265
+ /**
266
+ * `defer f()` — register the deferred call as a finalizer frame that stays
267
+ * active for the rest of the function tail. Every later `return` (and the
268
+ * normal fall-off) threads through it; LIFO across multiple defers falls out of
269
+ * `finalizersForReturn()` yielding innermost-first. The defer's call expression
270
+ * carries its def/use facts. The frame is NOT popped here — the top-level walk
271
+ * drains all defer frames once at function end.
272
+ */
273
+ visitDefer(stmt) {
274
+ // A single facts-only block is created for the deferred call body; it is the
275
+ // finalizer entry that completion legs route through.
276
+ const call = stmt.namedChildren.find((c) => c.type !== 'comment') ?? stmt;
277
+ const deferBlock = this.builder.newBlock(startLineOf(stmt), endLineOf(stmt), stmt.text, 'normal', this.harvest.facts(call));
278
+ const frame = this.cfc.pushFinalizer(deferBlock);
279
+ this.deferFrames.push(frame);
280
+ // The `defer` statement itself is a no-op at its source position — control
281
+ // falls straight through to the next statement (the deferred body only runs
282
+ // at function exit, modeled by the completion-leg threading). We therefore
283
+ // return a SEPARATE marker block as the in-line position so the deferred
284
+ // block stays out of the straight-line flow.
285
+ const marker = this.builder.newBlock(startLineOf(stmt), startLineOf(stmt), '');
286
+ return { entry: marker, exits: [marker] };
287
+ }
288
+ /**
289
+ * Drain the active `defer` chain at function end. Each deferred block is a
290
+ * single block, so its "exit" is itself; the chain runs innermost-first (LIFO,
291
+ * matching Go). Returns the block set control reaches AFTER the whole defer
292
+ * chain runs (to be wired to EXIT by the caller), or `normalExits` unchanged
293
+ * when there are no defers.
294
+ *
295
+ * Two completion sources converge here:
296
+ * - `return` statements that crossed these frames registered pending legs via
297
+ * `wireJumpThroughFinalizers`; {@link drainFinalizerPending} wires them
298
+ * (return → defer[0]; defer[i] → defer[i+1]; defer[last] → EXIT).
299
+ * - the function's NORMAL fall-off is threaded explicitly here through the
300
+ * same chain (`return` first leg, `finally-return` inter-defer legs); the
301
+ * builder de-dups, so legs shared with the return paths collapse.
302
+ */
303
+ finishDefers(normalExits) {
304
+ if (this.deferFrames.length === 0)
305
+ return normalExits;
306
+ // Innermost-first (LIFO): the LAST-registered defer runs first.
307
+ const lifo = [...this.deferFrames].reverse();
308
+ // Pop the frames off the active stack and drain any pending completion legs
309
+ // the return/break handlers registered while these frames were active.
310
+ for (let i = 0; i < lifo.length; i++)
311
+ this.cfc.pop();
312
+ for (const frame of lifo)
313
+ drainFinalizerPending(this.builder, frame, [frame.entry]);
314
+ // Thread the normal fall-off through the chain innermost-first: the first leg
315
+ // keeps the bare `return` kind (the "kind ⟹ source terminator" invariant), the
316
+ // inter-defer legs are `finally-return` completion edges.
317
+ if (normalExits.length > 0) {
318
+ this.builder.connect(normalExits, lifo[0].entry, 'return');
319
+ for (let i = 0; i + 1 < lifo.length; i++) {
320
+ this.builder.edge(lifo[i].entry, lifo[i + 1].entry, 'finally-return');
321
+ }
322
+ }
323
+ // After the outermost defer runs, control reaches EXIT.
324
+ return [lifo[lifo.length - 1].entry];
325
+ }
326
+ /**
327
+ * Route any forward `goto`s whose label never appeared in the function to EXIT
328
+ * (single-exit preserved) and log them so a dropped jump is never silent (R4).
329
+ * Called once after the body walk.
330
+ */
331
+ flushGotos(builder) {
332
+ for (const [label, froms] of this.pendingGotos) {
333
+ // eslint-disable-next-line no-console
334
+ console.warn(`[cfg] Go: unresolved goto label "${label}" routed to EXIT (${froms.length} site(s))`);
335
+ for (const from of froms)
336
+ builder.edge(from, builder.exitIndex, 'seq');
337
+ }
338
+ this.pendingGotos.clear();
339
+ }
340
+ visitIf(stmt) {
341
+ const cond = stmt.childForFieldName('condition') ?? stmt;
342
+ const init = stmt.childForFieldName('initializer');
343
+ // The header block carries the (optional) initializer's facts AND the
344
+ // condition's facts — both evaluate before the branch.
345
+ const header = this.builder.newBlock(init ? startLineOf(init) : startLineOf(stmt), endLineOf(cond), init ? `${init.text}; ${cond.text}` : cond.text, 'normal', this.harvest.facts(cond));
346
+ if (init)
347
+ this.builder.attachFacts(header, this.harvest.facts(init));
348
+ const exits = [];
349
+ const thenRes = this.visitBody(stmt.childForFieldName('consequence'));
350
+ if (thenRes) {
351
+ this.builder.edge(header, thenRes.entry, 'cond-true');
352
+ exits.push(...thenRes.exits);
353
+ }
354
+ else {
355
+ exits.push(header); // empty then — true path falls through
356
+ }
357
+ // No `else_clause` wrapper in Go: `alternative` is the else `block` or the
358
+ // nested `if_statement` of an `else if` chain directly.
359
+ const elseNode = stmt.childForFieldName('alternative');
360
+ if (elseNode) {
361
+ const elseRes = this.visitBody(elseNode);
362
+ if (elseRes) {
363
+ this.builder.edge(header, elseRes.entry, 'cond-false');
364
+ exits.push(...elseRes.exits);
365
+ }
366
+ else {
367
+ exits.push(header);
368
+ }
369
+ }
370
+ else {
371
+ exits.push(header); // no else — false path falls through to the join
372
+ }
373
+ return { entry: header, exits: [...new Set(exits)] };
374
+ }
375
+ /**
376
+ * `for_statement` — Go's single loop keyword covers all four shapes:
377
+ * 1. `for clause { }` (`for_clause`: init?/cond?/update? — C-style)
378
+ * 2. `for range x { }` (`range_clause`)
379
+ * 3. `for cond { }` (a bare condition expression — while-style)
380
+ * 4. `for { }` (no header child — infinite)
381
+ */
382
+ visitFor(stmt) {
383
+ const labels = this.takeLabels();
384
+ const head = this.forHeadChild(stmt);
385
+ if (head?.type === 'for_clause')
386
+ return this.visitForClause(stmt, head, labels);
387
+ if (head?.type === 'range_clause')
388
+ return this.visitForRange(stmt, head, labels);
389
+ // While-style (bare condition) or infinite (`for {}`): `head` is the
390
+ // condition expression (or undefined).
391
+ return this.visitForCond(stmt, head ?? undefined, labels);
392
+ }
393
+ /** The header child of a `for_statement` (for_clause / range_clause / cond), or undefined. */
394
+ forHeadChild(stmt) {
395
+ const body = stmt.childForFieldName('body');
396
+ return stmt.namedChildren.find((c) => c.id !== body?.id && c.type !== 'comment');
397
+ }
398
+ visitForClause(stmt, clause, labels) {
399
+ const init = clause.childForFieldName('initializer');
400
+ const cond = clause.childForFieldName('condition');
401
+ const incr = clause.childForFieldName('update');
402
+ const header = this.builder.newBlock(cond ? startLineOf(cond) : startLineOf(stmt), cond ? endLineOf(cond) : startLineOf(stmt), cond ? cond.text : 'for{}', 'normal', cond ? this.harvest.facts(cond) : undefined);
403
+ const loopExit = this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
404
+ let incrBlock = header;
405
+ if (incr) {
406
+ incrBlock = this.builder.newBlock(startLineOf(incr), endLineOf(incr), incr.text, 'normal', this.harvest.facts(incr));
407
+ this.builder.edge(incrBlock, header, 'loop-back');
408
+ }
409
+ this.cfc.pushLoop(incrBlock, loopExit, labels);
410
+ const body = this.visitBody(this.bodyBlockOf(stmt));
411
+ this.cfc.pop();
412
+ if (body) {
413
+ this.builder.edge(header, body.entry, 'cond-true');
414
+ this.builder.connect(body.exits, incrBlock, incr ? 'seq' : 'loop-back');
415
+ }
416
+ else {
417
+ this.builder.edge(header, incrBlock, 'cond-true');
418
+ if (!incr)
419
+ this.builder.edge(header, header, 'loop-back');
420
+ }
421
+ // Structural exit edge — `for ;; {}` (no condition) still keeps EXIT
422
+ // reverse-reachable so CDG is not silently skipped for the function.
423
+ this.builder.edge(header, loopExit, 'cond-false');
424
+ let entry = header;
425
+ if (init) {
426
+ const initBlock = this.builder.newBlock(startLineOf(init), endLineOf(init), init.text, 'normal', this.harvest.facts(init));
427
+ this.builder.edge(initBlock, header, 'seq');
428
+ entry = initBlock;
429
+ }
430
+ return { entry, exits: [loopExit] };
431
+ }
432
+ visitForRange(stmt, clause, labels) {
433
+ // Header carries the range head facts (loop vars are defs, the iterated
434
+ // expression is a use).
435
+ const header = this.builder.newBlock(startLineOf(stmt), endLineOf(clause), clause.text, 'normal', this.harvest.rangeHeadFacts(clause));
436
+ const loopExit = this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
437
+ this.cfc.pushLoop(header, loopExit, labels);
438
+ const body = this.visitBody(this.bodyBlockOf(stmt));
439
+ this.cfc.pop();
440
+ if (body) {
441
+ this.builder.edge(header, body.entry, 'cond-true');
442
+ this.builder.connect(body.exits, header, 'loop-back');
443
+ }
444
+ else {
445
+ this.builder.edge(header, header, 'loop-back');
446
+ }
447
+ this.builder.edge(header, loopExit, 'cond-false');
448
+ return { entry: header, exits: [loopExit] };
449
+ }
450
+ visitForCond(stmt, cond, labels) {
451
+ const header = this.builder.newBlock(cond ? startLineOf(cond) : startLineOf(stmt), cond ? endLineOf(cond) : startLineOf(stmt), cond ? cond.text : 'for{}', 'normal', cond ? this.harvest.facts(cond) : undefined);
452
+ const loopExit = this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
453
+ this.cfc.pushLoop(header, loopExit, labels);
454
+ const body = this.visitBody(this.bodyBlockOf(stmt));
455
+ this.cfc.pop();
456
+ if (body) {
457
+ this.builder.edge(header, body.entry, 'cond-true');
458
+ this.builder.connect(body.exits, header, 'loop-back');
459
+ }
460
+ else {
461
+ this.builder.edge(header, header, 'loop-back'); // empty `for {}` body re-tests
462
+ }
463
+ // Always emit the structural exit edge — even `for {}` (infinite, no
464
+ // condition) and `for cond {}` keep EXIT reverse-reachable for the CDG pass.
465
+ this.builder.edge(header, loopExit, 'cond-false');
466
+ return { entry: header, exits: [loopExit] };
467
+ }
468
+ visitExprSwitch(stmt) {
469
+ const labels = this.takeLabels();
470
+ const value = stmt.childForFieldName('value');
471
+ const init = stmt.childForFieldName('initializer');
472
+ const dispatch = this.builder.newBlock(startLineOf(stmt), value ? endLineOf(value) : startLineOf(stmt), value ? value.text : 'switch{}', 'normal', value ? this.harvest.facts(value) : undefined);
473
+ if (init)
474
+ this.builder.attachFacts(dispatch, this.harvest.facts(init));
475
+ const switchExit = this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
476
+ this.cfc.pushSwitch(switchExit, labels);
477
+ const cases = stmt.namedChildren.filter((c) => c.type === 'expression_case' || c.type === 'default_case');
478
+ // Each `expression_case`'s test value(s) evaluate before the body — harvest
479
+ // their uses CONDITIONALLY onto the dispatch block (a later case only tests
480
+ // when earlier cases didn't match).
481
+ for (const c of cases) {
482
+ if (c.type !== 'expression_case')
483
+ continue;
484
+ const test = c.childForFieldName('value');
485
+ if (test)
486
+ this.builder.attachFacts(dispatch, this.harvest.factsConditional(test));
487
+ }
488
+ const result = this.buildCases(dispatch, switchExit, cases, (c) => this.exprCaseBody(c));
489
+ this.cfc.pop();
490
+ return result;
491
+ }
492
+ visitTypeSwitch(stmt) {
493
+ const labels = this.takeLabels();
494
+ const dispatch = this.builder.newBlock(startLineOf(stmt), startLineOf(stmt), this.typeSwitchHeaderText(stmt), 'normal', this.harvest.typeSwitchHeadFacts(stmt));
495
+ const switchExit = this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
496
+ this.cfc.pushSwitch(switchExit, labels);
497
+ const cases = stmt.namedChildren.filter((c) => c.type === 'type_case' || c.type === 'default_case');
498
+ const result = this.buildCases(dispatch, switchExit, cases, (c) => this.typeCaseBody(c));
499
+ this.cfc.pop();
500
+ return result;
501
+ }
502
+ visitSelect(stmt) {
503
+ const labels = this.takeLabels();
504
+ const dispatch = this.builder.newBlock(startLineOf(stmt), startLineOf(stmt), 'select');
505
+ const selectExit = this.builder.newBlock(endLineOf(stmt), endLineOf(stmt), '');
506
+ this.cfc.pushSwitch(selectExit, labels);
507
+ const cases = stmt.namedChildren.filter((c) => c.type === 'communication_case' || c.type === 'default_case');
508
+ // A comm case's communication clause (`v := <-ch` / `ch <- x`) evaluates as
509
+ // part of dispatch — harvest its facts onto the dispatch block.
510
+ for (const c of cases) {
511
+ if (c.type !== 'communication_case')
512
+ continue;
513
+ const comm = c.childForFieldName('communication');
514
+ if (comm)
515
+ this.builder.attachFacts(dispatch, this.harvest.facts(comm));
516
+ }
517
+ const hasDefault = cases.some((c) => c.type === 'default_case');
518
+ const result = this.buildCases(dispatch, selectExit, cases, (c) => this.commCaseBody(c));
519
+ // A `select` with NO default BLOCKS until a case is ready — and a `select {}`
520
+ // with no cases at all blocks forever. Either way EXIT must stay
521
+ // reverse-reachable: emit a structural escape edge dispatch → selectExit so
522
+ // the CDG pass is not silently skipped for the function.
523
+ if (!hasDefault)
524
+ this.builder.edge(dispatch, selectExit, 'switch-case');
525
+ this.cfc.pop();
526
+ return result;
527
+ }
528
+ /**
529
+ * Shared dispatch builder for expression-switch / type-switch / select. Cases
530
+ * do NOT fall through by default (the opposite of C); an EXPLICIT
531
+ * `fallthrough` block in a case body spills into the NEXT case instead of the
532
+ * switch exit. `default_case` is the no-match target; without one, the dispatch
533
+ * also reaches the switch exit directly (no-match path).
534
+ */
535
+ buildCases(dispatch, switchExit, cases, bodyOf) {
536
+ const caseResults = cases.map((c) => this.visitSeq(bodyOf(c)));
537
+ const hasDefault = cases.some((c) => c.type === 'default_case');
538
+ const entryOf = new Array(cases.length);
539
+ let after = switchExit;
540
+ for (let i = cases.length - 1; i >= 0; i--) {
541
+ entryOf[i] = caseResults[i]?.entry ?? after;
542
+ after = entryOf[i];
543
+ }
544
+ for (let i = 0; i < cases.length; i++) {
545
+ this.builder.edge(dispatch, entryOf[i], 'switch-case');
546
+ }
547
+ if (!hasDefault)
548
+ this.builder.edge(dispatch, switchExit, 'switch-case'); // no-match path
549
+ // Case bodies rejoin AFTER the switch (no implicit fallthrough), UNLESS the
550
+ // body ends in an explicit `fallthrough`, which spills into the next case.
551
+ for (let i = 0; i < cases.length; i++) {
552
+ const res = caseResults[i];
553
+ if (!res)
554
+ continue;
555
+ const fallTarget = i + 1 < cases.length ? entryOf[i + 1] : switchExit;
556
+ for (const ex of res.exits) {
557
+ if (this.fallthroughBlocks.has(ex)) {
558
+ this.builder.edge(ex, fallTarget, 'fallthrough');
559
+ }
560
+ else {
561
+ this.builder.edge(ex, switchExit, 'seq');
562
+ }
563
+ }
564
+ }
565
+ return { entry: dispatch, exits: [switchExit] };
566
+ }
567
+ /** `expression_case` body statements (everything but the `value` test). */
568
+ exprCaseBody(caseNode) {
569
+ const value = caseNode.childForFieldName('value');
570
+ return caseNode.namedChildren.filter((c) => c.id !== value?.id && c.type !== 'comment');
571
+ }
572
+ /** `type_case` body statements (everything but the `type` field children). */
573
+ typeCaseBody(caseNode) {
574
+ const typeIds = new Set();
575
+ // All `type` field children (a type_case may list several types).
576
+ for (let i = 0; i < caseNode.childCount; i++) {
577
+ if (caseNode.fieldNameForChild(i) === 'type') {
578
+ const c = caseNode.child(i);
579
+ if (c)
580
+ typeIds.add(c.id);
581
+ }
582
+ }
583
+ return caseNode.namedChildren.filter((c) => !typeIds.has(c.id) && c.type !== 'comment');
584
+ }
585
+ /** `communication_case` body statements (everything but the `communication` clause). */
586
+ commCaseBody(caseNode) {
587
+ const comm = caseNode.childForFieldName('communication');
588
+ return caseNode.namedChildren.filter((c) => c.id !== comm?.id && c.type !== 'comment');
589
+ }
590
+ typeSwitchHeaderText(stmt) {
591
+ const alias = stmt.childForFieldName('alias')?.text;
592
+ const value = stmt.childForFieldName('value')?.text ?? '';
593
+ return alias ? `switch ${alias} := ${value}.(type)` : `switch ${value}.(type)`;
594
+ }
595
+ }
596
+ /** Build the CFG for one Go function node, or `undefined` if not modelable. */
597
+ function buildFunctionCfg(fnNode, filePath) {
598
+ try {
599
+ if (!GO_FUNCTION_TYPES.has(fnNode.type))
600
+ return undefined;
601
+ const startLine = startLineOf(fnNode);
602
+ const endLine = endLineOf(fnNode);
603
+ const startColumn = fnNode.startPosition.column;
604
+ const body = fnNode.childForFieldName('body');
605
+ if (!body || body.type !== 'block')
606
+ return undefined; // forward decl / interface method
607
+ const builder = new CfgBuilder(filePath, startLine, endLine, startColumn);
608
+ const harvest = new GoHarvester(fnNode);
609
+ const paramFacts = harvest.paramFacts();
610
+ if (paramFacts)
611
+ builder.attachFacts(builder.entryIndex, paramFacts);
612
+ const walk = new GoCfgWalk(builder, harvest);
613
+ const res = walk.visitSeq(body.namedChildren.filter((c) => c.type !== 'comment'));
614
+ builder.edge(builder.entryIndex, res ? res.entry : builder.exitIndex, 'seq');
615
+ // Normal fall-off threads through the active `defer` chain (LIFO) → EXIT.
616
+ const normalExits = res ? res.exits : [builder.entryIndex];
617
+ const afterDefers = walk.finishDefers(normalExits);
618
+ builder.connect(afterDefers, builder.exitIndex, 'seq');
619
+ walk.flushGotos(builder);
620
+ return builder.finish(harvest.bindingTable());
621
+ }
622
+ catch (err) {
623
+ // Never throw out of buildFunctionCfg — a malformed AST shape must skip only
624
+ // this one function's CFG, never drop the whole file's language group (R4).
625
+ // eslint-disable-next-line no-console
626
+ console.warn(`[cfg] Go buildFunctionCfg skipped a function in ${filePath}: ${String(err)}`);
627
+ return undefined;
628
+ }
629
+ }
630
+ /** Whether a node is a Go function this visitor builds a CFG for. */
631
+ function isFunction(node) {
632
+ return GO_FUNCTION_TYPES.has(node.type);
633
+ }
634
+ /** The Go CFG visitor. */
635
+ export function createGoCfgVisitor() {
636
+ return { buildFunctionCfg, isFunction };
637
+ }
638
+ export { GO_FUNCTION_TYPES };