gitnexus 1.6.9 → 1.6.10-aptos.0

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 (539) hide show
  1. package/README.md +211 -53
  2. package/dist/_shared/graph/types.d.ts +67 -3
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +1 -0
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js.map +1 -1
  7. package/dist/_shared/integrations/resilient-fetch.d.ts +3 -1
  8. package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
  9. package/dist/_shared/integrations/resilient-fetch.js +4 -3
  10. package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
  11. package/dist/_shared/language-detection.d.ts.map +1 -1
  12. package/dist/_shared/language-detection.js +2 -0
  13. package/dist/_shared/language-detection.js.map +1 -1
  14. package/dist/_shared/languages.d.ts +2 -0
  15. package/dist/_shared/languages.d.ts.map +1 -1
  16. package/dist/_shared/languages.js +2 -0
  17. package/dist/_shared/languages.js.map +1 -1
  18. package/dist/_shared/lbug/schema-constants.d.ts +2 -2
  19. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  20. package/dist/_shared/lbug/schema-constants.js +8 -0
  21. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  22. package/dist/_shared/pipeline.d.ts +1 -1
  23. package/dist/_shared/pipeline.d.ts.map +1 -1
  24. package/dist/_shared/scope-resolution/callable-flow-site.d.ts +110 -0
  25. package/dist/_shared/scope-resolution/callable-flow-site.d.ts.map +1 -0
  26. package/dist/_shared/scope-resolution/callable-flow-site.js +11 -0
  27. package/dist/_shared/scope-resolution/callable-flow-site.js.map +1 -0
  28. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +1 -1
  29. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
  30. package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -1
  31. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  32. package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
  33. package/dist/_shared/scope-resolution/language-classification.js +1 -0
  34. package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
  35. package/dist/_shared/scope-resolution/parsed-file.d.ts +7 -0
  36. package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
  37. package/dist/_shared/scope-resolution/reference-site.d.ts +9 -1
  38. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  39. package/dist/_shared/scope-resolution/types.d.ts +20 -3
  40. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  41. package/dist/cli/ai-context.d.ts +1 -1
  42. package/dist/cli/ai-context.js +25 -44
  43. package/dist/cli/analyze.d.ts +5 -2
  44. package/dist/cli/analyze.js +197 -11
  45. package/dist/cli/clean.js +17 -3
  46. package/dist/cli/cli-message.d.ts +1 -1
  47. package/dist/cli/doctor.d.ts +18 -0
  48. package/dist/cli/doctor.js +96 -5
  49. package/dist/cli/editor-targets.d.ts +17 -2
  50. package/dist/cli/editor-targets.js +44 -0
  51. package/dist/cli/embeddings.d.ts +12 -0
  52. package/dist/cli/embeddings.js +49 -0
  53. package/dist/cli/eval-server.d.ts +23 -1
  54. package/dist/cli/eval-server.js +126 -8
  55. package/dist/cli/help-i18n.js +6 -0
  56. package/dist/cli/i18n/en.d.ts +18 -8
  57. package/dist/cli/i18n/en.js +18 -8
  58. package/dist/cli/i18n/resources.d.ts +28 -8
  59. package/dist/cli/i18n/zh-CN.d.ts +10 -0
  60. package/dist/cli/i18n/zh-CN.js +18 -8
  61. package/dist/cli/index.js +21 -7
  62. package/dist/cli/lazy-action.d.ts +7 -0
  63. package/dist/cli/lazy-action.js +27 -0
  64. package/dist/cli/mcp.js +6 -3
  65. package/dist/cli/move-availability.d.ts +5 -0
  66. package/dist/cli/move-availability.js +11 -0
  67. package/dist/cli/setup.d.ts +8 -0
  68. package/dist/cli/setup.js +230 -32
  69. package/dist/cli/skill-gen.js +38 -18
  70. package/dist/cli/standard-skills.d.ts +76 -0
  71. package/dist/cli/standard-skills.js +45 -0
  72. package/dist/cli/status.d.ts +4 -1
  73. package/dist/cli/status.js +57 -4
  74. package/dist/cli/tool.js +11 -0
  75. package/dist/cli/uninstall.js +77 -18
  76. package/dist/cli/wiki.d.ts +1 -0
  77. package/dist/cli/wiki.js +7 -1
  78. package/dist/config/ignore-service.d.ts +2 -0
  79. package/dist/config/ignore-service.js +27 -0
  80. package/dist/core/analysis-features.d.ts +21 -0
  81. package/dist/core/analysis-features.js +59 -0
  82. package/dist/core/analyzer-identity.d.ts +74 -0
  83. package/dist/core/analyzer-identity.js +1820 -0
  84. package/dist/core/augmentation/engine.js +13 -8
  85. package/dist/core/embeddings/embedder.d.ts +3 -2
  86. package/dist/core/embeddings/embedder.js +24 -7
  87. package/dist/core/embeddings/embedding-identity.d.ts +11 -0
  88. package/dist/core/embeddings/embedding-identity.js +24 -0
  89. package/dist/core/embeddings/embedding-pipeline.d.ts +36 -1
  90. package/dist/core/embeddings/embedding-pipeline.js +100 -9
  91. package/dist/core/embeddings/http-client.d.ts +33 -3
  92. package/dist/core/embeddings/http-client.js +237 -25
  93. package/dist/core/embeddings/node-module-compat.d.ts +25 -0
  94. package/dist/core/embeddings/node-module-compat.js +25 -0
  95. package/dist/core/embeddings/onnxruntime-common-resolver.js +8 -5
  96. package/dist/core/embeddings/onnxruntime-node-resolver.js +33 -7
  97. package/dist/core/embeddings/runtime-install.d.ts +119 -0
  98. package/dist/core/embeddings/runtime-install.js +372 -0
  99. package/dist/core/embeddings/runtime-support.d.ts +48 -17
  100. package/dist/core/embeddings/runtime-support.js +96 -0
  101. package/dist/core/git-staleness.js +1 -1
  102. package/dist/core/group/bridge-db.js +2 -0
  103. package/dist/core/group/extractors/http-patterns/python.js +246 -108
  104. package/dist/core/group/extractors/manifest-extractor.js +4 -0
  105. package/dist/core/incremental/escalation-gate.d.ts +38 -0
  106. package/dist/core/incremental/escalation-gate.js +48 -0
  107. package/dist/core/incremental/shadow-candidates.d.ts +3 -3
  108. package/dist/core/incremental/shadow-candidates.js +3 -3
  109. package/dist/core/incremental/subgraph-extract.d.ts +2 -2
  110. package/dist/core/incremental/subgraph-extract.js +2 -2
  111. package/dist/core/index-freshness.d.ts +5 -0
  112. package/dist/core/index-freshness.js +13 -0
  113. package/dist/core/ingestion/class-extractors/configs/jvm.js +29 -0
  114. package/dist/core/ingestion/cobol/cobol-preprocessor.js +1 -1
  115. package/dist/core/ingestion/cobol/jcl-processor.js +9 -8
  116. package/dist/core/ingestion/cobol-processor.js +27 -26
  117. package/dist/core/ingestion/community-processor.d.ts +51 -1
  118. package/dist/core/ingestion/community-processor.js +323 -64
  119. package/dist/core/ingestion/emit-references.js +7 -2
  120. package/dist/core/ingestion/filesystem-walker.js +4 -0
  121. package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +3 -0
  122. package/dist/core/ingestion/frameworks/spring/analysis-features.js +7 -0
  123. package/dist/core/ingestion/frameworks/spring/bean-candidates.d.ts +30 -0
  124. package/dist/core/ingestion/frameworks/spring/bean-candidates.js +182 -0
  125. package/dist/core/ingestion/frameworks/spring/bean-catalog.d.ts +12 -0
  126. package/dist/core/ingestion/frameworks/spring/bean-catalog.js +26 -0
  127. package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +24 -0
  128. package/dist/core/ingestion/frameworks/spring/config-bindings.js +115 -0
  129. package/dist/core/ingestion/languages/c/captures.js +56 -0
  130. package/dist/core/ingestion/languages/c/query.js +17 -0
  131. package/dist/core/ingestion/languages/c/scope-resolver.js +6 -0
  132. package/dist/core/ingestion/languages/cobol/captures.js +93 -0
  133. package/dist/core/ingestion/languages/cobol/scope-resolver.js +7 -0
  134. package/dist/core/ingestion/languages/cpp/captures.js +365 -75
  135. package/dist/core/ingestion/languages/cpp/scope-resolver.js +14 -0
  136. package/dist/core/ingestion/languages/csharp/captures.js +25 -0
  137. package/dist/core/ingestion/languages/dart/captures.js +90 -2
  138. package/dist/core/ingestion/languages/dart/extension-type-preprocess.d.ts +7 -0
  139. package/dist/core/ingestion/languages/dart/extension-type-preprocess.js +30 -0
  140. package/dist/core/ingestion/languages/dart.js +2 -0
  141. package/dist/core/ingestion/languages/go/captures.js +34 -0
  142. package/dist/core/ingestion/languages/index.d.ts +1 -0
  143. package/dist/core/ingestion/languages/index.js +2 -0
  144. package/dist/core/ingestion/languages/java/analysis-features.d.ts +3 -0
  145. package/dist/core/ingestion/languages/java/analysis-features.js +13 -0
  146. package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +22 -0
  147. package/dist/core/ingestion/languages/java/capture-side-channel.js +58 -0
  148. package/dist/core/ingestion/languages/java/captures.d.ts +4 -3
  149. package/dist/core/ingestion/languages/java/captures.js +193 -17
  150. package/dist/core/ingestion/languages/java/package-facts.d.ts +5 -0
  151. package/dist/core/ingestion/languages/java/package-facts.js +9 -0
  152. package/dist/core/ingestion/languages/java/package-siblings.d.ts +3 -16
  153. package/dist/core/ingestion/languages/java/package-siblings.js +8 -147
  154. package/dist/core/ingestion/languages/java/query.js +23 -0
  155. package/dist/core/ingestion/languages/java/scope-resolver.js +23 -0
  156. package/dist/core/ingestion/languages/java/spring-bean-metadata.d.ts +2 -0
  157. package/dist/core/ingestion/languages/java/spring-bean-metadata.js +8 -0
  158. package/dist/core/ingestion/languages/java/spring-config-bindings.d.ts +23 -0
  159. package/dist/core/ingestion/languages/java/spring-config-bindings.js +215 -0
  160. package/dist/core/ingestion/languages/java.js +3 -0
  161. package/dist/core/ingestion/languages/javascript/captures.js +16 -0
  162. package/dist/core/ingestion/languages/javascript/query.js +21 -0
  163. package/dist/core/ingestion/languages/jvm/package-facts.d.ts +35 -0
  164. package/dist/core/ingestion/languages/jvm/package-facts.js +40 -0
  165. package/dist/core/ingestion/languages/jvm/package-siblings.d.ts +14 -0
  166. package/dist/core/ingestion/languages/jvm/package-siblings.js +129 -0
  167. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +17 -3
  168. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +42 -8
  169. package/dist/core/ingestion/languages/kotlin/captures.js +59 -0
  170. package/dist/core/ingestion/languages/kotlin/package-facts.d.ts +5 -0
  171. package/dist/core/ingestion/languages/kotlin/package-facts.js +9 -0
  172. package/dist/core/ingestion/languages/kotlin/package-siblings.d.ts +4 -0
  173. package/dist/core/ingestion/languages/kotlin/package-siblings.js +8 -0
  174. package/dist/core/ingestion/languages/kotlin/query.js +19 -0
  175. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +9 -1
  176. package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.d.ts +2 -0
  177. package/dist/core/ingestion/languages/kotlin/spring-bean-metadata.js +8 -0
  178. package/dist/core/ingestion/languages/kotlin.js +5 -6
  179. package/dist/core/ingestion/languages/move.d.ts +1 -0
  180. package/dist/core/ingestion/languages/move.js +27 -0
  181. package/dist/core/ingestion/languages/php/captures.js +40 -0
  182. package/dist/core/ingestion/languages/php/import-decomposer.js +12 -0
  183. package/dist/core/ingestion/languages/php/import-target.d.ts +2 -1
  184. package/dist/core/ingestion/languages/php/import-target.js +110 -2
  185. package/dist/core/ingestion/languages/php/interpret.js +10 -0
  186. package/dist/core/ingestion/languages/php/scope-resolver.js +1 -1
  187. package/dist/core/ingestion/languages/python/captures.d.ts +3 -4
  188. package/dist/core/ingestion/languages/python/captures.js +24 -5
  189. package/dist/core/ingestion/languages/python/interpret.js +4 -0
  190. package/dist/core/ingestion/languages/python/receiver-binding.d.ts +15 -2
  191. package/dist/core/ingestion/languages/python/receiver-binding.js +96 -2
  192. package/dist/core/ingestion/languages/python/simple-hooks.d.ts +5 -5
  193. package/dist/core/ingestion/languages/python/simple-hooks.js +15 -5
  194. package/dist/core/ingestion/languages/ruby/captures.js +42 -0
  195. package/dist/core/ingestion/languages/rust/captures.js +13 -0
  196. package/dist/core/ingestion/languages/rust/interpret.js +18 -0
  197. package/dist/core/ingestion/languages/rust/query.js +9 -0
  198. package/dist/core/ingestion/languages/rust/range-binding.js +6 -2
  199. package/dist/core/ingestion/languages/swift/captures.js +12 -0
  200. package/dist/core/ingestion/languages/typescript/captures.js +21 -0
  201. package/dist/core/ingestion/languages/typescript/nuxt-auto-imports.js +2 -1
  202. package/dist/core/ingestion/languages/typescript/query.js +37 -0
  203. package/dist/core/ingestion/markdown-processor.js +3 -2
  204. package/dist/core/ingestion/model/registration-table.js +1 -0
  205. package/dist/core/ingestion/parsing-processor.d.ts +3 -1
  206. package/dist/core/ingestion/parsing-processor.js +36 -1
  207. package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
  208. package/dist/core/ingestion/pipeline-phases/index.js +2 -0
  209. package/dist/core/ingestion/pipeline-phases/parse-impl.js +56 -2
  210. package/dist/core/ingestion/pipeline-phases/parse.d.ts +0 -2
  211. package/dist/core/ingestion/pipeline-phases/parse.js +12 -3
  212. package/dist/core/ingestion/pipeline-phases/processes.d.ts +8 -0
  213. package/dist/core/ingestion/pipeline-phases/processes.js +11 -1
  214. package/dist/core/ingestion/pipeline-phases/spring-config.d.ts +37 -0
  215. package/dist/core/ingestion/pipeline-phases/spring-config.js +433 -0
  216. package/dist/core/ingestion/pipeline-phases/standalone-ingest.d.ts +10 -0
  217. package/dist/core/ingestion/pipeline-phases/standalone-ingest.js +6 -0
  218. package/dist/core/ingestion/pipeline.d.ts +4 -2
  219. package/dist/core/ingestion/pipeline.js +5 -2
  220. package/dist/core/ingestion/resolve-references.js +12 -0
  221. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +83 -0
  222. package/dist/core/ingestion/route-extractors/constant-resolver.js +131 -0
  223. package/dist/core/ingestion/route-extractors/python-const-resolver.d.ts +75 -0
  224. package/dist/core/ingestion/route-extractors/python-const-resolver.js +299 -0
  225. package/dist/core/ingestion/scope-extractor.js +306 -43
  226. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +71 -2
  227. package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +7 -7
  228. package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +8 -7
  229. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +3 -1
  230. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +6 -0
  231. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +1 -0
  232. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +4 -1
  233. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +7 -2
  234. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +47 -0
  235. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +1138 -0
  236. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +16 -4
  237. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +97 -1
  238. package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +60 -0
  239. package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +111 -0
  240. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +4 -3
  241. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +5 -0
  242. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +25 -38
  243. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +6 -0
  244. package/dist/core/ingestion/scope-resolution/pipeline/run.js +147 -35
  245. package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
  246. package/dist/core/ingestion/scope-resolution/scope/walkers.js +73 -44
  247. package/dist/core/ingestion/taint/typescript-model.js +34 -2
  248. package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
  249. package/dist/core/ingestion/tree-sitter-queries.js +23 -2
  250. package/dist/core/ingestion/type-extractors/jvm.js +17 -2
  251. package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -0
  252. package/dist/core/ingestion/utils/ast-helpers.js +153 -2
  253. package/dist/core/ingestion/utils/callable-flow-captures.d.ts +94 -0
  254. package/dist/core/ingestion/utils/callable-flow-captures.js +878 -0
  255. package/dist/core/ingestion/utils/line-base.d.ts +20 -0
  256. package/dist/core/ingestion/utils/line-base.js +20 -0
  257. package/dist/core/ingestion/utils/symbol-labels.d.ts +21 -0
  258. package/dist/core/ingestion/utils/symbol-labels.js +45 -0
  259. package/dist/core/ingestion/workers/parse-worker.d.ts +34 -0
  260. package/dist/core/ingestion/workers/parse-worker.js +40 -5
  261. package/dist/core/ingestion/workers/result-merge.js +4 -0
  262. package/dist/core/ingestion/workers/worker-pool.d.ts +28 -0
  263. package/dist/core/ingestion/workers/worker-pool.js +128 -28
  264. package/dist/core/lbug/csv-generator.d.ts +15 -0
  265. package/dist/core/lbug/csv-generator.js +124 -27
  266. package/dist/core/lbug/cypher-escape.d.ts +20 -0
  267. package/dist/core/lbug/cypher-escape.js +20 -0
  268. package/dist/core/lbug/extension-load-error.d.ts +67 -0
  269. package/dist/core/lbug/extension-load-error.js +326 -0
  270. package/dist/core/lbug/extension-loader.d.ts +17 -2
  271. package/dist/core/lbug/extension-loader.js +38 -13
  272. package/dist/core/lbug/lbug-adapter.d.ts +203 -2
  273. package/dist/core/lbug/lbug-adapter.js +527 -86
  274. package/dist/core/lbug/lbug-config.d.ts +56 -2
  275. package/dist/core/lbug/lbug-config.js +267 -7
  276. package/dist/core/lbug/move-columns.d.ts +7 -0
  277. package/dist/core/lbug/move-columns.js +86 -0
  278. package/dist/core/lbug/native-check.d.ts +40 -0
  279. package/dist/core/lbug/native-check.js +90 -0
  280. package/dist/core/lbug/node-table-layout.d.ts +29 -0
  281. package/dist/core/lbug/node-table-layout.js +119 -0
  282. package/dist/core/lbug/pool-adapter.d.ts +23 -1
  283. package/dist/core/lbug/pool-adapter.js +115 -8
  284. package/dist/core/lbug/schema.d.ts +4 -3
  285. package/dist/core/lbug/schema.js +16 -16
  286. package/dist/core/lbug/sidecar-recovery.d.ts +172 -0
  287. package/dist/core/lbug/sidecar-recovery.js +418 -16
  288. package/dist/core/lbug/wal-checkpoint-driver.js +3 -0
  289. package/dist/core/move/artifact-download.d.ts +19 -0
  290. package/dist/core/move/artifact-download.js +179 -0
  291. package/dist/core/move/compiler-facts.d.ts +120 -0
  292. package/dist/core/move/compiler-facts.js +9 -0
  293. package/dist/core/move/consistency.d.ts +28 -0
  294. package/dist/core/move/consistency.js +98 -0
  295. package/dist/core/move/constants.d.ts +98 -0
  296. package/dist/core/move/constants.js +136 -0
  297. package/dist/core/move/discovery.d.ts +10 -0
  298. package/dist/core/move/discovery.js +22 -0
  299. package/dist/core/move/entry-points.d.ts +14 -0
  300. package/dist/core/move/entry-points.js +40 -0
  301. package/dist/core/move/facts-mapper.d.ts +75 -0
  302. package/dist/core/move/facts-mapper.js +534 -0
  303. package/dist/core/move/install-lock.d.ts +14 -0
  304. package/dist/core/move/install-lock.js +102 -0
  305. package/dist/core/move/install.d.ts +39 -0
  306. package/dist/core/move/install.js +391 -0
  307. package/dist/core/move/mcp-client.d.ts +115 -0
  308. package/dist/core/move/mcp-client.js +436 -0
  309. package/dist/core/move/move-ingest.d.ts +49 -0
  310. package/dist/core/move/move-ingest.js +320 -0
  311. package/dist/core/move/provision.d.ts +19 -0
  312. package/dist/core/move/provision.js +91 -0
  313. package/dist/core/move/release.d.ts +6 -0
  314. package/dist/core/move/release.js +10 -0
  315. package/dist/core/move/symbol-id.d.ts +35 -0
  316. package/dist/core/move/symbol-id.js +65 -0
  317. package/dist/core/move/type-parser.d.ts +11 -0
  318. package/dist/core/move/type-parser.js +38 -0
  319. package/dist/core/platform/capabilities.d.ts +0 -1
  320. package/dist/core/platform/capabilities.js +39 -8
  321. package/dist/core/run-analyze.d.ts +3 -3
  322. package/dist/core/run-analyze.js +1001 -184
  323. package/dist/core/search/fts-indexes.d.ts +31 -0
  324. package/dist/core/search/fts-indexes.js +73 -0
  325. package/dist/core/search/fts-schema.js +2 -0
  326. package/dist/core/tree-sitter/safe-parse.d.ts +8 -3
  327. package/dist/core/tree-sitter/safe-parse.js +21 -7
  328. package/dist/core/wiki/graph-queries.js +6 -5
  329. package/dist/core/wiki/llm-client.d.ts +8 -2
  330. package/dist/core/wiki/llm-client.js +41 -5
  331. package/dist/mcp/core/embedder.js +16 -2
  332. package/dist/mcp/http-transport.d.ts +5 -0
  333. package/dist/mcp/http-transport.js +19 -5
  334. package/dist/mcp/local/bean-metadata.d.ts +2 -0
  335. package/dist/mcp/local/bean-metadata.js +25 -0
  336. package/dist/mcp/local/line-display.d.ts +22 -0
  337. package/dist/mcp/local/line-display.js +3 -0
  338. package/dist/mcp/local/local-backend.d.ts +19 -1
  339. package/dist/mcp/local/local-backend.js +402 -155
  340. package/dist/mcp/local/pdg-impact.d.ts +5 -3
  341. package/dist/mcp/local/pdg-impact.js +5 -2
  342. package/dist/mcp/output-budget.d.ts +5 -0
  343. package/dist/mcp/output-budget.js +52 -0
  344. package/dist/mcp/read-only-policy.d.ts +12 -0
  345. package/dist/mcp/read-only-policy.js +102 -0
  346. package/dist/mcp/repository-policy.d.ts +34 -0
  347. package/dist/mcp/repository-policy.js +328 -0
  348. package/dist/mcp/resources.js +32 -5
  349. package/dist/mcp/server.d.ts +5 -2
  350. package/dist/mcp/server.js +29 -9
  351. package/dist/mcp/tools.d.ts +0 -8
  352. package/dist/mcp/tools.js +102 -5
  353. package/dist/server/analyze-job.d.ts +3 -0
  354. package/dist/server/analyze-job.js +17 -0
  355. package/dist/server/analyze-launch.d.ts +6 -0
  356. package/dist/server/analyze-launch.js +82 -6
  357. package/dist/server/analyze-worker-core.d.ts +2 -1
  358. package/dist/server/analyze-worker-core.js +5 -2
  359. package/dist/server/analyze-worker.js +29 -6
  360. package/dist/server/api.d.ts +30 -0
  361. package/dist/server/api.js +120 -34
  362. package/dist/server/mcp-http.d.ts +1 -1
  363. package/dist/server/mcp-http.js +4 -2
  364. package/dist/server/upload-ingest.js +2 -1
  365. package/dist/server/validation.js +2 -1
  366. package/dist/storage/git.d.ts +31 -0
  367. package/dist/storage/git.js +111 -1
  368. package/dist/storage/parse-cache.js +7 -1
  369. package/dist/storage/parsedfile-store.d.ts +8 -0
  370. package/dist/storage/parsedfile-store.js +165 -1
  371. package/dist/storage/repo-manager.d.ts +194 -2
  372. package/dist/storage/repo-manager.js +56 -1
  373. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +50 -3
  374. package/hooks/claude/gitnexus-hook.cjs +59 -9
  375. package/hooks/claude/pre-tool-use.sh +0 -0
  376. package/hooks/claude/session-start.sh +0 -0
  377. package/package.json +21 -15
  378. package/scripts/cross-platform-tests.ts +56 -0
  379. package/scripts/ensure-fts.ts +43 -0
  380. package/scripts/install-duckdb-extension.mjs +85 -24
  381. package/scripts/run-cross-platform.ts +61 -6
  382. package/scripts/shard-arg.ts +30 -0
  383. package/scripts/sync-plugin-manifests.mjs +192 -0
  384. package/skills/gitnexus-lfg/README.md +55 -0
  385. package/skills/gitnexus-lfg/SKILL.md +86 -0
  386. package/skills/gitnexus-plan/README.md +142 -0
  387. package/skills/gitnexus-plan/SKILL.md +348 -0
  388. package/skills/gitnexus-plan/references/context-ledger.md +137 -0
  389. package/skills/gitnexus-plan/references/context-pack.md +126 -0
  390. package/skills/gitnexus-plan/references/evidence-provenance.md +272 -0
  391. package/skills/gitnexus-plan/references/pdg-slice.md +109 -0
  392. package/skills/gitnexus-plan/references/plan-template.md +201 -0
  393. package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +2084 -0
  394. package/skills/gitnexus-review/SKILL.md +273 -0
  395. package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +42 -0
  396. package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +39 -0
  397. package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +37 -0
  398. package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +40 -0
  399. package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +42 -0
  400. package/skills/gitnexus-review/ci-personas/ci-security-lens.md +39 -0
  401. package/skills/gitnexus-work/README.md +71 -0
  402. package/skills/gitnexus-work/SKILL.md +269 -0
  403. package/skills/gitnexus-work/references/evidence-provenance.md +272 -0
  404. package/skills/gitnexus-work/scripts/evidence-provenance.mjs +2084 -0
  405. package/web/assets/ProcessFlowModal-B_bfBySy.js +22 -0
  406. package/web/assets/__vite-browser-external-bMKyYQkO.js +1 -0
  407. package/web/assets/agent-Bqxn-abU.js +626 -0
  408. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +1 -0
  409. package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +36 -0
  410. package/web/assets/{blockDiagram-7IZFK4PR-BkWhpzWB.js → blockDiagram-7IZFK4PR-DBefcjof.js} +7 -7
  411. package/web/assets/{c4Diagram-Y2BXMSZH-DtBvpzWD.js → c4Diagram-Y2BXMSZH-EjWnjEJl.js} +6 -6
  412. package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +4 -0
  413. package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +1 -0
  414. package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +321 -0
  415. package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +159 -0
  416. package/web/assets/{chunk-6764PJDD-DpIS7hxD.js → chunk-6764PJDD-C7xxk063.js} +1 -1
  417. package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +124 -0
  418. package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +32 -0
  419. package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +10 -0
  420. package/web/assets/chunk-7W6UQGC5-pyKGssV3.js +1 -0
  421. package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +1 -0
  422. package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +1 -0
  423. package/web/assets/{chunk-INKRHTLW-Nu4ri9P-.js → chunk-INKRHTLW-Ckl3_KkO.js} +13 -13
  424. package/web/assets/chunk-J5EP6P6S-L19oz55R.js +1 -0
  425. package/web/assets/{chunk-KGFNY3KK-JGMJvKCK.js → chunk-KGFNY3KK-BZeP-55u.js} +17 -17
  426. package/web/assets/chunk-KGYTTC2M-zm6n242I.js +1 -0
  427. package/web/assets/{chunk-KRXBNO2N-BW5o0KUN.js → chunk-KRXBNO2N-C-UNuKKf.js} +1 -1
  428. package/web/assets/{chunk-LCXTWHL2-CfLLCywY.js → chunk-LCXTWHL2-C162wE5z.js} +5 -5
  429. package/web/assets/chunk-LII3EMHJ-BL6lKJ_P.js +1 -0
  430. package/web/assets/chunk-LRIF4GLE-n59lhprL.js +1 -0
  431. package/web/assets/chunk-QA3QBVWF-DVXPOIxe.js +2 -0
  432. package/web/assets/chunk-RERM46MO-B5dAdWpP.js +1 -0
  433. package/web/assets/chunk-RG4AUYOV-ZNgyLFq6.js +206 -0
  434. package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +1 -0
  435. package/web/assets/chunk-RLI5ZMPA-CkXZ0y0U.js +1 -0
  436. package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +1 -0
  437. package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +1 -0
  438. package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +1 -0
  439. package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +1 -0
  440. package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +2 -0
  441. package/web/assets/{chunk-W44A43WB-JqMLIpR0.js → chunk-W44A43WB-BN8EQc_u.js} +1 -1
  442. package/web/assets/chunk-ZXARS5L4-C3v-4Fsw.js +1 -0
  443. package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +1 -0
  444. package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +1 -0
  445. package/web/assets/cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js +1 -0
  446. package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +4 -0
  447. package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +43 -0
  448. package/web/assets/diagram-GF46GFSD-B2atbzmU.js +24 -0
  449. package/web/assets/diagram-HNR7UZ2L-DVRltWbL.js +3 -0
  450. package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +24 -0
  451. package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +10 -0
  452. package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +85 -0
  453. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +1 -0
  454. package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +162 -0
  455. package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +292 -0
  456. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +1 -0
  457. package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +106 -0
  458. package/web/assets/index-CX_fADmQ.css +2 -0
  459. package/web/assets/index-D1Z3dGGz.js +575 -0
  460. package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +1 -0
  461. package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +2 -0
  462. package/web/assets/{ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js → ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js} +6 -6
  463. package/web/assets/journeyDiagram-M6C3CM3L-C6wjooas.js +139 -0
  464. package/web/assets/kanban-definition-75IXJCU3-5_UVY79g.js +89 -0
  465. package/web/assets/{katex-K3KEBU37-CTc5BslQ.js → katex-K3KEBU37-qRQBy-EZ.js} +2 -2
  466. package/web/assets/{mindmap-definition-2TDM6QVE-DypvbOMQ.js → mindmap-definition-2TDM6QVE-8xDLzk2e.js} +29 -29
  467. package/web/assets/node-Ct_zna8U.js +8 -0
  468. package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +1 -0
  469. package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +1 -0
  470. package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +30 -0
  471. package/web/assets/preload-helper-Czpn1I53.js +1 -0
  472. package/web/assets/{quadrantDiagram-VICAPDV7-yXSZ2lLz.js → quadrantDiagram-VICAPDV7-DR54jOeR.js} +6 -6
  473. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +1 -0
  474. package/web/assets/requirementDiagram-JXO7QTGE-PEkg7sKC.js +84 -0
  475. package/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  476. package/web/assets/sankeyDiagram-URQDO5SZ-DDWEtjcs.js +40 -0
  477. package/web/assets/sdk-CzHHH8tD.js +37 -0
  478. package/web/assets/sequenceDiagram-VS2MUI6T-Bv-uwANx.js +162 -0
  479. package/web/assets/src-JV30wyV8.js +1 -0
  480. package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +1 -0
  481. package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +1 -0
  482. package/web/assets/timeline-definition-O6YCAMPW-Qmsuo7qS.js +120 -0
  483. package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +1 -0
  484. package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +1 -0
  485. package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +34 -0
  486. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +1 -0
  487. package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +78 -0
  488. package/web/assets/{xychartDiagram-N2JHSOCM-BOLm0eNm.js → xychartDiagram-N2JHSOCM-CoZ_Tits.js} +6 -6
  489. package/web/index.html +18 -10
  490. package/skills/gitnexus-pr-review.md +0 -163
  491. package/web/assets/agent-Dli_x7bU.js +0 -660
  492. package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +0 -1
  493. package/web/assets/architectureDiagram-UL44E2DR-dEkqUZN9.js +0 -36
  494. package/web/assets/chunk-3SSMPTDK-B4_etUhr.js +0 -321
  495. package/web/assets/chunk-67TQ5CYL-4sNPJU1q.js +0 -124
  496. package/web/assets/chunk-7W6UQGC5-KyEG0HQg.js +0 -1
  497. package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +0 -161
  498. package/web/assets/chunk-LII3EMHJ-D-jm-dLa.js +0 -1
  499. package/web/assets/chunk-QA3QBVWF-BgRW3SXd.js +0 -2
  500. package/web/assets/chunk-RG4AUYOV-CqWzWsV3.js +0 -206
  501. package/web/assets/chunk-T2UQINTJ-DSBqkzH7.js +0 -1
  502. package/web/assets/chunk-UY5QBCOK-DyF0vyGd.js +0 -1
  503. package/web/assets/chunk-ZXARS5L4-CxN8oiwI.js +0 -1
  504. package/web/assets/classDiagram-KGZ6W3CR-CMne4tG9.js +0 -1
  505. package/web/assets/classDiagram-v2-72OJOZXJ-CMne4tG9.js +0 -1
  506. package/web/assets/cose-bilkent-UX7MHV2Q-D71wNYRJ.js +0 -1
  507. package/web/assets/dagre-ND4H6XIP-Co5rRx9X.js +0 -4
  508. package/web/assets/diagram-3NCE3AQN-DBp4O00j.js +0 -43
  509. package/web/assets/diagram-GF46GFSD-6N_8yS0i.js +0 -24
  510. package/web/assets/diagram-HNR7UZ2L-DFCfd5LI.js +0 -3
  511. package/web/assets/diagram-QXG6HAR7-Di093rFg.js +0 -24
  512. package/web/assets/diagram-WEQXMOUZ-DZWi4SUN.js +0 -10
  513. package/web/assets/erDiagram-L5TCEMPS-8X1y6R4Y.js +0 -85
  514. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +0 -1
  515. package/web/assets/flowDiagram-H6V6AXG4-CMpY8Ufn.js +0 -162
  516. package/web/assets/ganttDiagram-JCBTUEKG-D3iL2Aet.js +0 -292
  517. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +0 -1
  518. package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +0 -106
  519. package/web/assets/index-KctnI3Vq.js +0 -635
  520. package/web/assets/index-_lgn7hs5.css +0 -2
  521. package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +0 -1
  522. package/web/assets/infoDiagram-3YFTVSEB-BaLMZkUg.js +0 -2
  523. package/web/assets/journeyDiagram-M6C3CM3L-CvArszLo.js +0 -139
  524. package/web/assets/kanban-definition-75IXJCU3-CpfVLLf9.js +0 -89
  525. package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +0 -1
  526. package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +0 -1
  527. package/web/assets/pieDiagram-CU6KROY3-s27EFWgP.js +0 -30
  528. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +0 -1
  529. package/web/assets/requirementDiagram-JXO7QTGE-CWhqInuf.js +0 -84
  530. package/web/assets/sankeyDiagram-URQDO5SZ-1qEjlFIB.js +0 -40
  531. package/web/assets/sequenceDiagram-VS2MUI6T-RyTlZ5cR.js +0 -162
  532. package/web/assets/stateDiagram-7D4R322I-DTjVfX4A.js +0 -1
  533. package/web/assets/stateDiagram-v2-36443NZ5-xY9_k9_Q.js +0 -1
  534. package/web/assets/timeline-definition-O6YCAMPW-DrrqLYAf.js +0 -120
  535. package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +0 -1
  536. package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +0 -1
  537. package/web/assets/vennDiagram-MWXL3ELB-B0RkWAim.js +0 -34
  538. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +0 -1
  539. package/web/assets/wardleyDiagram-CUQ6CDDI-boUxiQ5F.js +0 -78
@@ -51,10 +51,15 @@ import { promises as fs, mkdirSync, writeFileSync } from 'node:fs';
51
51
  import path from 'node:path';
52
52
  import v8 from 'node:v8';
53
53
  import vm from 'node:vm';
54
+ import { logger } from '../core/logger.js';
54
55
  import { mapReplacer, mapReviver } from './parse-cache.js';
55
56
  const STORE_DIRNAME = 'parsedfile-store';
56
57
  const DURABLE_DIRNAME = 'parsedfile-cache';
57
58
  const DURABLE_INDEX_FILENAME = 'index.json';
59
+ const MAX_CALLABLE_FLOW_SITES_PER_FILE = 100_000;
60
+ const MAX_CALLABLE_FLOW_INDIRECTION = 16;
61
+ const MAX_CALLABLE_FLOW_NAME_LENGTH = 4_096;
62
+ const MAX_CALLABLE_FLOW_PARAMETERS = 1_024;
58
63
  /**
59
64
  * Build a JSON.parse reviver that (a) interns every string against a shared
60
65
  * pool and (b) applies the parse-cache `mapReviver` (Map/Set reconstruction).
@@ -217,6 +222,8 @@ export const loadParsedFilesForPaths = async (storagePath, wantPaths) => {
217
222
  // (one `int` / one repeated filePath for the whole language), which is where
218
223
  // most of the saving comes from. Dropped when this function returns.
219
224
  const pool = new Map();
225
+ let droppedSites = 0;
226
+ let filesWithDroppedSites = 0;
220
227
  for (let i = 0; i < shards.length; i++) {
221
228
  // Per-shard def pool: a SymbolDefinition's three serialized copies live within
222
229
  // a single shard (one ParsedFile), so the dedup is shard-local. A cross-shard
@@ -235,9 +242,19 @@ export const loadParsedFilesForPaths = async (storagePath, wantPaths) => {
235
242
  if (!Array.isArray(parsed))
236
243
  continue;
237
244
  for (const pf of parsed) {
238
- if (pf && typeof pf.filePath === 'string' && wantPaths.has(pf.filePath)) {
245
+ if (!pf || typeof pf.filePath !== 'string' || !wantPaths.has(pf.filePath))
246
+ continue;
247
+ const flow = sanitizeCallableFlowSites(pf.callableFlowSites);
248
+ if (flow === undefined)
249
+ continue; // non-array garbage → distrust the file, re-extract
250
+ if (flow.dropped === 0) {
239
251
  out.set(pf.filePath, pf);
240
252
  }
253
+ else {
254
+ droppedSites += flow.dropped;
255
+ filesWithDroppedSites++;
256
+ out.set(pf.filePath, { ...pf, callableFlowSites: flow.sites });
257
+ }
241
258
  }
242
259
  // Every few shards, reclaim the transient pre-intern parse churn before it
243
260
  // piles up against the heap limit (~5 GB avoidable on the kernel), and
@@ -247,11 +264,158 @@ export const loadParsedFilesForPaths = async (storagePath, wantPaths) => {
247
264
  await new Promise((resolve) => setImmediate(resolve));
248
265
  }
249
266
  }
267
+ if (droppedSites > 0) {
268
+ // Facts for the dropped sites are omitted this run (the file itself is
269
+ // retained, so no re-extract happens) — surface it so a recurring drop
270
+ // on every warm load is observable rather than silent (#2522 review).
271
+ logger.warn({ droppedSites, files: filesWithDroppedSites }, 'parsedfile-store: dropped malformed/over-bound callable-flow sites at load; files retained without those facts');
272
+ }
250
273
  return out;
251
274
  };
275
+ /**
276
+ * Treat the durable ParsedFile store as an untrusted serialization boundary.
277
+ * Sanitation is per-SITE, not per-file: one malformed or over-bound fact drops
278
+ * only itself (counted, logged by the caller), so a legitimately pathological
279
+ * source file cannot push its whole ParsedFile into a permanent, silent
280
+ * warm-cache-miss reparse loop (#2522 review). Only a non-array field —
281
+ * i.e. garbage that says the serialization itself is untrustworthy — rejects
282
+ * the file, and `undefined` (never emitted / no facts) passes through.
283
+ * Returns `undefined` for the reject-file case.
284
+ */
285
+ function sanitizeCallableFlowSites(value) {
286
+ if (value === undefined)
287
+ return { sites: undefined, dropped: 0 };
288
+ if (!Array.isArray(value))
289
+ return undefined;
290
+ const bounded = value.length > MAX_CALLABLE_FLOW_SITES_PER_FILE
291
+ ? value.slice(0, MAX_CALLABLE_FLOW_SITES_PER_FILE)
292
+ : value;
293
+ const sites = bounded.filter(isValidCallableFlowSite);
294
+ return { sites, dropped: value.length - sites.length };
295
+ }
296
+ function isValidCallableFlowSite(value) {
297
+ if (!isRecord(value) || typeof value.kind !== 'string')
298
+ return false;
299
+ switch (value.kind) {
300
+ case 'seed':
301
+ return (isValidOperand(value.destination) &&
302
+ isBoundedString(value.targetName) &&
303
+ isOptionalBoundedString(value.targetQualifiedName) &&
304
+ isValidRange(value.targetRange) &&
305
+ isValidExpectedSignature(value.expectedSignature));
306
+ case 'copy':
307
+ case 'alias':
308
+ case 'address':
309
+ return isValidOperand(value.source) && isValidOperand(value.destination);
310
+ case 'store':
311
+ return isValidOperand(value.source) && isValidOperand(value.pointer);
312
+ case 'load':
313
+ return isValidOperand(value.pointer) && isValidOperand(value.destination);
314
+ case 'formal':
315
+ return (isBoundedString(value.ownerName) &&
316
+ isValidRange(value.ownerRange) &&
317
+ isSafeIndex(value.parameterIndex) &&
318
+ isValidOperand(value.binding) &&
319
+ (value.passingMode === 'value' ||
320
+ value.passingMode === 'reference' ||
321
+ value.passingMode === 'pointer') &&
322
+ isValidExpectedSignature(value.expectedSignature));
323
+ case 'argument':
324
+ return (isValidRange(value.callSite) &&
325
+ isSafeIndex(value.parameterIndex) &&
326
+ isValidOperand(value.source) &&
327
+ isOptionalBoundedString(value.directCalleeName));
328
+ case 'invoke':
329
+ return (isValidRange(value.callSite) &&
330
+ isBoundedString(value.inScope) &&
331
+ isValidOperand(value.callee) &&
332
+ (value.receiver === undefined || isValidOperand(value.receiver)) &&
333
+ (value.invocationKind === 'indirect' ||
334
+ value.invocationKind === 'member-pointer' ||
335
+ value.invocationKind === 'callable-object') &&
336
+ (value.arity === undefined || isSafeIndex(value.arity)));
337
+ default:
338
+ return false;
339
+ }
340
+ }
341
+ function isValidOperand(value) {
342
+ if (!isRecord(value))
343
+ return false;
344
+ return (isBoundedString(value.name) &&
345
+ isBoundedString(value.inScope) &&
346
+ isValidRange(value.atRange) &&
347
+ Number.isInteger(value.indirection) &&
348
+ value.indirection >= 0 &&
349
+ value.indirection <= MAX_CALLABLE_FLOW_INDIRECTION &&
350
+ typeof value.addressOf === 'boolean' &&
351
+ (value.expressionKind === undefined ||
352
+ value.expressionKind === 'binding' ||
353
+ value.expressionKind === 'callable-designator' ||
354
+ value.expressionKind === 'bound-member' ||
355
+ value.expressionKind === 'anonymous-callable') &&
356
+ isOptionalBoundedString(value.qualifiedName));
357
+ }
358
+ function isValidExpectedSignature(value) {
359
+ if (value === undefined)
360
+ return true;
361
+ if (!isRecord(value))
362
+ return false;
363
+ return ((value.parameterCount === undefined || isSafeIndex(value.parameterCount)) &&
364
+ isValidBoundedStringArray(value.parameterTypes) &&
365
+ (value.parameterTypeClasses === undefined ||
366
+ (Array.isArray(value.parameterTypeClasses) &&
367
+ value.parameterTypeClasses.length <= MAX_CALLABLE_FLOW_PARAMETERS &&
368
+ value.parameterTypeClasses.every(isRecord))) &&
369
+ (value.isConst === undefined || typeof value.isConst === 'boolean'));
370
+ }
371
+ function isValidBoundedStringArray(value) {
372
+ return (value === undefined ||
373
+ (Array.isArray(value) &&
374
+ value.length <= MAX_CALLABLE_FLOW_PARAMETERS &&
375
+ // '' is a legitimate entry meaning "unknown type" — the same convention
376
+ // as ReferenceSite.argumentTypes. C++ emits it for cv-qualifier-only or
377
+ // ERROR-recovered parameter types, so requiring non-empty here rejected
378
+ // real extractor output (#2522 review).
379
+ value.every((entry) => typeof entry === 'string' && entry.length <= MAX_CALLABLE_FLOW_NAME_LENGTH)));
380
+ }
381
+ function isValidRange(value) {
382
+ if (!isRecord(value))
383
+ return false;
384
+ return (isNonNegativeInteger(value.startLine) &&
385
+ isNonNegativeInteger(value.startCol) &&
386
+ isNonNegativeInteger(value.endLine) &&
387
+ isNonNegativeInteger(value.endCol));
388
+ }
389
+ function isRecord(value) {
390
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
391
+ }
392
+ function isBoundedString(value) {
393
+ return (typeof value === 'string' && value.length > 0 && value.length <= MAX_CALLABLE_FLOW_NAME_LENGTH);
394
+ }
395
+ function isOptionalBoundedString(value) {
396
+ return value === undefined || isBoundedString(value);
397
+ }
398
+ function isNonNegativeInteger(value) {
399
+ return Number.isSafeInteger(value) && value >= 0;
400
+ }
401
+ function isSafeIndex(value) {
402
+ return isNonNegativeInteger(value) && value <= MAX_CALLABLE_FLOW_PARAMETERS;
403
+ }
252
404
  /** Durable store dir — a sibling of `parsedfile-store/`, NEVER cleared per run. */
253
405
  export const getDurableParsedFileDir = (storagePath) => path.join(storagePath, DURABLE_DIRNAME);
254
406
  const durableChunkDir = (durableDir, chunkHash) => path.join(durableDir, chunkHash);
407
+ /**
408
+ * Start a fresh durable generation for one content-addressed parse chunk.
409
+ * The main thread calls this once before dispatching a cache miss, before any
410
+ * worker can write that chunk. Recreating the directory immediately keeps the
411
+ * worker-side mkdir memoization valid while preventing old worker shard names
412
+ * from accumulating across analyses.
413
+ */
414
+ export const prepareDurableParsedFileChunk = async (durableDir, chunkHash) => {
415
+ const dir = durableChunkDir(durableDir, chunkHash);
416
+ await fs.rm(dir, { recursive: true, force: true });
417
+ await fs.mkdir(dir, { recursive: true });
418
+ };
255
419
  // Per-process set of durable chunk subdirs already `mkdir`ed (mirrors
256
420
  // `createdStoreDirs`) so the worker doesn't `mkdirSync` on every shard.
257
421
  const createdDurableDirs = new Set();
@@ -13,6 +13,7 @@
13
13
  * construction (getStoragePath is per-checkout), regardless of which filename
14
14
  * the metadata inside it uses.
15
15
  */
16
+ import type { MoveCompilerIdentity, MoveFlowReleaseSelection } from '../core/move/constants.js';
16
17
  import { branchSlug, resolveBranchPlacement, type BranchSummary } from './branch-index.js';
17
18
  export { branchSlug, resolveBranchPlacement };
18
19
  export type { BranchSummary };
@@ -54,10 +55,72 @@ export declare const canonicalizePath: (p: string) => string;
54
55
  * lookups/dedup/finalize checks all share so they answer identically.
55
56
  */
56
57
  export declare const registryPathEquals: (a: string, b: string) => boolean;
58
+ /**
59
+ * Does the clone dir derived from an entry's *name* actually belong to that
60
+ * entry? Registry names are not unique across storage locations: a cloned
61
+ * repo under `~/.gitnexus/repos/<name>` and a local repo registered under the
62
+ * same name share a `getCloneDir(entry.name)` result. The server's delete
63
+ * handler must therefore never remove the clone dir based on the name alone —
64
+ * only when the entry's own `path` resolves to that dir (mirroring its step-2b
65
+ * rule that cleanup is driven off `entry.path`, so a same-named sibling's
66
+ * clone is never removed). Both sides are canonicalised so symlinked or
67
+ * differently-spelled forms of the same dir still match.
68
+ */
69
+ export declare const cloneDirBelongsToEntry: (cloneDir: string, entryPath: string) => boolean;
70
+ /**
71
+ * Versioned receipt for the analyzer process that produced an index.
72
+ *
73
+ * Paths identify the resolved runtime and invoked GitNexus entry artifact on
74
+ * this machine. The entry artifact is diagnostic (CLI and server-worker entry
75
+ * files differ); semantic freshness compares the runtime/build/dependency
76
+ * fields. SHA-256 digests make the receipt independently reproducible:
77
+ * `invokedArtifact.digest` covers the entry file, `build.digest` covers the
78
+ * complete source or distribution tree, and `dependencyRuntime.digest` covers
79
+ * the applicable lockfile, resolved runtime package metadata, and every
80
+ * content-addressed package payload (including JS/JSON/native/Wasm inputs)
81
+ * using the canonicalizations defined in `core/analyzer-identity.ts`.
82
+ */
83
+ export interface AnalyzerRunnerIdentity {
84
+ schemaVersion: 4;
85
+ runtime: {
86
+ executablePath: string;
87
+ version: string;
88
+ platform: string;
89
+ architecture: string;
90
+ modulesAbi: string;
91
+ libc: string;
92
+ };
93
+ cliVersion: string;
94
+ invokedArtifact: {
95
+ path: string;
96
+ digest: string;
97
+ };
98
+ build: {
99
+ kind: 'source' | 'distribution';
100
+ rootPath: string;
101
+ canonicalization: 'gitnexus-analyzer-build-v2';
102
+ digest: string;
103
+ };
104
+ dependencyRuntime: {
105
+ manifestPath: string;
106
+ lockfilePath: string | null;
107
+ canonicalization: 'gitnexus-analyzer-dependency-runtime-v4';
108
+ packageCount: number;
109
+ artifactCount: number;
110
+ digest: string;
111
+ };
112
+ }
57
113
  export interface RepoMeta {
58
114
  repoPath: string;
59
115
  lastCommit: string;
60
116
  indexedAt: string;
117
+ /**
118
+ * Analyzer/runtime receipt for the successful run represented by this
119
+ * metadata. Optional so indexes written by older GitNexus releases remain
120
+ * readable; a missing value means provenance is unknown, never that it
121
+ * matches the currently invoked analyzer.
122
+ */
123
+ runnerIdentity?: AnalyzerRunnerIdentity;
61
124
  /**
62
125
  * Canonical `origin` remote URL captured at index time. Used to
63
126
  * fingerprint the same logical repo across multiple on-disk clones
@@ -74,6 +137,33 @@ export interface RepoMeta {
74
137
  processes?: number;
75
138
  embeddings?: number;
76
139
  };
140
+ /**
141
+ * Capability stamps for what THIS analyze run actually produced (mirrors
142
+ * the meta literal in run-analyze.ts — typed here so the stamp site is
143
+ * compile-checked; tri-review 4669518496 P1/U3: `vectorSearch.status`
144
+ * must never claim 'vector-index' unless the run verified or recreated
145
+ * the HNSW index). Forensic today — no programmatic readers (`doctor`
146
+ * prints platform-derived capabilities, query routing never consults
147
+ * meta). The status unions mirror `CapabilityStatus` /
148
+ * `SemanticSearchMode` in core/platform/capabilities.ts; inlined to keep
149
+ * storage/ free of a core/ type dependency.
150
+ */
151
+ capabilities?: {
152
+ graph: {
153
+ provider: string;
154
+ status: 'available' | 'degraded' | 'unavailable';
155
+ };
156
+ fts: {
157
+ provider: string;
158
+ status: 'available' | 'degraded' | 'unavailable';
159
+ };
160
+ vectorSearch: {
161
+ provider: string;
162
+ status: 'vector-index' | 'exact-scan' | 'unavailable';
163
+ exactScanLimit: number;
164
+ reason?: string;
165
+ };
166
+ };
77
167
  /**
78
168
  * Bumped whenever incremental-indexing invariants change in an
79
169
  * incompatible way (delete-and-rewrite logic, subgraph extraction,
@@ -81,6 +171,12 @@ export interface RepoMeta {
81
171
  * full rebuild rather than risk an inconsistent incremental update.
82
172
  */
83
173
  schemaVersion?: number;
174
+ /**
175
+ * Exact versions of independently-gated analysis capabilities produced by
176
+ * the successful run. Unlike schemaVersion, these may apply only to repos
177
+ * containing relevant source files.
178
+ */
179
+ analysisFeatures?: Record<string, number>;
84
180
  /**
85
181
  * The resolved GITNEXUS_FTS_CJK_SEGMENTATION mode ('none' | 'bigram') the
86
182
  * existing index's content/description columns were last written under
@@ -98,6 +194,15 @@ export interface RepoMeta {
98
194
  * Map keys are repo-relative paths.
99
195
  */
100
196
  fileHashes?: Record<string, string>;
197
+ /**
198
+ * Whether the persisted Move facts are compiler-backed. Absent on legacy
199
+ * metadata and non-Move repositories.
200
+ */
201
+ moveIngestAvailable?: boolean;
202
+ /** Compiler identity that produced the persisted Move facts. */
203
+ moveCompilerIdentity?: MoveCompilerIdentity;
204
+ /** Managed release coordinates, kept separate from the binary fingerprint. */
205
+ moveFlowReleaseSelection?: MoveFlowReleaseSelection;
101
206
  /**
102
207
  * Crash-recovery dirty flag — a generic marker written to the metadata
103
208
  * file (gitnexus.json + its meta.json mirror) BEFORE any destructive DB
@@ -110,9 +215,53 @@ export interface RepoMeta {
110
215
  incrementalInProgress?: {
111
216
  /** When the run started (epoch ms). */
112
217
  startedAt: number;
218
+ /** Last dirty-flag refresh (epoch ms). */
219
+ updatedAt?: number;
113
220
  /** Number of files in the writable set, for diagnostic logs.
114
221
  * `0` on the full-rebuild path (no incremental write set exists). */
115
222
  toWriteCount: number;
223
+ /** Last completed writeback phase before the process stopped. */
224
+ phase?: string;
225
+ /** Directly changed/added files before importer expansion. */
226
+ directWriteCount?: number;
227
+ /** Extra files pulled into the writable set by importer BFS. */
228
+ importerExpansion?: number;
229
+ /** Files in the effective write set after graph-boundary expansion. */
230
+ effectiveWriteCount?: number;
231
+ /** Files whose persisted rows were scheduled for deletion. */
232
+ deleteCount?: number;
233
+ /** Added-file shadow seeds included in importer BFS. */
234
+ shadowSeedCount?: number;
235
+ /** Importer-BFS chunks dropped by failed IMPORTS queries (#2410 +
236
+ * tri-review 4669518496 P2-5). Stamped only when > 0: a dropped chunk
237
+ * means the importer expansion silently shrank, so a crash's
238
+ * diagnostics must show whether the write set was already
239
+ * under-expanded when the run died. */
240
+ droppedImporterChunks?: number;
241
+ };
242
+ /**
243
+ * Durable embedding-resume marker. Before a bounded write window begins,
244
+ * `pendingNodeIds` records every node that could become partially persisted;
245
+ * after the LadybugDB checkpoint it is cleared while progress is retained.
246
+ * A matching runtime resumes from persisted hashes and regenerates pending
247
+ * nodes; a model or dimension mismatch fails before mutation.
248
+ */
249
+ embeddingCheckpoint?: {
250
+ at: string;
251
+ nodesProcessed: number;
252
+ totalNodes: number;
253
+ chunksProcessed: number;
254
+ model: string;
255
+ dimensions: number;
256
+ /** `local` or a secret-free SHA-256 fingerprint of the HTTP endpoint identity. */
257
+ provider: string;
258
+ /**
259
+ * Nodes in the current checkpoint window. Any of these may have only a
260
+ * subset of their chunks persisted after an abrupt process termination,
261
+ * so resume must delete and regenerate them even when a persisted row has
262
+ * the current content hash.
263
+ */
264
+ pendingNodeIds?: string[];
116
265
  };
117
266
  /**
118
267
  * Name of the git branch this index represents (#2106). Absent for the
@@ -242,8 +391,51 @@ export interface RepoMeta {
242
391
  * URL-only id). The incremental writeback preserves unchanged-file rows, so a
243
392
  * top-up against a pre-v5 index would strand old url-keyed Route nodes alongside
244
393
  * new composite-keyed ones — force a full re-analyze instead.
245
- */
246
- export declare const INCREMENTAL_SCHEMA_VERSION = 5;
394
+ * v6: line-number storage flipped to uniform 0-based for the last 1-based
395
+ * GraphNode emitters — COBOL/JCL/markdown/scope (#2377/#2379/#2380). Incremental
396
+ * writeback preserves unchanged-file rows, so a top-up against a pre-v6 index
397
+ * would MIX old 1-based rows with new 0-based ones — and the 1-based MCP display
398
+ * would render the stale rows one line too high — so force a full re-analyze.
399
+ * v7: callable-value-flow CALLS/USES edges added (#2437/#2522) — new edges can
400
+ * connect two files whose content did not change, but the incremental write set
401
+ * only covers changed files (`computeEffectiveWriteSet`), so a top-up against a
402
+ * pre-v7 index would silently omit the new edges for every unchanged file pair;
403
+ * force a full re-analyze instead (same contract as v2–v6).
404
+ * v8: Java anonymous class bodies became first-class Class nodes (#2550):
405
+ * `new Runnable() { run(){} }` now emits `Class:...:Worker$1` and its methods
406
+ * re-keyed from `Worker.run` to `Worker$1.run`. Node identities move on
407
+ * unchanged files — a top-up against a pre-v8 index would strand the old
408
+ * `Worker.run`-keyed Method nodes alongside the new ones (the v5 Route
409
+ * precedent); force a full re-analyze instead.
410
+ * v9: Java enum constant bodies joined the instance model and anonymous
411
+ * naming switched to JLS 13.1 immediately-enclosing-type chains (#2555): `enum E { A {
412
+ * hook(){} } }` now emits `Class:...:E$1` with methods re-keyed from
413
+ * `E.hook` to `E$1.hook`, and nested-host anonymous names re-key
414
+ * (`EnumWrap$1` → `EnumWrap$Mode$1`). Same contract as v8: identities move
415
+ * on unchanged files; force a full re-analyze.
416
+ * v10: Java `record_declaration` now emits a first-class `Record` graph node
417
+ * (#2564): a record's container node was previously never created (JAVA_QUERIES
418
+ * had no capture for it), so its methods existed as ownerless Method nodes
419
+ * with no `HAS_METHOD` edge. The incremental write set only covers changed
420
+ * files — a top-up against a pre-v10 index would keep silently omitting the
421
+ * `Record` node and its `HAS_METHOD` edges for every unchanged record file
422
+ * (same v7 contract: new nodes/edges the incremental path would otherwise
423
+ * never backfill); force a full re-analyze instead.
424
+ * v11: Rust abstract trait methods (`fn foo(&self) -> T;`, no body) now get a
425
+ * scope + declaration capture (#2604): RUST_SCOPE_QUERY had no
426
+ * `function_signature_item` pattern, so a `&dyn Trait` receiver could never
427
+ * dispatch a CALLS edge to the trait's own method. Same v7/v10 contract: the
428
+ * incremental write set only covers changed files, so a top-up against a
429
+ * pre-v11 index would keep silently missing these CALLS edges for every
430
+ * unchanged Rust trait file; force a full re-analyze instead.
431
+ * v12: main-aptos merge. The Move lineage's v9 — `attributesJson` column added
432
+ * to the Move node tables (Function, Struct, Enum, EnumVariant, Module) with
433
+ * full attribute payloads — is re-numbered past main's v9–v11: a persisted
434
+ * stamp of 9 is ambiguous between the two lineages, and a pre-merge Move
435
+ * index also predates main's v9–v11 rebuild reasons. Any pre-v12 stamp fails
436
+ * the strict-equality reuse gate; force a full re-analyze (same contract as v3).
437
+ */
438
+ export declare const INCREMENTAL_SCHEMA_VERSION = 12;
247
439
  export interface IndexedRepo {
248
440
  repoPath: string;
249
441
  storagePath: string;
@@ -71,6 +71,18 @@ export const canonicalizePath = (p) => {
71
71
  * lookups/dedup/finalize checks all share so they answer identically.
72
72
  */
73
73
  export const registryPathEquals = (a, b) => process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b;
74
+ /**
75
+ * Does the clone dir derived from an entry's *name* actually belong to that
76
+ * entry? Registry names are not unique across storage locations: a cloned
77
+ * repo under `~/.gitnexus/repos/<name>` and a local repo registered under the
78
+ * same name share a `getCloneDir(entry.name)` result. The server's delete
79
+ * handler must therefore never remove the clone dir based on the name alone —
80
+ * only when the entry's own `path` resolves to that dir (mirroring its step-2b
81
+ * rule that cleanup is driven off `entry.path`, so a same-named sibling's
82
+ * clone is never removed). Both sides are canonicalised so symlinked or
83
+ * differently-spelled forms of the same dir still match.
84
+ */
85
+ export const cloneDirBelongsToEntry = (cloneDir, entryPath) => registryPathEquals(canonicalizePath(cloneDir), canonicalizePath(entryPath));
74
86
  /**
75
87
  * Bumped whenever incremental-indexing invariants change incompatibly.
76
88
  * v2: `BasicBlock.callees` column added (statement-precise inter-procedural
@@ -90,8 +102,51 @@ export const registryPathEquals = (a, b) => process.platform === 'win32' ? a.toL
90
102
  * URL-only id). The incremental writeback preserves unchanged-file rows, so a
91
103
  * top-up against a pre-v5 index would strand old url-keyed Route nodes alongside
92
104
  * new composite-keyed ones — force a full re-analyze instead.
105
+ * v6: line-number storage flipped to uniform 0-based for the last 1-based
106
+ * GraphNode emitters — COBOL/JCL/markdown/scope (#2377/#2379/#2380). Incremental
107
+ * writeback preserves unchanged-file rows, so a top-up against a pre-v6 index
108
+ * would MIX old 1-based rows with new 0-based ones — and the 1-based MCP display
109
+ * would render the stale rows one line too high — so force a full re-analyze.
110
+ * v7: callable-value-flow CALLS/USES edges added (#2437/#2522) — new edges can
111
+ * connect two files whose content did not change, but the incremental write set
112
+ * only covers changed files (`computeEffectiveWriteSet`), so a top-up against a
113
+ * pre-v7 index would silently omit the new edges for every unchanged file pair;
114
+ * force a full re-analyze instead (same contract as v2–v6).
115
+ * v8: Java anonymous class bodies became first-class Class nodes (#2550):
116
+ * `new Runnable() { run(){} }` now emits `Class:...:Worker$1` and its methods
117
+ * re-keyed from `Worker.run` to `Worker$1.run`. Node identities move on
118
+ * unchanged files — a top-up against a pre-v8 index would strand the old
119
+ * `Worker.run`-keyed Method nodes alongside the new ones (the v5 Route
120
+ * precedent); force a full re-analyze instead.
121
+ * v9: Java enum constant bodies joined the instance model and anonymous
122
+ * naming switched to JLS 13.1 immediately-enclosing-type chains (#2555): `enum E { A {
123
+ * hook(){} } }` now emits `Class:...:E$1` with methods re-keyed from
124
+ * `E.hook` to `E$1.hook`, and nested-host anonymous names re-key
125
+ * (`EnumWrap$1` → `EnumWrap$Mode$1`). Same contract as v8: identities move
126
+ * on unchanged files; force a full re-analyze.
127
+ * v10: Java `record_declaration` now emits a first-class `Record` graph node
128
+ * (#2564): a record's container node was previously never created (JAVA_QUERIES
129
+ * had no capture for it), so its methods existed as ownerless Method nodes
130
+ * with no `HAS_METHOD` edge. The incremental write set only covers changed
131
+ * files — a top-up against a pre-v10 index would keep silently omitting the
132
+ * `Record` node and its `HAS_METHOD` edges for every unchanged record file
133
+ * (same v7 contract: new nodes/edges the incremental path would otherwise
134
+ * never backfill); force a full re-analyze instead.
135
+ * v11: Rust abstract trait methods (`fn foo(&self) -> T;`, no body) now get a
136
+ * scope + declaration capture (#2604): RUST_SCOPE_QUERY had no
137
+ * `function_signature_item` pattern, so a `&dyn Trait` receiver could never
138
+ * dispatch a CALLS edge to the trait's own method. Same v7/v10 contract: the
139
+ * incremental write set only covers changed files, so a top-up against a
140
+ * pre-v11 index would keep silently missing these CALLS edges for every
141
+ * unchanged Rust trait file; force a full re-analyze instead.
142
+ * v12: main-aptos merge. The Move lineage's v9 — `attributesJson` column added
143
+ * to the Move node tables (Function, Struct, Enum, EnumVariant, Module) with
144
+ * full attribute payloads — is re-numbered past main's v9–v11: a persisted
145
+ * stamp of 9 is ambiguous between the two lineages, and a pre-merge Move
146
+ * index also predates main's v9–v11 rebuild reasons. Any pre-v12 stamp fails
147
+ * the strict-equality reuse gate; force a full re-analyze (same contract as v3).
93
148
  */
94
- export const INCREMENTAL_SCHEMA_VERSION = 5;
149
+ export const INCREMENTAL_SCHEMA_VERSION = 12;
95
150
  const GITNEXUS_DIR = '.gitnexus';
96
151
  const GITNEXUS_EXCLUDE_ENTRY = `${GITNEXUS_DIR}/`;
97
152
  export const INDEX_METADATA_FILE = 'gitnexus.json';
@@ -391,6 +391,49 @@ function buildAfterToolContext(input) {
391
391
  return parts.length > 0 ? parts.join('\n\n') : null;
392
392
  }
393
393
 
394
+ /**
395
+ * Fallback augmentation for the #2396 path: when a GitNexus process holds the
396
+ * lbug DB write lock the CLI `augment` can't run, so point the agent at the MCP
397
+ * `query` tool instead. Phrased conditionally ("if the MCP tools are live") so it
398
+ * stays truthful on every owner path — a confirmed MCP owner, a `serve` owner, or
399
+ * a fail-closed probe where no server is actually confirmed. `pattern` is embedded
400
+ * verbatim; the caller (writeAdditionalContext) JSON-escapes it structurally.
401
+ */
402
+ function buildMcpQueryHint(pattern) {
403
+ return (
404
+ `[GitNexus] Local augment is unavailable (the graph DB is held by another ` +
405
+ `GitNexus process). If the GitNexus MCP tools are live in this session, call ` +
406
+ `the GitNexus \`query\` MCP tool (e.g. mcp__gitnexus__query) with ` +
407
+ `search_query "${pattern}".`
408
+ );
409
+ }
410
+
411
+ /**
412
+ * #2396 throttle: emit the MCP-query hint at most once per repo per window, so an
413
+ * owner-locked session isn't nudged on every search. Window (ms) via
414
+ * GITNEXUS_MCP_HINT_THROTTLE_MS (default 10min; 0/invalid disables). Best-effort —
415
+ * any fs error falls back to emitting.
416
+ * ponytail: per-repo mtime marker, shared across concurrent sessions on the same
417
+ * repo; add per-session dedup only if that sharing becomes a problem.
418
+ */
419
+ function shouldEmitMcpHint(gitNexusDir) {
420
+ const raw = process.env.GITNEXUS_MCP_HINT_THROTTLE_MS;
421
+ const windowMs = raw === undefined || raw === '' ? 600000 : Number(raw);
422
+ if (!Number.isFinite(windowMs) || windowMs <= 0) return true;
423
+ const marker = path.join(gitNexusDir, '.mcp-hint-shown');
424
+ try {
425
+ if (Date.now() - fs.statSync(marker).mtimeMs < windowMs) return false;
426
+ } catch {
427
+ /* marker missing/unreadable → emit */
428
+ }
429
+ try {
430
+ fs.writeFileSync(marker, '');
431
+ } catch {
432
+ /* best-effort; still emit */
433
+ }
434
+ return true;
435
+ }
436
+
394
437
  function runAugment(gitNexusDir, cwd, pattern) {
395
438
  // Acquire the per-repo slot BEFORE the DB-owner probe (#2163): the probe
396
439
  // itself spawns lsof/ps, so it must be bounded by the same ≤3-per-repo cap
@@ -410,12 +453,16 @@ function runAugment(gitNexusDir, cwd, pattern) {
410
453
  }
411
454
  try {
412
455
  if (hasGitNexusServerOwner(gitNexusDir)) {
413
- // Normal skip path: the MCP server owns the DB. Stay silent for strict
414
- // hook runners (issue #1913); surface the reason only under GITNEXUS_DEBUG.
456
+ // #2396: the MCP server holds the DB write lock, so a competing CLI
457
+ // `augment` would only contend on it (LadybugDB is single-writer). The
458
+ // session has the GitNexus MCP tools live — route the augmentation to the
459
+ // agent via additionalContext instead of dropping it. Mirror the skip
460
+ // reason to stderr only under GITNEXUS_DEBUG (strict-runner contract,
461
+ // #1913); the hint itself rides the sanctioned additionalContext channel.
415
462
  if (isDebugEnabled()) {
416
463
  process.stderr.write('[GitNexus] augment skipped: MCP server owns DB\n');
417
464
  }
418
- return '';
465
+ return shouldEmitMcpHint(gitNexusDir) ? buildMcpQueryHint(pattern) : '';
419
466
  }
420
467
  const cliPath = resolveCliPath();
421
468
  const child = runGitNexusCli(cliPath, ['augment', '--', pattern], cwd, 7000);