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,124 @@
1
+ /**
2
+ * Synthetic-escape pass for CDG soundness (#2197 U1).
3
+ *
4
+ * THE PROBLEM. Control dependence is computed over the post-dominator tree
5
+ * (control-dependence.ts), which is only sound when EXIT is reverse-reachable
6
+ * from every entry-reachable block (post-dominators.ts §
7
+ * {@link isExitReachableFromAllBlocks}). Loop visitors keep that invariant by
8
+ * giving every loop a structural `header → loopExit` `cond-false` edge — so an
9
+ * ordinary `while`/`for` always has a path to EXIT. The `goto` handlers
10
+ * (C/C++/C#/Go), however, wire an UNCONDITIONAL back-edge as plain `seq` with no
11
+ * such escape:
12
+ *
13
+ * void handler(int a){ start: if (a > 0) { work(); } goto start; }
14
+ *
15
+ * Here every body block sits in a trapping cycle (`start … goto start`) with no
16
+ * path to EXIT, so EXIT is non-reverse-reachable and {@link emitFileCdg} (the
17
+ * soundness gate) WITHHOLDS all control dependence for the whole function —
18
+ * silent CDG coverage loss for an entire (common) class of functions.
19
+ *
20
+ * THE FIX (nontermination-sensitive control dependence — Ranganath et al.,
21
+ * TOPLAS 2007). For a genuinely exit-unreachable *cycle* (an infinite loop), add
22
+ * an ANALYSIS-ONLY virtual escape edge from the cycle's controlling branch to
23
+ * EXIT, making the post-dom tree well-defined again. The synthetic edge is inert
24
+ * in the Ferrante walk (EXIT post-dominates its source, so the post-dom guard
25
+ * skips it) — it only restores reverse-reachability so the REAL control points
26
+ * inside the loop get their dependences.
27
+ *
28
+ * ANALYSIS-ONLY (load-bearing — KTD7). The pass NEVER mutates the input. The
29
+ * persisted CFG / REACHING_DEF graph and the byte-identical-off golden depend on
30
+ * `cfg.edges` staying faithful, so the augmentation lives on a shallow-cloned
31
+ * {@link FunctionCfg} whose `edges` is `[...cfg.edges, ...synthetic]`. Because
32
+ * both {@link computePostDominators} AND {@link computeControlDependence}
33
+ * (its Ferrante walk + `buildArmSenses`) re-read `cfg.edges` directly, the
34
+ * augmented view must be passed to BOTH — feeding only an augmented post-dom
35
+ * tree would leave the walk on the un-augmented edges (KTD7).
36
+ *
37
+ * PURE AND DETERMINISTIC (mirrors post-dominators.ts / reaching-defs.ts). The
38
+ * SCC routine sorts every adjacency list and emits SCCs root-deterministically,
39
+ * so the chosen representative — hence the augmented edge set and any downstream
40
+ * snapshot — is identical across runs.
41
+ *
42
+ * WHICH SCCs ARE BRIDGED (KTD2 / KTD6, and the anti-masking guarantee R2). The
43
+ * decision is gated on the WHOLE entry-reachable trapped region (the union of
44
+ * the entry-reachable blocks that cannot reach EXIT): the pass bridges only when
45
+ * that region contains at least one *control point* — a block with ≥2 successors
46
+ * (a branch terminator). A region with a control point is a real, recoverable
47
+ * loop (a `goto`-cycle always carries the `if` predicate from its guard); a
48
+ * region with NO control point is a branch-less infinite spin that carries no
49
+ * control dependence to recover AND is indistinguishable from a genuine
50
+ * CFG-construction anomaly (e.g. a disconnected EXIT block), so it is
51
+ * deliberately LEFT UNBRIDGED — the existing soundness gate then skips the
52
+ * function and surfaces the skip (R2 / R3). In practice a branch-less trapping
53
+ * region never comes from a real loop visitor (loops emit the structural escape
54
+ * edge) — it signals a construction error, exactly what we must not paper over.
55
+ *
56
+ * When the region is bridged, EACH exit-less SCC gets one synthetic escape edge
57
+ * from its *controlling representative*: the entry-reachable member with a branch
58
+ * terminator (≥2 successors), highest out-degree, lowest-index tie-break. That
59
+ * branch is the predicate deciding stay-in-loop vs. leave, the faithful escape
60
+ * representative; attaching the escape anywhere else invents or drops CDG edges
61
+ * while still passing the AC2 post-dominance property test, so the choice is
62
+ * pinned by an exact-edge-set test, not `CDG>0`. When an exit-less SCC has NO
63
+ * internal branch (e.g. the body of an irreducible loop whose control point sits
64
+ * OUTSIDE the cycle), its escape attaches to the lowest-index member — the
65
+ * choice is semantically immaterial (the SCC has no internal control point so it
66
+ * contributes no internal CDG), and a deterministic index keeps snapshots
67
+ * stable. This per-SCC bridging restores reverse-reachability for the whole
68
+ * region in one batch, then the gate re-checks (KTD2).
69
+ *
70
+ * GRANULARITY OF A MIXED cycle + dead-end FUNCTION. {@link emitFileCdg} is
71
+ * all-or-nothing per function: it computes CDG only when EXIT is reverse-
72
+ * reachable from EVERY entry-reachable block. So if a function contains a
73
+ * recoverable goto-cycle AND a *separate* residual block that is still
74
+ * exit-unreachable after all escapes (a dangling/dead-end block not in any
75
+ * bridgeable cycle), the pass restores the cycle but the residual block keeps
76
+ * EXIT non-reverse-reachable → the WHOLE function is still skipped and surfaced.
77
+ * We do NOT bridge the residual (that would mask the construction error), and we
78
+ * do NOT emit partial per-cycle CDG (the emit layer has no partial mode). This
79
+ * is the documented, intentional trade-off: recover the common goto-cycle case;
80
+ * surface anything with a genuine residual anomaly rather than guess.
81
+ */
82
+ import { isExitReachableFromAllBlocks, type PostDomTree } from './post-dominators.js';
83
+ import type { FunctionCfg } from './types.js';
84
+ /**
85
+ * Strongly-connected components of a CFG via an ITERATIVE Tarjan over the
86
+ * forward edges. Pure and deterministic: nodes are visited in ascending index
87
+ * and every successor list is iterated in sorted order, so the component
88
+ * partition (and the per-component member order) is identical across runs.
89
+ *
90
+ * Returns `compOf[b]` = the component id of block `b`, plus `members[c]` = the
91
+ * (ascending-index) members of component `c`. Component ids are assigned in
92
+ * Tarjan completion order (a reverse-topological order over the condensation),
93
+ * which is deterministic but not relied upon — callers key on `compOf`.
94
+ */
95
+ export interface SccResult {
96
+ readonly compOf: readonly number[];
97
+ readonly members: readonly (readonly number[])[];
98
+ }
99
+ export declare function computeScc(succ: readonly number[][], n: number): SccResult;
100
+ /**
101
+ * Restore EXIT reverse-reachability for genuine exit-unreachable cycles so the
102
+ * post-dom / CDG pass runs on a well-defined tree, WITHOUT masking construction
103
+ * errors or perturbing sound functions. See the module doc for the full
104
+ * contract.
105
+ *
106
+ * Returns the input `cfg` UNCHANGED (referential no-op) when EXIT is already
107
+ * reverse-reachable from every entry-reachable block — terminating functions and
108
+ * properly-escaped loops are byte-identical (zero synthetic edges). Otherwise
109
+ * returns a SHALLOW-CLONED {@link FunctionCfg} whose `edges` is the original
110
+ * edges followed by the synthetic escapes; the input's `edges` is never mutated.
111
+ *
112
+ * Pass the returned view to BOTH {@link computePostDominators} and
113
+ * {@link computeControlDependence} (KTD7).
114
+ */
115
+ export declare function augmentForPostDom(cfg: FunctionCfg): FunctionCfg;
116
+ /**
117
+ * Convenience: `true` iff {@link augmentForPostDom} returned a DIFFERENT object
118
+ * (i.e. at least one synthetic escape edge was added). Useful for tests
119
+ * asserting the no-op path. Reference equality is exact: the no-op path returns
120
+ * the input unchanged.
121
+ */
122
+ export declare function wasAugmented(cfg: FunctionCfg, view: FunctionCfg): boolean;
123
+ export { isExitReachableFromAllBlocks };
124
+ export type { PostDomTree };
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Synthetic-escape pass for CDG soundness (#2197 U1).
3
+ *
4
+ * THE PROBLEM. Control dependence is computed over the post-dominator tree
5
+ * (control-dependence.ts), which is only sound when EXIT is reverse-reachable
6
+ * from every entry-reachable block (post-dominators.ts §
7
+ * {@link isExitReachableFromAllBlocks}). Loop visitors keep that invariant by
8
+ * giving every loop a structural `header → loopExit` `cond-false` edge — so an
9
+ * ordinary `while`/`for` always has a path to EXIT. The `goto` handlers
10
+ * (C/C++/C#/Go), however, wire an UNCONDITIONAL back-edge as plain `seq` with no
11
+ * such escape:
12
+ *
13
+ * void handler(int a){ start: if (a > 0) { work(); } goto start; }
14
+ *
15
+ * Here every body block sits in a trapping cycle (`start … goto start`) with no
16
+ * path to EXIT, so EXIT is non-reverse-reachable and {@link emitFileCdg} (the
17
+ * soundness gate) WITHHOLDS all control dependence for the whole function —
18
+ * silent CDG coverage loss for an entire (common) class of functions.
19
+ *
20
+ * THE FIX (nontermination-sensitive control dependence — Ranganath et al.,
21
+ * TOPLAS 2007). For a genuinely exit-unreachable *cycle* (an infinite loop), add
22
+ * an ANALYSIS-ONLY virtual escape edge from the cycle's controlling branch to
23
+ * EXIT, making the post-dom tree well-defined again. The synthetic edge is inert
24
+ * in the Ferrante walk (EXIT post-dominates its source, so the post-dom guard
25
+ * skips it) — it only restores reverse-reachability so the REAL control points
26
+ * inside the loop get their dependences.
27
+ *
28
+ * ANALYSIS-ONLY (load-bearing — KTD7). The pass NEVER mutates the input. The
29
+ * persisted CFG / REACHING_DEF graph and the byte-identical-off golden depend on
30
+ * `cfg.edges` staying faithful, so the augmentation lives on a shallow-cloned
31
+ * {@link FunctionCfg} whose `edges` is `[...cfg.edges, ...synthetic]`. Because
32
+ * both {@link computePostDominators} AND {@link computeControlDependence}
33
+ * (its Ferrante walk + `buildArmSenses`) re-read `cfg.edges` directly, the
34
+ * augmented view must be passed to BOTH — feeding only an augmented post-dom
35
+ * tree would leave the walk on the un-augmented edges (KTD7).
36
+ *
37
+ * PURE AND DETERMINISTIC (mirrors post-dominators.ts / reaching-defs.ts). The
38
+ * SCC routine sorts every adjacency list and emits SCCs root-deterministically,
39
+ * so the chosen representative — hence the augmented edge set and any downstream
40
+ * snapshot — is identical across runs.
41
+ *
42
+ * WHICH SCCs ARE BRIDGED (KTD2 / KTD6, and the anti-masking guarantee R2). The
43
+ * decision is gated on the WHOLE entry-reachable trapped region (the union of
44
+ * the entry-reachable blocks that cannot reach EXIT): the pass bridges only when
45
+ * that region contains at least one *control point* — a block with ≥2 successors
46
+ * (a branch terminator). A region with a control point is a real, recoverable
47
+ * loop (a `goto`-cycle always carries the `if` predicate from its guard); a
48
+ * region with NO control point is a branch-less infinite spin that carries no
49
+ * control dependence to recover AND is indistinguishable from a genuine
50
+ * CFG-construction anomaly (e.g. a disconnected EXIT block), so it is
51
+ * deliberately LEFT UNBRIDGED — the existing soundness gate then skips the
52
+ * function and surfaces the skip (R2 / R3). In practice a branch-less trapping
53
+ * region never comes from a real loop visitor (loops emit the structural escape
54
+ * edge) — it signals a construction error, exactly what we must not paper over.
55
+ *
56
+ * When the region is bridged, EACH exit-less SCC gets one synthetic escape edge
57
+ * from its *controlling representative*: the entry-reachable member with a branch
58
+ * terminator (≥2 successors), highest out-degree, lowest-index tie-break. That
59
+ * branch is the predicate deciding stay-in-loop vs. leave, the faithful escape
60
+ * representative; attaching the escape anywhere else invents or drops CDG edges
61
+ * while still passing the AC2 post-dominance property test, so the choice is
62
+ * pinned by an exact-edge-set test, not `CDG>0`. When an exit-less SCC has NO
63
+ * internal branch (e.g. the body of an irreducible loop whose control point sits
64
+ * OUTSIDE the cycle), its escape attaches to the lowest-index member — the
65
+ * choice is semantically immaterial (the SCC has no internal control point so it
66
+ * contributes no internal CDG), and a deterministic index keeps snapshots
67
+ * stable. This per-SCC bridging restores reverse-reachability for the whole
68
+ * region in one batch, then the gate re-checks (KTD2).
69
+ *
70
+ * GRANULARITY OF A MIXED cycle + dead-end FUNCTION. {@link emitFileCdg} is
71
+ * all-or-nothing per function: it computes CDG only when EXIT is reverse-
72
+ * reachable from EVERY entry-reachable block. So if a function contains a
73
+ * recoverable goto-cycle AND a *separate* residual block that is still
74
+ * exit-unreachable after all escapes (a dangling/dead-end block not in any
75
+ * bridgeable cycle), the pass restores the cycle but the residual block keeps
76
+ * EXIT non-reverse-reachable → the WHOLE function is still skipped and surfaced.
77
+ * We do NOT bridge the residual (that would mask the construction error), and we
78
+ * do NOT emit partial per-cycle CDG (the emit layer has no partial mode). This
79
+ * is the documented, intentional trade-off: recover the common goto-cycle case;
80
+ * surface anything with a genuine residual anomaly rather than guess.
81
+ */
82
+ import { isExitReachableFromAllBlocks } from './post-dominators.js';
83
+ /**
84
+ * The synthetic escape edge kind. Reuses the existing `cond-false` kind (the
85
+ * same kind every loop's structural `header → loopExit` escape carries — see the
86
+ * module doc), so the augmented view is structurally indistinguishable from a
87
+ * normally-escaped loop and `buildArmSenses`/`labelFor` treat it identically.
88
+ * The edge is analysis-only and never persisted.
89
+ */
90
+ const SYNTHETIC_ESCAPE_KIND = 'cond-false';
91
+ function reach(start, adj, n) {
92
+ const seen = new Uint8Array(n);
93
+ if (start < 0 || start >= n)
94
+ return seen;
95
+ const stack = [start];
96
+ seen[start] = 1;
97
+ while (stack.length > 0) {
98
+ const b = stack.pop();
99
+ for (const next of adj[b]) {
100
+ if (!seen[next]) {
101
+ seen[next] = 1;
102
+ stack.push(next);
103
+ }
104
+ }
105
+ }
106
+ return seen;
107
+ }
108
+ function computeReachability(cfg) {
109
+ const n = cfg.blocks.length;
110
+ const succ = Array.from({ length: n }, () => []);
111
+ const pred = Array.from({ length: n }, () => []);
112
+ for (const e of cfg.edges) {
113
+ if (e.from < 0 || e.from >= n || e.to < 0 || e.to >= n)
114
+ continue;
115
+ succ[e.from].push(e.to);
116
+ pred[e.to].push(e.from);
117
+ }
118
+ // Sorted adjacency — determinism (mirrors post-dominators.ts).
119
+ for (const l of succ)
120
+ l.sort((a, b) => a - b);
121
+ return {
122
+ fromEntry: reach(cfg.entryIndex, succ, n),
123
+ canReachExit: reach(cfg.exitIndex, pred, n),
124
+ succ,
125
+ };
126
+ }
127
+ export function computeScc(succ, n) {
128
+ const compOf = new Array(n).fill(-1);
129
+ const members = [];
130
+ const index = new Array(n).fill(-1);
131
+ const lowlink = new Array(n).fill(0);
132
+ const onStack = new Uint8Array(n);
133
+ const tarjanStack = [];
134
+ let nextIndex = 0;
135
+ // Explicit work stack: each frame tracks the node and how far through its
136
+ // (sorted) successor list we have iterated, so recursion depth never blows the
137
+ // JS stack on a large per-function CFG.
138
+ for (let root = 0; root < n; root++) {
139
+ if (index[root] !== -1)
140
+ continue;
141
+ const work = [{ node: root, childIdx: 0 }];
142
+ while (work.length > 0) {
143
+ const frame = work[work.length - 1];
144
+ const v = frame.node;
145
+ if (frame.childIdx === 0) {
146
+ // First visit to v.
147
+ index[v] = nextIndex;
148
+ lowlink[v] = nextIndex;
149
+ nextIndex += 1;
150
+ tarjanStack.push(v);
151
+ onStack[v] = 1;
152
+ }
153
+ const succs = succ[v];
154
+ if (frame.childIdx < succs.length) {
155
+ const w = succs[frame.childIdx];
156
+ frame.childIdx += 1;
157
+ if (index[w] === -1) {
158
+ // Descend into the unvisited child; resume v afterwards.
159
+ work.push({ node: w, childIdx: 0 });
160
+ }
161
+ else if (onStack[w]) {
162
+ if (index[w] < lowlink[v])
163
+ lowlink[v] = index[w];
164
+ }
165
+ continue;
166
+ }
167
+ // All successors of v processed: propagate lowlink to the parent, and if v
168
+ // is a component root, pop its component off the Tarjan stack.
169
+ if (lowlink[v] === index[v]) {
170
+ const comp = [];
171
+ for (;;) {
172
+ const w = tarjanStack.pop();
173
+ onStack[w] = 0;
174
+ comp.push(w);
175
+ if (w === v)
176
+ break;
177
+ }
178
+ comp.sort((a, b) => a - b); // ascending member order — determinism
179
+ const id = members.length;
180
+ for (const w of comp)
181
+ compOf[w] = id;
182
+ members.push(comp);
183
+ }
184
+ work.pop();
185
+ if (work.length > 0) {
186
+ const parent = work[work.length - 1].node;
187
+ if (lowlink[v] < lowlink[parent])
188
+ lowlink[parent] = lowlink[v];
189
+ }
190
+ }
191
+ }
192
+ return { compOf, members };
193
+ }
194
+ /**
195
+ * Restore EXIT reverse-reachability for genuine exit-unreachable cycles so the
196
+ * post-dom / CDG pass runs on a well-defined tree, WITHOUT masking construction
197
+ * errors or perturbing sound functions. See the module doc for the full
198
+ * contract.
199
+ *
200
+ * Returns the input `cfg` UNCHANGED (referential no-op) when EXIT is already
201
+ * reverse-reachable from every entry-reachable block — terminating functions and
202
+ * properly-escaped loops are byte-identical (zero synthetic edges). Otherwise
203
+ * returns a SHALLOW-CLONED {@link FunctionCfg} whose `edges` is the original
204
+ * edges followed by the synthetic escapes; the input's `edges` is never mutated.
205
+ *
206
+ * Pass the returned view to BOTH {@link computePostDominators} and
207
+ * {@link computeControlDependence} (KTD7).
208
+ */
209
+ export function augmentForPostDom(cfg) {
210
+ const n = cfg.blocks.length;
211
+ const { entryIndex, exitIndex } = cfg;
212
+ if (n === 0 || entryIndex < 0 || entryIndex >= n || exitIndex < 0 || exitIndex >= n) {
213
+ return cfg; // degenerate — leave to the existing gate
214
+ }
215
+ const { fromEntry, canReachExit, succ } = computeReachability(cfg);
216
+ // No-op fast path: every entry-reachable block already reaches EXIT.
217
+ let allReach = true;
218
+ for (let b = 0; b < n; b++) {
219
+ if (fromEntry[b] && !canReachExit[b]) {
220
+ allReach = false;
221
+ break;
222
+ }
223
+ }
224
+ if (allReach)
225
+ return cfg;
226
+ // Anti-masking gate (R2): only bridge when the entry-reachable TRAPPED REGION
227
+ // (the union of entry-reachable blocks that cannot reach EXIT) holds at least
228
+ // one control point — a block with ≥2 successors. A branch-less trapped region
229
+ // is a degenerate spin / construction anomaly we refuse to mask; the existing
230
+ // soundness gate skips it and surfaces the skip. A real `goto`-cycle always
231
+ // carries its guard's `if`, so it is recovered; a disconnected/dangling EXIT
232
+ // (no branch anywhere in the trap) is left to skip. See the module doc.
233
+ let regionHasControlPoint = false;
234
+ for (let b = 0; b < n; b++) {
235
+ if (fromEntry[b] && !canReachExit[b] && succ[b].length >= 2) {
236
+ regionHasControlPoint = true;
237
+ break;
238
+ }
239
+ }
240
+ if (!regionHasControlPoint)
241
+ return cfg;
242
+ // Condense into SCCs over the real edges.
243
+ const { members } = computeScc(succ, n);
244
+ // Bridge EACH exit-less SCC (a trapping cycle: no member can reach EXIT, so
245
+ // `canReachExit` is false for the whole SCC). `canReachExit` already encodes
246
+ // the transitive closure, so a single member's flag answers it for the SCC.
247
+ const synthetic = [];
248
+ for (const comp of members) {
249
+ if (comp.length === 0)
250
+ continue;
251
+ const rep = comp[0]; // ascending-order members → comp[0] is the lowest index
252
+ if (canReachExit[rep])
253
+ continue; // SCC escapes to EXIT — nothing to bridge
254
+ // Only genuine CYCLES trap. A singleton SCC with no self-edge is an ordinary
255
+ // acyclic block (ENTRY / the spine) that is exit-unreachable only because it
256
+ // FEEDS a trap downstream; it gets its path to EXIT for free once the trap is
257
+ // bridged, so it is never bridged on its own.
258
+ const isCycle = comp.length > 1 || cfg.edges.some((e) => e.from === rep && e.to === rep);
259
+ if (!isCycle)
260
+ continue;
261
+ // Controlling representative: the entry-reachable member with a branch
262
+ // terminator (≥2 successors), highest out-degree, lowest-index tie-break.
263
+ // When the SCC has no internal branch (its control point sits outside, e.g.
264
+ // an irreducible loop body), fall back to the lowest-index member — the
265
+ // choice is immaterial (no internal control point ⇒ no internal CDG) and a
266
+ // deterministic index keeps snapshots stable (KTD6).
267
+ let controller = -1;
268
+ let bestOutDeg = 1; // require ≥2 to qualify as a branch
269
+ for (const b of comp) {
270
+ if (!fromEntry[b])
271
+ continue;
272
+ const outDeg = succ[b].length;
273
+ if (outDeg >= 2 && outDeg > bestOutDeg) {
274
+ bestOutDeg = outDeg;
275
+ controller = b;
276
+ }
277
+ }
278
+ if (controller === -1) {
279
+ // No internal branch — attach at the lowest entry-reachable member (or the
280
+ // lowest member if none is entry-reachable, a defensive fallback).
281
+ controller = comp.find((b) => fromEntry[b]) ?? rep;
282
+ }
283
+ synthetic.push({ from: controller, to: exitIndex, kind: SYNTHETIC_ESCAPE_KIND });
284
+ }
285
+ if (synthetic.length === 0)
286
+ return cfg; // nothing bridgeable — gate will skip
287
+ // Shallow clone with the augmented edge set; the input's `edges` is untouched.
288
+ return { ...cfg, edges: [...cfg.edges, ...synthetic] };
289
+ }
290
+ /**
291
+ * Convenience: `true` iff {@link augmentForPostDom} returned a DIFFERENT object
292
+ * (i.e. at least one synthetic escape edge was added). Useful for tests
293
+ * asserting the no-op path. Reference equality is exact: the no-op path returns
294
+ * the input unchanged.
295
+ */
296
+ export function wasAugmented(cfg, view) {
297
+ return view !== cfg;
298
+ }
299
+ // Re-export so callers can build the augmented view and gate it in one import.
300
+ export { isExitReachableFromAllBlocks };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * TraversalResult (issue #2081, M1).
3
+ *
4
+ * Visiting a statement (or a statement sequence) returns the block its control
5
+ * flow ENTERS through, plus the set of blocks whose **normal** control flows
6
+ * out the bottom (the "dangling exits") — to be wired to the entry of whatever
7
+ * comes next. Abnormal exits (return/break/continue/throw) are wired directly
8
+ * to their targets during the walk and are NOT part of `exits`.
9
+ *
10
+ * A statement that cannot fall through (e.g. ends in `return`/`throw`, or both
11
+ * branches of an `if` return) yields an empty `exits` array.
12
+ */
13
+ export interface TraversalResult {
14
+ /** Block index control enters this statement/sequence through. */
15
+ readonly entry: number;
16
+ /** Block indices whose normal control falls out the bottom (may be empty). */
17
+ readonly exits: readonly number[];
18
+ }
19
+ /** A sequence of statements that produced no blocks (e.g. an empty body). */
20
+ export declare const emptyTraversal: (entry: number) => TraversalResult;
@@ -0,0 +1,2 @@
1
+ /** A sequence of statements that produced no blocks (e.g. an empty body). */
2
+ export const emptyTraversal = (entry) => ({ entry, exits: [entry] });