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,54 @@
1
+ import { type WriteStream } from 'fs';
2
+ /** Injectable for tests (backpressure/error simulation), mirroring split. */
3
+ export type WriteStreamFactory = (filePath: string) => WriteStream;
4
+ /**
5
+ * Derive a node's table label from its graph id. Matches the legacy
6
+ * `getNodeLabel` that lived inline in `loadGraphToLbug`:
7
+ * - `comm_*` → Community
8
+ * - `proc_*` → Process
9
+ * - otherwise the prefix before the first `:` (e.g. `Function:…` → Function)
10
+ */
11
+ export declare const getNodeLabel: (nodeId: string) => string;
12
+ export interface RelPairMeta {
13
+ csvPath: string;
14
+ rows: number;
15
+ }
16
+ /**
17
+ * Routes already-escaped relationship CSV rows to per-FROM→TO-label-pair
18
+ * files. Filters edges whose endpoint labels are not valid node tables
19
+ * (counted as `skipped`), exactly as the legacy split did.
20
+ */
21
+ export declare class RelPairRouter {
22
+ private readonly csvDir;
23
+ private readonly header;
24
+ private readonly validTables;
25
+ private readonly wsFactory;
26
+ /** pairKey (`From|To`) → { csvPath, rows } */
27
+ readonly byPair: Map<string, RelPairMeta>;
28
+ private readonly streams;
29
+ skipped: number;
30
+ total: number;
31
+ private streamError;
32
+ private readonly abort;
33
+ constructor(csvDir: string, header: string, validTables: Set<string>, wsFactory?: WriteStreamFactory);
34
+ private markError;
35
+ /**
36
+ * The first stream error observed, if any. Lets the emit caller rethrow the
37
+ * real error (EMFILE / disk-full) instead of the generic `AbortError` that a
38
+ * pending `once(ws,'drain',{signal})` rejects with when the abort fires —
39
+ * mirroring the retained `splitRelCsvByLabelPair`'s `throw streamError ?? err`.
40
+ */
41
+ get lastError(): Error | null;
42
+ /**
43
+ * Route one already-escaped CSV row (no trailing newline) to its pair file.
44
+ * Returns `void` on the synchronous hot path; a `Promise<void>` only when a
45
+ * stream signals backpressure (or a new pair's header does) — the caller
46
+ * awaits the promise before routing the next edge.
47
+ */
48
+ route(fromId: string, toId: string, row: string): void | Promise<void>;
49
+ private openAndWrite;
50
+ /** Flush + close every pair stream. Rejects if any stream errored. */
51
+ close(): Promise<void>;
52
+ /** Tear down all streams (no flush) — used on the error path. */
53
+ destroy(): void;
54
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Relationship per-label-pair routing (#2203 U2).
3
+ *
4
+ * LadybugDB's bulk `COPY` into the single `CodeRelation` rel table requires a
5
+ * separate CSV per FROM→TO node-label pair (the `from=`/`to=` COPY params).
6
+ * Historically the emit pass wrote one monolithic `relations.csv`, which
7
+ * `loadGraphToLbug` then RE-READ line-by-line (regex per edge) and re-split
8
+ * into per-pair files — writing and reading the entire ~1M-edge set twice.
9
+ *
10
+ * This router lets the single emit pass route each edge to its per-pair file
11
+ * directly, so the monolithic write + re-read + per-edge regex are all gone.
12
+ * The label-derivation + validTables filtering + per-pair-file format here match
13
+ * the legacy `splitRelCsvByLabelPair`, so the per-pair files are byte-identical
14
+ * for all quote-free ids — see the differential test in
15
+ * `test/integration/csv-pipeline.test.ts`. ONE intentional divergence: this
16
+ * router derives the label from the RAW id, while the oracle re-derives it via a
17
+ * regex over the ESCAPED row — so for an id containing a `"` the router is the
18
+ * more-correct path (it routes the edge to the right pair; the oracle's regex
19
+ * mis-buckets or drops it). `splitRelCsvByLabelPair` is retained as the
20
+ * differential oracle (the quote-in-id divergence is asserted explicitly).
21
+ *
22
+ * Backpressure: at most one stream is awaited at a time (the caller routes
23
+ * edges sequentially and awaits the returned drain promise before the next),
24
+ * mirroring the legacy split's `for await` invariant. The hot path (existing
25
+ * pair, no backpressure) returns `void` — no microtask per edge.
26
+ */
27
+ import path from 'path';
28
+ import { createWriteStream } from 'fs';
29
+ import { once } from 'events';
30
+ import { finished } from 'stream/promises';
31
+ /**
32
+ * Derive a node's table label from its graph id. Matches the legacy
33
+ * `getNodeLabel` that lived inline in `loadGraphToLbug`:
34
+ * - `comm_*` → Community
35
+ * - `proc_*` → Process
36
+ * - otherwise the prefix before the first `:` (e.g. `Function:…` → Function)
37
+ */
38
+ export const getNodeLabel = (nodeId) => {
39
+ if (nodeId.startsWith('comm_'))
40
+ return 'Community';
41
+ if (nodeId.startsWith('proc_'))
42
+ return 'Process';
43
+ return nodeId.split(':')[0];
44
+ };
45
+ /**
46
+ * Routes already-escaped relationship CSV rows to per-FROM→TO-label-pair
47
+ * files. Filters edges whose endpoint labels are not valid node tables
48
+ * (counted as `skipped`), exactly as the legacy split did.
49
+ */
50
+ export class RelPairRouter {
51
+ csvDir;
52
+ header;
53
+ validTables;
54
+ wsFactory;
55
+ /** pairKey (`From|To`) → { csvPath, rows } */
56
+ byPair = new Map();
57
+ streams = new Map();
58
+ skipped = 0;
59
+ total = 0;
60
+ streamError = null;
61
+ abort = new AbortController();
62
+ constructor(csvDir, header, validTables, wsFactory = (p) => createWriteStream(p, 'utf-8')) {
63
+ this.csvDir = csvDir;
64
+ this.header = header;
65
+ this.validTables = validTables;
66
+ this.wsFactory = wsFactory;
67
+ }
68
+ markError = (err) => {
69
+ this.streamError ??= err;
70
+ this.abort.abort(err);
71
+ };
72
+ /**
73
+ * The first stream error observed, if any. Lets the emit caller rethrow the
74
+ * real error (EMFILE / disk-full) instead of the generic `AbortError` that a
75
+ * pending `once(ws,'drain',{signal})` rejects with when the abort fires —
76
+ * mirroring the retained `splitRelCsvByLabelPair`'s `throw streamError ?? err`.
77
+ */
78
+ get lastError() {
79
+ return this.streamError;
80
+ }
81
+ /**
82
+ * Route one already-escaped CSV row (no trailing newline) to its pair file.
83
+ * Returns `void` on the synchronous hot path; a `Promise<void>` only when a
84
+ * stream signals backpressure (or a new pair's header does) — the caller
85
+ * awaits the promise before routing the next edge.
86
+ */
87
+ route(fromId, toId, row) {
88
+ if (this.streamError)
89
+ throw this.streamError;
90
+ const fromLabel = getNodeLabel(fromId);
91
+ const toLabel = getNodeLabel(toId);
92
+ if (!this.validTables.has(fromLabel) || !this.validTables.has(toLabel)) {
93
+ this.skipped++;
94
+ return;
95
+ }
96
+ const pairKey = `${fromLabel}|${toLabel}`;
97
+ const ws = this.streams.get(pairKey);
98
+ if (ws === undefined) {
99
+ // First edge for this pair: open the stream, write header + row.
100
+ return this.openAndWrite(pairKey, fromLabel, toLabel, row);
101
+ }
102
+ this.byPair.get(pairKey).rows++;
103
+ this.total++;
104
+ if (!ws.write(row + '\n')) {
105
+ return once(ws, 'drain', { signal: this.abort.signal }).then(() => undefined);
106
+ }
107
+ }
108
+ async openAndWrite(pairKey, fromLabel, toLabel, row) {
109
+ const csvPath = path.join(this.csvDir, `rel_${fromLabel}_${toLabel}.csv`);
110
+ const ws = this.wsFactory(csvPath);
111
+ ws.on('error', this.markError);
112
+ this.streams.set(pairKey, ws);
113
+ this.byPair.set(pairKey, { csvPath, rows: 1 });
114
+ this.total++;
115
+ if (!ws.write(this.header + '\n')) {
116
+ await once(ws, 'drain', { signal: this.abort.signal });
117
+ }
118
+ if (!ws.write(row + '\n')) {
119
+ await once(ws, 'drain', { signal: this.abort.signal });
120
+ }
121
+ }
122
+ /** Flush + close every pair stream. Rejects if any stream errored. */
123
+ async close() {
124
+ if (this.streamError) {
125
+ this.destroy();
126
+ throw this.streamError;
127
+ }
128
+ await Promise.all(Array.from(this.streams.values()).map(async (ws) => {
129
+ ws.end();
130
+ await finished(ws);
131
+ }));
132
+ if (this.streamError)
133
+ throw this.streamError;
134
+ }
135
+ /** Tear down all streams (no flush) — used on the error path. */
136
+ destroy() {
137
+ for (const ws of this.streams.values())
138
+ ws.destroy();
139
+ }
140
+ }
@@ -39,10 +39,10 @@ export declare const ANNOTATION_SCHEMA: string;
39
39
  export declare const CONSTRUCTOR_SCHEMA: string;
40
40
  export declare const TEMPLATE_SCHEMA: string;
41
41
  export declare const MODULE_SCHEMA: string;
42
- export declare const ROUTE_SCHEMA = "\nCREATE NODE TABLE Route (\n id STRING,\n name STRING,\n filePath STRING,\n responseKeys STRING[],\n errorKeys STRING[],\n middleware STRING[],\n PRIMARY KEY (id)\n)";
42
+ export declare const ROUTE_SCHEMA = "\nCREATE NODE TABLE Route (\n id STRING,\n name STRING,\n filePath STRING,\n responseKeys STRING[],\n errorKeys STRING[],\n middleware STRING[],\n method STRING,\n PRIMARY KEY (id)\n)";
43
43
  export declare const TOOL_SCHEMA = "\nCREATE NODE TABLE Tool (\n id STRING,\n name STRING,\n filePath STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
44
44
  export declare const SECTION_SCHEMA = "\nCREATE NODE TABLE Section (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n level INT64,\n content STRING,\n description STRING,\n PRIMARY KEY (id)\n)";
45
- export declare const BASICBLOCK_SCHEMA = "\nCREATE NODE TABLE BasicBlock (\n id STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n text STRING,\n PRIMARY KEY (id)\n)";
45
+ export declare const BASICBLOCK_SCHEMA = "\nCREATE NODE TABLE BasicBlock (\n id STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n text STRING,\n callees STRING,\n calleeIds STRING,\n PRIMARY KEY (id)\n)";
46
46
  export declare const RELATION_SCHEMA = "\nCREATE REL TABLE CodeRelation (\n FROM File TO File,\n FROM File TO Folder,\n FROM File TO Function,\n FROM File TO Class,\n FROM File TO Interface,\n FROM File TO Method,\n FROM File TO CodeElement,\n FROM File TO `Struct`,\n FROM File TO `Enum`,\n FROM File TO `Macro`,\n FROM File TO `Typedef`,\n FROM File TO `Union`,\n FROM File TO `Namespace`,\n FROM File TO `Trait`,\n FROM File TO `Impl`,\n FROM File TO `TypeAlias`,\n FROM File TO `Const`,\n FROM File TO `Static`,\n FROM File TO `Variable`,\n FROM File TO `Property`,\n FROM File TO `Record`,\n FROM File TO `Delegate`,\n FROM File TO `Annotation`,\n FROM File TO `Constructor`,\n FROM File TO `Template`,\n FROM File TO `Module`,\n FROM File TO Section,\n FROM Folder TO Folder,\n FROM Folder TO File,\n FROM Function TO Function,\n FROM Function TO Method,\n FROM Function TO Class,\n FROM Function TO Community,\n FROM Function TO `Macro`,\n FROM Function TO `Struct`,\n FROM Function TO `Template`,\n FROM Function TO `Enum`,\n FROM Function TO `Namespace`,\n FROM Function TO `TypeAlias`,\n FROM Function TO `Module`,\n FROM Function TO `Impl`,\n FROM Function TO Interface,\n FROM Function TO `Constructor`,\n FROM Function TO `Const`,\n FROM Function TO `Typedef`,\n FROM Function TO `Union`,\n FROM Function TO `Property`,\n FROM Function TO CodeElement,\n FROM Class TO Method,\n FROM Class TO Function,\n FROM Class TO Class,\n FROM Class TO Interface,\n FROM Class TO Community,\n FROM Class TO `Template`,\n FROM Class TO `TypeAlias`,\n FROM Class TO `Struct`,\n FROM Class TO `Enum`,\n FROM Class TO `Annotation`,\n FROM Class TO `Constructor`,\n FROM Class TO `Trait`,\n FROM Class TO `Macro`,\n FROM Class TO `Impl`,\n FROM Class TO `Union`,\n FROM Class TO `Namespace`,\n FROM Class TO `Typedef`,\n FROM Class TO `Property`,\n FROM Method TO Function,\n FROM Method TO Method,\n FROM Method TO Class,\n FROM Method TO Community,\n FROM Method TO `Template`,\n FROM Method TO `Struct`,\n FROM Method TO `TypeAlias`,\n FROM Method TO `Enum`,\n FROM Method TO `Macro`,\n FROM Method TO `Namespace`,\n FROM Method TO `Module`,\n FROM Method TO `Impl`,\n FROM Method TO Interface,\n FROM Method TO `Constructor`,\n FROM Method TO `Property`,\n FROM Method TO CodeElement,\n FROM `Template` TO `Template`,\n FROM `Template` TO Function,\n FROM `Template` TO Method,\n FROM `Template` TO Class,\n FROM `Template` TO `Struct`,\n FROM `Template` TO `TypeAlias`,\n FROM `Template` TO `Enum`,\n FROM `Template` TO `Macro`,\n FROM `Template` TO Interface,\n FROM `Template` TO `Constructor`,\n FROM `Module` TO `Module`,\n FROM Section TO Section,\n FROM Section TO File,\n FROM File TO Route,\n FROM Function TO Route,\n FROM Method TO Route,\n FROM File TO Tool,\n FROM Function TO Tool,\n FROM Method TO Tool,\n FROM CodeElement TO Community,\n FROM Interface TO Community,\n FROM Interface TO Function,\n FROM Interface TO Method,\n FROM Interface TO Class,\n FROM Interface TO Interface,\n FROM Interface TO `TypeAlias`,\n FROM Interface TO `Struct`,\n FROM Interface TO `Constructor`,\n FROM Interface TO `Property`,\n FROM `Struct` TO Community,\n FROM `Struct` TO `Trait`,\n FROM `Struct` TO `Struct`,\n FROM `Struct` TO Class,\n FROM `Struct` TO `Enum`,\n FROM `Struct` TO Function,\n FROM `Struct` TO Method,\n FROM `Struct` TO Interface,\n FROM `Struct` TO `Constructor`,\n FROM `Struct` TO `Property`,\n FROM `Enum` TO `Enum`,\n FROM `Enum` TO Community,\n FROM `Enum` TO Class,\n FROM `Enum` TO Interface,\n FROM `Macro` TO Community,\n FROM `Macro` TO Function,\n FROM `Macro` TO Method,\n FROM `Module` TO Function,\n FROM `Module` TO Method,\n FROM `Typedef` TO Community,\n FROM `Union` TO Community,\n FROM `Namespace` TO Community,\n FROM `Namespace` TO `Struct`,\n FROM `Trait` TO Method,\n FROM `Trait` TO `Constructor`,\n FROM `Trait` TO `Property`,\n FROM `Trait` TO Community,\n FROM `Impl` TO Method,\n FROM `Impl` TO `Constructor`,\n FROM `Impl` TO `Property`,\n FROM `Impl` TO Community,\n FROM `Impl` TO `Trait`,\n FROM `Impl` TO `Struct`,\n FROM `Impl` TO `Impl`,\n FROM `TypeAlias` TO Community,\n FROM `TypeAlias` TO `Trait`,\n FROM `TypeAlias` TO Class,\n FROM `Const` TO Community,\n FROM `Static` TO Community,\n FROM `Variable` TO Community,\n FROM `Property` TO Community,\n FROM `Record` TO Method,\n FROM `Record` TO `Constructor`,\n FROM `Record` TO `Property`,\n FROM `Record` TO Community,\n FROM `Delegate` TO Community,\n FROM `Annotation` TO Community,\n FROM `Constructor` TO Community,\n FROM `Constructor` TO Interface,\n FROM `Constructor` TO Class,\n FROM `Constructor` TO Method,\n FROM `Constructor` TO Function,\n FROM `Constructor` TO `Constructor`,\n FROM `Constructor` TO `Struct`,\n FROM `Constructor` TO `Macro`,\n FROM `Constructor` TO `Template`,\n FROM `Constructor` TO `TypeAlias`,\n FROM `Constructor` TO `Enum`,\n FROM `Constructor` TO `Annotation`,\n FROM `Constructor` TO `Impl`,\n FROM `Constructor` TO `Namespace`,\n FROM `Constructor` TO `Module`,\n FROM `Constructor` TO `Property`,\n FROM `Constructor` TO `Typedef`,\n FROM `Template` TO Community,\n FROM `Module` TO Community,\n FROM Function TO Process,\n FROM Method TO Process,\n FROM Class TO Process,\n FROM Interface TO Process,\n FROM `Struct` TO Process,\n FROM `Constructor` TO Process,\n FROM `Module` TO Process,\n FROM `Macro` TO Process,\n FROM `Impl` TO Process,\n FROM `Typedef` TO Process,\n FROM `TypeAlias` TO Process,\n FROM `Enum` TO Process,\n FROM `Union` TO Process,\n FROM `Namespace` TO Process,\n FROM `Trait` TO Process,\n FROM `Const` TO Process,\n FROM `Static` TO Process,\n FROM `Variable` TO Process,\n FROM `Property` TO Process,\n FROM `Record` TO Process,\n FROM `Delegate` TO Process,\n FROM `Annotation` TO Process,\n FROM `Template` TO Process,\n FROM CodeElement TO Process,\n FROM Route TO Process,\n FROM Tool TO Process,\n FROM BasicBlock TO BasicBlock,\n type STRING,\n confidence DOUBLE,\n reason STRING,\n step INT32\n)";
47
47
  export declare const EMBEDDING_DIMS: number;
48
48
  /** HNSW vector index name for the CodeEmbedding table. */
@@ -177,6 +177,7 @@ CREATE NODE TABLE Route (
177
177
  responseKeys STRING[],
178
178
  errorKeys STRING[],
179
179
  middleware STRING[],
180
+ method STRING,
180
181
  PRIMARY KEY (id)
181
182
  )`;
182
183
  // MCP tool definitions
@@ -215,6 +216,8 @@ CREATE NODE TABLE BasicBlock (
215
216
  startLine INT64,
216
217
  endLine INT64,
217
218
  text STRING,
219
+ callees STRING,
220
+ calleeIds STRING,
218
221
  PRIMARY KEY (id)
219
222
  )`;
220
223
  // ============================================================================
@@ -46,11 +46,6 @@ export interface CreateLoggerOptions {
46
46
  * test mode (tests use an in-memory destination).
47
47
  */
48
48
  export declare function flushLoggerSync(): void;
49
- /**
50
- * @internal Test-only reset for the pino-pretty availability cache. Lets
51
- * unit tests exercise both resolve outcomes within the same vitest worker.
52
- */
53
- export declare function _resetPrettyAvailableCache(): void;
54
49
  /**
55
50
  * Build the pino-pretty transport options. Internal — exported only so unit
56
51
  * tests can exercise the probe path without going through `shouldUsePretty()`
@@ -8,6 +8,7 @@
8
8
  * IMPORTANT: This module must NEVER call process.exit(). The caller (CLI
9
9
  * wrapper or server worker) is responsible for process lifecycle.
10
10
  */
11
+ import { type RepoMeta } from '../storage/repo-manager.js';
11
12
  export interface AnalyzeCallbacks {
12
13
  onProgress: (phase: string, percent: number, message: string) => void;
13
14
  onLog?: (message: string) => void;
@@ -48,6 +49,52 @@ export interface AnalyzeOptions {
48
49
  noStats?: boolean;
49
50
  /** Skip installing standard GitNexus skill files to .claude/skills/gitnexus/. */
50
51
  skipSkills?: boolean;
52
+ /**
53
+ * Build the CFG/PDG substrate (#2081 M1). Forwarded to `PipelineOptions.pdg`,
54
+ * which threads to BOTH the worker (CFG build, via workerData) AND
55
+ * scope-resolution (BasicBlock/CFG emit gate). Off by default.
56
+ */
57
+ pdg?: boolean;
58
+ /** Per-function source-line cap for worker-side CFG construction (#2081 M1).
59
+ * Forwarded to `PipelineOptions.pdgMaxFunctionLines`. No CLI flag in M1 —
60
+ * programmatic / server analyze-worker path only; the worker applies
61
+ * `DEFAULT_PDG_MAX_FUNCTION_LINES` when unset. */
62
+ pdgMaxFunctionLines?: number;
63
+ /** Per-function CFG edge cap. Forwarded to `PipelineOptions.pdgMaxEdgesPerFunction`. */
64
+ pdgMaxEdgesPerFunction?: number;
65
+ /** Per-function REACHING_DEF edge cap (#2082 M2). Forwarded to
66
+ * `PipelineOptions.pdgMaxReachingDefEdgesPerFunction`. */
67
+ pdgMaxReachingDefEdgesPerFunction?: number;
68
+ /** Per-function CDG edge cap (#2085 M5). Forwarded to
69
+ * `PipelineOptions.pdgMaxCdgEdgesPerFunction`. No CLI flag or rc key —
70
+ * programmatic / server path only, like the other pdg caps. */
71
+ pdgMaxCdgEdgesPerFunction?: number;
72
+ /** Per-function taint findings cap (#2083 M3). Forwarded to
73
+ * `PipelineOptions.pdgMaxTaintFindingsPerFunction`. No CLI flag or rc key
74
+ * (KTD8) — programmatic / server path only, like the other pdg caps. */
75
+ pdgMaxTaintFindingsPerFunction?: number;
76
+ /** Per-finding taint hop cap (#2083 M3, KTD6). Forwarded to
77
+ * `PipelineOptions.pdgMaxTaintHops`. No CLI flag or rc key (KTD8). */
78
+ pdgMaxTaintHops?: number;
79
+ /** Per-run cross-function findings/hops/edges caps (#2084 review P1-3).
80
+ * Forwarded to the matching `PipelineOptions.pdgMaxInterproc*`; resolved
81
+ * into `RepoMeta.pdg`. No CLI flag or rc key (KTD8). */
82
+ pdgMaxInterprocFindings?: number;
83
+ pdgMaxInterprocHops?: number;
84
+ pdgMaxInterprocEdges?: number;
85
+ /**
86
+ * Stream the BasicBlock + intra-file PDG-edge layer to CSV-on-disk during the
87
+ * emit loop instead of materializing it in the in-memory graph, bounding peak
88
+ * RSS to O(chunk) for full-kernel-scale repos (#2202). Only engages on a full
89
+ * rebuild — `resolveStreamPdgEmit` additionally requires `force === true`
90
+ * (the pre-pipeline guarantee of a full rebuild). May also be enabled via
91
+ * `GITNEXUS_STREAM_PDG_EMIT`. Memory-only; byte-identical output; not stamped
92
+ * into `RepoMeta.pdg`. */
93
+ streamPdgEmit?: boolean;
94
+ /** Streamed PDG-emit write buffer (rows). `undefined` ⇒
95
+ * `DEFAULT_PDG_EMIT_CHUNK_ROWS`. May also be set via
96
+ * `GITNEXUS_PDG_EMIT_CHUNK_SIZE`. Memory-only (#2202). */
97
+ pdgEmitChunkSize?: number;
51
98
  /**
52
99
  * Default branch threaded into generated AGENTS.md / CLAUDE.md so the
53
100
  * regression-compare example uses the configured branch instead of a
@@ -162,4 +209,53 @@ export declare const collectBranchCacheKeys: (storagePath: string, excludeDir?:
162
209
  keys: Set<string>;
163
210
  complete: boolean;
164
211
  }>;
212
+ /**
213
+ * Resolve the requested `--pdg` configuration to the shape recorded in
214
+ * `RepoMeta.pdg`, or `undefined` for a pdg-off run. Caps resolve to their
215
+ * defaults so an explicit-default run compares equal to a default run
216
+ * (`0` = unlimited is preserved as `0`). Pure + exported for testing.
217
+ */
218
+ type PdgOptions = Pick<AnalyzeOptions, 'pdg' | 'pdgMaxFunctionLines' | 'pdgMaxEdgesPerFunction' | 'pdgMaxReachingDefEdgesPerFunction' | 'pdgMaxCdgEdgesPerFunction' | 'pdgMaxTaintFindingsPerFunction' | 'pdgMaxTaintHops' | 'pdgMaxInterprocFindings' | 'pdgMaxInterprocHops' | 'pdgMaxInterprocEdges'>;
219
+ export declare const resolvePdgConfig: (options: PdgOptions) => RepoMeta["pdg"];
220
+ /**
221
+ * Whether streaming/chunked PDG graph emit (#2202) engages this run.
222
+ *
223
+ * Streaming flushes the BasicBlock + intra-file PDG-edge layer to CSV-on-disk
224
+ * during the emit loop and never lands it in the in-memory graph, bounding peak
225
+ * RSS to O(chunk). It is sound ONLY on a full rebuild: the incremental
226
+ * writeback (`extractChangedSubgraph`) reads BasicBlock nodes back out of the
227
+ * in-memory graph, which streaming has already offloaded. `force === true` is
228
+ * the pre-pipeline guarantee of a full rebuild — `isIncremental` has
229
+ * `!force` as a necessary condition — so gating on it avoids the deliberately
230
+ * absent pre-pipeline incremental prediction (see the `isIncremental` note).
231
+ *
232
+ * Requires `pdg === true` (nothing to stream otherwise). Enabled by either the
233
+ * explicit `streamPdgEmit` option or the `GITNEXUS_STREAM_PDG_EMIT` env toggle.
234
+ * Memory-only — NOT part of {@link resolvePdgConfig}, so toggling it never
235
+ * trips `pdgModeMismatch`. Read every call (not memoized) so `vi.stubEnv`
236
+ * works in tests. Pure + exported for testing.
237
+ */
238
+ export declare const resolveStreamPdgEmit: (options: {
239
+ pdg?: boolean;
240
+ force?: boolean;
241
+ streamPdgEmit?: boolean;
242
+ }) => boolean;
243
+ /**
244
+ * Resolve the streamed PDG-emit write-buffer size (#2202). Explicit option wins
245
+ * over `GITNEXUS_PDG_EMIT_CHUNK_SIZE`; `undefined` ⇒ the sink's
246
+ * `DEFAULT_PDG_EMIT_CHUNK_ROWS`. Memory-only; does not affect emitted bytes.
247
+ */
248
+ export declare const resolvePdgEmitChunkSize: (options: {
249
+ pdgEmitChunkSize?: number;
250
+ }) => number | undefined;
251
+ /**
252
+ * Whether the requested `--pdg` configuration differs from the one the
253
+ * existing index's DB rows were built under (#2099 F1). An absent recorded
254
+ * stamp means pdg-off (every legacy meta — `--pdg` shipped opt-in). Any
255
+ * mismatch means the incremental writeback (which only persists changed-file
256
+ * nodes) cannot produce a coherent index: off→on would silently drop the
257
+ * freshly built CFG layer, on→off would strand zombie BasicBlocks — so the
258
+ * caller forces a full writeback. Pure + exported for testing.
259
+ */
260
+ export declare const pdgModeMismatch: (recorded: RepoMeta["pdg"], options: PdgOptions) => boolean;
165
261
  export declare function runFullAnalysis(repoPath: string, options: AnalyzeOptions, callbacks: AnalyzeCallbacks): Promise<AnalyzeResult>;
@@ -13,11 +13,18 @@ import fs from 'fs/promises';
13
13
  import { execFileSync } from 'child_process';
14
14
  import { runPipelineFromRepo } from './ingestion/pipeline.js';
15
15
  import { resetDegradedParseCounter } from './tree-sitter/safe-parse.js';
16
- import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, loadCachedEmbeddings, deleteNodesForFile, deleteAllCommunitiesAndProcesses, queryImporters, loadFTSExtension, } from './lbug/lbug-adapter.js';
16
+ import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, loadCachedEmbeddings, deleteNodesForFile, deleteAllCommunitiesAndProcesses, deleteAllInterprocTaintPaths, deleteAllCallSummaries, queryImporters, loadFTSExtension, } from './lbug/lbug-adapter.js';
17
17
  import { createSearchFTSIndexes, verifySearchFTSIndexes } from './search/fts-indexes.js';
18
18
  import { resolveAnalyzeInstallPolicy } from './lbug/extension-loader.js';
19
19
  import { startWalCheckpointDriver, } from './lbug/wal-checkpoint-driver.js';
20
20
  import { getStoragePaths, resolveBranchPlacement, saveMeta, loadMeta, ensureGitNexusIgnored, registerRepo, cleanupOldKuzuFiles, INCREMENTAL_SCHEMA_VERSION, } from '../storage/repo-manager.js';
21
+ import { DEFAULT_PDG_MAX_FUNCTION_LINES } from './ingestion/cfg/collect.js';
22
+ import { DEFAULT_MAX_CFG_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION, DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION, } from './ingestion/cfg/emit.js';
23
+ import { DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION, DEFAULT_PDG_MAX_TAINT_HOPS, } from './ingestion/taint/propagate.js';
24
+ import { DEFAULT_MAX_INTERPROC_HOPS, DEFAULT_PDG_MAX_INTERPROC_FINDINGS, } from './ingestion/taint/interproc-solver.js';
25
+ import { DEFAULT_PDG_MAX_INTERPROC_EDGES } from './ingestion/taint/interproc-emit.js';
26
+ import { taintModelVersion } from './ingestion/taint/typescript-model.js';
27
+ import { parseTruthyEnv, parsePositiveIntEnv } from './ingestion/utils/env.js';
21
28
  import { computeFileHashes, diffFileHashes } from '../storage/file-hash.js';
22
29
  import { extractChangedSubgraph, computeEffectiveWriteSet, } from './incremental/subgraph-extract.js';
23
30
  import { shadowCandidatesFor } from './incremental/shadow-candidates.js';
@@ -128,6 +135,123 @@ export const collectBranchCacheKeys = async (storagePath, excludeDir) => {
128
135
  }
129
136
  return { keys, complete };
130
137
  };
138
+ export const resolvePdgConfig = (options) => options.pdg === true
139
+ ? {
140
+ maxFunctionLines: options.pdgMaxFunctionLines ?? DEFAULT_PDG_MAX_FUNCTION_LINES,
141
+ maxEdgesPerFunction: options.pdgMaxEdgesPerFunction ?? DEFAULT_MAX_CFG_EDGES_PER_FUNCTION,
142
+ maxReachingDefEdgesPerFunction: options.pdgMaxReachingDefEdgesPerFunction ??
143
+ DEFAULT_PDG_MAX_REACHING_DEF_EDGES_PER_FUNCTION,
144
+ // #2085 M5: control-dependence cap. Absent on any pre-M5 (M2/M3/M4-era)
145
+ // stamp → the key-union pdgModeMismatch trips the first CDG-aware run
146
+ // over an existing `--pdg` index and forces the full writeback that
147
+ // materialises CDG edges for every file without `--force`.
148
+ maxCdgEdgesPerFunction: options.pdgMaxCdgEdgesPerFunction ?? DEFAULT_PDG_MAX_CDG_EDGES_PER_FUNCTION,
149
+ // #2083 M3: taint caps + model identity. The key-union comparator in
150
+ // pdgModeMismatch picks these up structurally — an M2-era stamp lacks
151
+ // all three, so the first M3 run over an M2 `--pdg` index trips a full
152
+ // writeback that populates TAINTED/SANITIZES rows without `--force`.
153
+ maxTaintFindingsPerFunction: options.pdgMaxTaintFindingsPerFunction ?? DEFAULT_PDG_MAX_TAINT_FINDINGS_PER_FUNCTION,
154
+ maxTaintHops: options.pdgMaxTaintHops ?? DEFAULT_PDG_MAX_TAINT_HOPS,
155
+ // #2084 review P1-3: cross-function caps. Absent on an M3-era stamp →
156
+ // pdgModeMismatch trips the first run that adds them (key-union),
157
+ // forcing the full writeback that re-materialises TAINT_PATH bounded.
158
+ maxInterprocFindings: options.pdgMaxInterprocFindings ?? DEFAULT_PDG_MAX_INTERPROC_FINDINGS,
159
+ maxInterprocHops: options.pdgMaxInterprocHops ?? DEFAULT_MAX_INTERPROC_HOPS,
160
+ maxInterprocEdges: options.pdgMaxInterprocEdges ?? DEFAULT_PDG_MAX_INTERPROC_EDGES,
161
+ // Built-in model digest (KTD7/R7): persisted findings must never
162
+ // outlive the model that produced them — ANY model-content change
163
+ // ships as a new digest and repopulates the taint edges.
164
+ taintModelVersion,
165
+ // #2201 review R3: reaching-defs solver identity. The SSA-sparse rewrite
166
+ // computes full facts for deep-loop functions the dense worklist used to
167
+ // truncate to empty, so an existing `--pdg` index carries stale-truncated
168
+ // REACHING_DEF rows. Absent on any pre-#2201 stamp → the key-union
169
+ // pdgModeMismatch trips on the first upgraded run and forces the full
170
+ // writeback that recomputes the fuller coverage (no `--force` needed).
171
+ // Bump this tag on any future change to which facts the solver emits.
172
+ reachingDefSolver: 'ssa-sparse-v1',
173
+ // PDG FU-C: this run records CALL_SUMMARY return-value-ascent edges.
174
+ // Absent on any pre-FU-C (v3) stamp → the key-union pdgModeMismatch trips
175
+ // the first FU-C-aware run over an existing `--pdg` index and forces the
176
+ // full writeback that materialises CALL_SUMMARY edges without `--force`;
177
+ // and `impact`'s PDG mode reads its absence to note "no return-value
178
+ // ascent (re-index for CALL_SUMMARY)" on a v3 index (intra slice intact).
179
+ hasCallSummary: true,
180
+ }
181
+ : undefined;
182
+ /**
183
+ * Whether streaming/chunked PDG graph emit (#2202) engages this run.
184
+ *
185
+ * Streaming flushes the BasicBlock + intra-file PDG-edge layer to CSV-on-disk
186
+ * during the emit loop and never lands it in the in-memory graph, bounding peak
187
+ * RSS to O(chunk). It is sound ONLY on a full rebuild: the incremental
188
+ * writeback (`extractChangedSubgraph`) reads BasicBlock nodes back out of the
189
+ * in-memory graph, which streaming has already offloaded. `force === true` is
190
+ * the pre-pipeline guarantee of a full rebuild — `isIncremental` has
191
+ * `!force` as a necessary condition — so gating on it avoids the deliberately
192
+ * absent pre-pipeline incremental prediction (see the `isIncremental` note).
193
+ *
194
+ * Requires `pdg === true` (nothing to stream otherwise). Enabled by either the
195
+ * explicit `streamPdgEmit` option or the `GITNEXUS_STREAM_PDG_EMIT` env toggle.
196
+ * Memory-only — NOT part of {@link resolvePdgConfig}, so toggling it never
197
+ * trips `pdgModeMismatch`. Read every call (not memoized) so `vi.stubEnv`
198
+ * works in tests. Pure + exported for testing.
199
+ */
200
+ export const resolveStreamPdgEmit = (options) => options.pdg === true &&
201
+ options.force === true &&
202
+ (options.streamPdgEmit === true || parseTruthyEnv(process.env.GITNEXUS_STREAM_PDG_EMIT));
203
+ /**
204
+ * Resolve the streamed PDG-emit write-buffer size (#2202). Explicit option wins
205
+ * over `GITNEXUS_PDG_EMIT_CHUNK_SIZE`; `undefined` ⇒ the sink's
206
+ * `DEFAULT_PDG_EMIT_CHUNK_ROWS`. Memory-only; does not affect emitted bytes.
207
+ */
208
+ export const resolvePdgEmitChunkSize = (options) => {
209
+ // Only honor a positive-integer explicit option; `0`/negative is NOT nullish
210
+ // so `?? env` would pass it through and make the sink flush every row.
211
+ const opt = options.pdgEmitChunkSize;
212
+ if (opt !== undefined && Number.isInteger(opt) && opt > 0)
213
+ return opt;
214
+ return parsePositiveIntEnv(process.env.GITNEXUS_PDG_EMIT_CHUNK_SIZE);
215
+ };
216
+ /**
217
+ * Whether the requested `--pdg` configuration differs from the one the
218
+ * existing index's DB rows were built under (#2099 F1). An absent recorded
219
+ * stamp means pdg-off (every legacy meta — `--pdg` shipped opt-in). Any
220
+ * mismatch means the incremental writeback (which only persists changed-file
221
+ * nodes) cannot produce a coherent index: off→on would silently drop the
222
+ * freshly built CFG layer, on→off would strand zombie BasicBlocks — so the
223
+ * caller forces a full writeback. Pure + exported for testing.
224
+ */
225
+ export const pdgModeMismatch = (recorded, options) => {
226
+ const requested = resolvePdgConfig(options);
227
+ if (!requested && !recorded)
228
+ return false;
229
+ if (!requested || !recorded)
230
+ return true;
231
+ // Structural comparison over the KEY UNION of both resolved records — not a
232
+ // hand-maintained field list. Both sides come fully resolved from
233
+ // resolvePdgConfig, so any new emit-affecting knob added there joins the
234
+ // comparison automatically (M1's hand-extended comparator was the trap this
235
+ // closes: a knob it missed would silently strand a stale projection). It is
236
+ // also what makes the M1→M2 upgrade work with zero extra code: an M1-era
237
+ // stamp lacks maxReachingDefEdgesPerFunction, so `4000 !== undefined` trips
238
+ // a full writeback that populates REACHING_DEF rows without `--force`.
239
+ const reqRecord = requested;
240
+ const recRecord = recorded;
241
+ // INVARIANT: every value stamped by resolvePdgConfig MUST be a SCALAR (string /
242
+ // number / boolean). This comparison is a shallow `!==`, so an OBJECT or ARRAY
243
+ // value would compare by REFERENCE — two structurally-equal values from
244
+ // different runs would always be `!==`, tripping pdgModeMismatch on every
245
+ // re-analyze and forcing a needless full writeback. e.g. do NOT change
246
+ // `hasCallSummary: true` to a per-language object like `{ ts: true, ... }`; keep
247
+ // the diagnostic per-language refinement in the impact CONSUMER (see
248
+ // pdg-impact.ts assemblePdgImpactResult), not in this version discriminator.
249
+ for (const key of new Set([...Object.keys(reqRecord), ...Object.keys(recRecord)])) {
250
+ if (reqRecord[key] !== recRecord[key])
251
+ return true;
252
+ }
253
+ return false;
254
+ };
131
255
  export async function runFullAnalysis(repoPath, options, callbacks) {
132
256
  const log = (msg) => callbacks.onLog?.(msg);
133
257
  const progress = (phase, percent, message) => callbacks.onProgress(phase, percent, message);
@@ -265,13 +389,37 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
265
389
  // clear it, the on-disk index may be in a half-state. Cheapest path
266
390
  // back to a known-good index is to wipe + rebuild from scratch.
267
391
  if (existingMeta?.incrementalInProgress) {
268
- log('Previous incremental run did not complete cleanly (incrementalInProgress flag set); ' +
392
+ log(
393
+ // "analyze run", not "incremental run" — since #2099 F1 the flag is a
394
+ // generic dirty marker written by BOTH writeback branches.
395
+ 'Previous analyze run did not complete cleanly (incrementalInProgress flag set); ' +
269
396
  'forcing full rebuild to restore a known-good index.');
270
397
  options = { ...options, force: true };
271
398
  // Reload meta after clearing the flag in-memory; we still want fileHashes
272
399
  // for the post-rebuild meta carry-over, but force=true ensures the
273
400
  // rebuild path executes.
274
401
  }
402
+ // ── pdg-mode flip forces full writeback (#2099 F1) ─────────────────
403
+ // The incremental writeback persists only changed-file nodes, so a pdg
404
+ // config differing from the one the DB rows were built under cannot be
405
+ // reconciled incrementally: off→on silently drops the freshly built CFG
406
+ // layer ("Incremental: changed=0", zero BasicBlock rows), on→off strands
407
+ // zombie blocks for unchanged files. MUST sit before the alreadyUpToDate
408
+ // fast path below — a clean-tree flip would otherwise early-return without
409
+ // running the pipeline at all. The notice is deliberately NOT gated on
410
+ // options.force: --skills implies force with no message of its own, and a
411
+ // mode change deserves a diagnostic regardless of why a rebuild happens.
412
+ if (existingMeta && pdgModeMismatch(existingMeta.pdg, options)) {
413
+ const pdgOn = options.pdg === true;
414
+ const capsOnly = !!existingMeta.pdg && pdgOn; // both-on can only mismatch via caps
415
+ const was = existingMeta.pdg ? 'with --pdg' : 'without --pdg';
416
+ const now = pdgOn ? 'with --pdg' : 'without --pdg';
417
+ log(`pdg mode changed (index built ${was}, this run is ${now}` +
418
+ `${capsOnly ? ', but with different caps' : ''}); forcing a full ` +
419
+ `rebuild so the CFG layer is ${pdgOn ? 'fully persisted' : 'fully removed'}. ` +
420
+ `Tip: set \`pdg: ${pdgOn}\` in .gitnexusrc to pin the mode across runs.`);
421
+ options = { ...options, force: true };
422
+ }
275
423
  // ── Early-return: already up to date ──────────────────────────────
276
424
  if (existingMeta && !options.force && existingMeta.lastCommit === currentCommit) {
277
425
  // Non-git folders have currentCommit = '' — always rebuild since we can't detect changes
@@ -416,6 +564,23 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
416
564
  }, {
417
565
  parseCache,
418
566
  workerPoolSize: options.workerPoolSize,
567
+ // CFG/PDG opt-in (#2081 M1). PipelineOptions.pdg fans out to the worker
568
+ // build gate (workerData.pdg) and the scope-resolution emit gate.
569
+ pdg: options.pdg === true,
570
+ pdgMaxFunctionLines: options.pdgMaxFunctionLines,
571
+ pdgMaxEdgesPerFunction: options.pdgMaxEdgesPerFunction,
572
+ pdgMaxReachingDefEdgesPerFunction: options.pdgMaxReachingDefEdgesPerFunction,
573
+ pdgMaxCdgEdgesPerFunction: options.pdgMaxCdgEdgesPerFunction,
574
+ pdgMaxTaintFindingsPerFunction: options.pdgMaxTaintFindingsPerFunction,
575
+ pdgMaxTaintHops: options.pdgMaxTaintHops,
576
+ pdgMaxInterprocFindings: options.pdgMaxInterprocFindings,
577
+ pdgMaxInterprocHops: options.pdgMaxInterprocHops,
578
+ pdgMaxInterprocEdges: options.pdgMaxInterprocEdges,
579
+ // Streaming/chunked PDG emit (#2202) — gated to full-rebuild runs
580
+ // (force === true) so the incremental writeback never reads back an
581
+ // offloaded BasicBlock layer. Memory-only; byte-identical output.
582
+ streamPdgEmit: resolveStreamPdgEmit(options),
583
+ pdgEmitChunkSize: resolvePdgEmitChunkSize(options),
419
584
  fetchWrappers: options.fetchWrappers,
420
585
  });
421
586
  // ── Phase 2: LadybugDB (60–85%) ──────────────────────────────────
@@ -465,6 +630,19 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
465
630
  }
466
631
  else {
467
632
  // Full rebuild path: wipe DB files first.
633
+ // Set the dirty flag BEFORE the wipe whenever a prior meta exists,
634
+ // mirroring the incremental branch above (#2099 F1, KTD2b). Without it a
635
+ // full rebuild crashing between the wipe and the end-of-run saveMeta
636
+ // leaves a meta that vouches for a DB it no longer matches — the next
637
+ // clean-tree run's fast path would certify a destroyed DB (or, after a
638
+ // pdg flip, certify zombie/missing BasicBlock rows indefinitely).
639
+ // toWriteCount: 0 is the full-path sentinel (no incremental write set).
640
+ if (existingMeta) {
641
+ await saveMeta(metaDir, {
642
+ ...existingMeta,
643
+ incrementalInProgress: { startedAt: Date.now(), toWriteCount: 0 },
644
+ });
645
+ }
468
646
  await closeLbug();
469
647
  const lbugFiles = [lbugPath, `${lbugPath}.wal`, `${lbugPath}.lock`];
470
648
  for (const f of lbugFiles) {
@@ -606,6 +784,21 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
606
784
  // from the fresh pipeline output below. Required for the
607
785
  // "Leiden runs on the FULL graph" correctness invariant.
608
786
  await deleteAllCommunitiesAndProcesses();
787
+ // 2b. Drop interprocedural TAINT_PATH edges (#2084 M4 U6) when pdg is on
788
+ // — their validity is a whole-program property (an A→C flow can be
789
+ // invalidated by a change to an intermediate function on a third
790
+ // file), so endpoint-writability extraction can't refresh them.
791
+ // extractChangedSubgraph re-includes all of them from the fresh
792
+ // graph (isGraphWideRelType), mirroring Community/Process.
793
+ if (options.pdg === true) {
794
+ await deleteAllInterprocTaintPaths();
795
+ // 2c. Drop CALL_SUMMARY edges (PDG FU-C) on an incremental `--pdg`
796
+ // writeback. They are re-included from the FULL fresh graph
797
+ // (isGraphWideRelType) and the callSummaries phase recomputes every
798
+ // summary each run, so delete-all-then-rebuild keeps an unchanged
799
+ // function's summary from being lost — same contract as TAINT_PATH.
800
+ await deleteAllCallSummaries();
801
+ }
609
802
  // 3. Extract the changed subgraph from the FULL ctx.graph and write
610
803
  // only that. Unchanged-file rows in the DB stay untouched. Pass
611
804
  // the SAME effectiveWriteSet so the subgraph and the deletes
@@ -619,11 +812,15 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
619
812
  }
620
813
  else {
621
814
  // ── Full rebuild ───────────────────────────────────────────────
815
+ // Pass the streamed PDG-emit manifest (#2202) so the BasicBlock layer that
816
+ // was flushed to CSV during the emit loop is COPY'd alongside the
817
+ // structural CSVs. Only ever set on a full rebuild (streaming is
818
+ // force-gated), so the incremental branch above never carries it.
622
819
  await loadGraphToLbug(pipelineResult.graph, pipelineResult.repoPath, storagePath, (msg) => {
623
820
  lbugMsgCount++;
624
821
  const pct = Math.min(84, 60 + Math.round((lbugMsgCount / (lbugMsgCount + 10)) * 24));
625
822
  progress('lbug', pct, msg);
626
- });
823
+ }, pipelineResult.pdgEmitManifest);
627
824
  }
628
825
  // ── Phase 3: FTS (85–90%) ─────────────────────────────────────────
629
826
  // The analyze (write) path owns building the search indexes, so it uses
@@ -846,6 +1043,12 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
846
1043
  // so a sibling branch's prune can union it and not evict our shards.
847
1044
  cacheKeys: [...parseCache.usedKeys],
848
1045
  incrementalInProgress: undefined,
1046
+ // The effective pdg config this run's DB rows were built under
1047
+ // (#2099 F1). `undefined` on pdg-off runs — this meta is a fresh
1048
+ // literal (no spread of existingMeta), so omission is what CLEARS the
1049
+ // stamp after an on→off flip; the next pdgModeMismatch then compares
1050
+ // off==off and incremental eligibility is restored.
1051
+ pdg: resolvePdgConfig(options),
849
1052
  };
850
1053
  await saveMeta(metaDir, meta);
851
1054
  // Persist the incremental parse cache for the next run. Wraps in
@@ -938,6 +1141,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
938
1141
  skipSkills: options.skipSkills,
939
1142
  noStats: options.noStats,
940
1143
  defaultBranch: options.defaultBranch,
1144
+ hasPdg: options.pdg === true,
941
1145
  });
942
1146
  }
943
1147
  catch {