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
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Warning attached to search responses when BM25/FTS is degraded. Prefers the
3
+ * live extension-load failure (with LadybugDB's real reason, #2374) over the
4
+ * generic indexes-missing message, so "indexes exist but the extension broke"
5
+ * is not misreported as missing indexes.
6
+ */
7
+ export declare const ftsDegradedWarning: () => string;
1
8
  export declare const SUPPORTED_FTS_STEMMERS: ReadonlySet<string>;
2
9
  export interface CreateSearchFTSIndexesOptions {
3
10
  onIndexStart?: (table: string, indexName: string) => void;
@@ -17,5 +24,29 @@ export declare function initialiseSearchFTSStemmer(): string;
17
24
  * tests) so validation always applies.
18
25
  */
19
26
  export declare function getSearchFTSStemmer(): string;
27
+ /**
28
+ * Drop every configured FTS index (no-op per index when absent or unloadable
29
+ * — `dropFTSIndex` tolerates both). Callable ahead of any DML that mutates an
30
+ * FTS-indexed table's rows: LadybugDB's FTS extension is not proven to
31
+ * survive a DETACH DELETE against a table that still carries a live index
32
+ * from a prior run (#2589) — dropping first removes that hazard entirely,
33
+ * regardless of whether it also fixed a specific native inconsistency.
34
+ */
35
+ export declare function dropSearchFTSIndexes(): Promise<void>;
20
36
  export declare function createSearchFTSIndexes(options?: CreateSearchFTSIndexesOptions): Promise<void>;
21
37
  export declare function verifySearchFTSIndexes(executeQuery: (cypher: string) => Promise<unknown[]>): Promise<string[]>;
38
+ export interface BuildSearchIndexesResult {
39
+ ok: boolean;
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Build + verify FTS indexes, catching any failure instead of letting it
44
+ * propagate. `createSearchFTSIndexes` re-tokenizes every stored row on every
45
+ * analyze run (see the `ponytail:` comment above) — a native LadybugDB
46
+ * tokenizer error on a single pre-existing row (e.g. a "Failed calling
47
+ * LOWER: Invalid UTF-8", #2544/#2546) must not discard an otherwise-
48
+ * successful analyze's graph/embeddings work. The caller degrades keyword
49
+ * search for this run instead, mirroring the existing FTS-extension-
50
+ * unavailable degrade path in `run-analyze.ts`.
51
+ */
52
+ export declare function buildSearchIndexesOrDegrade(executeQuery: (cypher: string) => Promise<unknown[]>, options?: CreateSearchFTSIndexesOptions): Promise<BuildSearchIndexesResult>;
@@ -1,5 +1,42 @@
1
1
  import { createFTSIndex, dropFTSIndex, DEFAULT_FTS_STEMMER } from '../lbug/lbug-adapter.js';
2
+ import { getExtensionCapabilities } from '../lbug/extension-loader.js';
3
+ import { classifyExtensionLoadError } from '../lbug/extension-load-error.js';
2
4
  import { FTS_INDEXES } from './fts-schema.js';
5
+ /**
6
+ * Strip filesystem paths from a LadybugDB error before it reaches the HTTP
7
+ * `/api/search` and MCP query surfaces (#2374, PR #2375): the raw LOAD error
8
+ * embeds the absolute extension path (username, home dir) which must not leak to
9
+ * a network client. The error class words ("Failed to load library", "invalid
10
+ * ELF header", "has not been installed") have no leading path separator and
11
+ * survive. CLI/doctor/log surfaces keep the full path (they read the reason
12
+ * directly, not through this function).
13
+ */
14
+ const redactPaths = (reason) => reason.replace(/(?:[A-Za-z]:\\|\/)[^\s'"]+/g, '<path>');
15
+ /**
16
+ * Warning attached to search responses when BM25/FTS is degraded. Prefers the
17
+ * live extension-load failure (with LadybugDB's real reason, #2374) over the
18
+ * generic indexes-missing message, so "indexes exist but the extension broke"
19
+ * is not misreported as missing indexes.
20
+ */
21
+ export const ftsDegradedWarning = () => {
22
+ const fts = getExtensionCapabilities().find((c) => c.name === 'fts');
23
+ if (fts && !fts.loaded) {
24
+ const reason = fts.reason ? redactPaths(fts.reason).replace(/\.$/, '') : undefined;
25
+ // A missing *runtime dependency* (Windows error 126, etc.) is not healed by
26
+ // reinstalling (#2374) — surface the classified remedy instead of the generic
27
+ // reinstall tail. Read the diagnosis cached at mark-unavailable time so this
28
+ // per-request path (HTTP /api/search + MCP query) does NO file I/O (#2383 F3);
29
+ // fall back to the pure, no-I/O string classifier if it is somehow absent.
30
+ const { kind, remedy } = fts.diagnosis ?? classifyExtensionLoadError(fts.reason);
31
+ const tail = kind === 'missing_dependency'
32
+ ? ` ${remedy}`
33
+ : '. Run `gitnexus doctor` for details, then `gitnexus analyze --repair-fts` with network access to reinstall.';
34
+ return ('FTS extension failed to load — keyword search degraded' +
35
+ (reason ? ` (${reason})` : '') +
36
+ tail);
37
+ }
38
+ return 'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --repair-fts (or gitnexus analyze --force) to rebuild indexes.';
39
+ };
3
40
  // Stemmers shipped by the LadybugDB FTS extension. Mirrors the lowercase token
4
41
  // set in the extension bundled with @ladybugdb/core 0.18.x (see package.json).
5
42
  // Keep in sync on a LadybugDB minor bump — a value here that the installed
@@ -66,6 +103,19 @@ export function initialiseSearchFTSStemmer() {
66
103
  export function getSearchFTSStemmer() {
67
104
  return resolvedStemmer ?? resolveFTSStemmer();
68
105
  }
106
+ /**
107
+ * Drop every configured FTS index (no-op per index when absent or unloadable
108
+ * — `dropFTSIndex` tolerates both). Callable ahead of any DML that mutates an
109
+ * FTS-indexed table's rows: LadybugDB's FTS extension is not proven to
110
+ * survive a DETACH DELETE against a table that still carries a live index
111
+ * from a prior run (#2589) — dropping first removes that hazard entirely,
112
+ * regardless of whether it also fixed a specific native inconsistency.
113
+ */
114
+ export async function dropSearchFTSIndexes() {
115
+ for (const { table, indexName } of FTS_INDEXES) {
116
+ await dropFTSIndex(table, indexName);
117
+ }
118
+ }
69
119
  export async function createSearchFTSIndexes(options) {
70
120
  const stemmer = getSearchFTSStemmer();
71
121
  for (const { table, indexName, properties } of FTS_INDEXES) {
@@ -115,3 +165,26 @@ export async function verifySearchFTSIndexes(executeQuery) {
115
165
  }
116
166
  return missing;
117
167
  }
168
+ /**
169
+ * Build + verify FTS indexes, catching any failure instead of letting it
170
+ * propagate. `createSearchFTSIndexes` re-tokenizes every stored row on every
171
+ * analyze run (see the `ponytail:` comment above) — a native LadybugDB
172
+ * tokenizer error on a single pre-existing row (e.g. a "Failed calling
173
+ * LOWER: Invalid UTF-8", #2544/#2546) must not discard an otherwise-
174
+ * successful analyze's graph/embeddings work. The caller degrades keyword
175
+ * search for this run instead, mirroring the existing FTS-extension-
176
+ * unavailable degrade path in `run-analyze.ts`.
177
+ */
178
+ export async function buildSearchIndexesOrDegrade(executeQuery, options) {
179
+ try {
180
+ await createSearchFTSIndexes(options);
181
+ const missing = await verifySearchFTSIndexes(executeQuery);
182
+ if (missing.length > 0) {
183
+ return { ok: false, error: `missing indexes after build: ${missing.join(', ')}` };
184
+ }
185
+ return { ok: true };
186
+ }
187
+ catch (e) {
188
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
189
+ }
190
+ }
@@ -37,4 +37,6 @@ export const FTS_INDEXES = [
37
37
  { table: 'Union', indexName: 'union_fts', properties: FTS_PROPERTIES },
38
38
  { table: 'Static', indexName: 'static_fts', properties: FTS_PROPERTIES },
39
39
  { table: 'Variable', indexName: 'variable_fts', properties: FTS_PROPERTIES },
40
+ // Move/Aptos module nodes also carry description/content columns.
41
+ { table: 'Module', indexName: 'module_fts', properties: FTS_PROPERTIES },
40
42
  ];
@@ -42,7 +42,7 @@ export declare function getParseDiagnostics(tree: Parser.Tree): {
42
42
  /**
43
43
  * Parse `sourceText` safely on every platform.
44
44
  *
45
- * This is the single "parse safely" entry point and its contract covers three
45
+ * This is the single "parse safely" entry point and its contract covers four
46
46
  * concerns:
47
47
  *
48
48
  * 1. **Windows crash workaround.** Inputs longer than 32 767 chars are fed
@@ -62,7 +62,12 @@ export declare function getParseDiagnostics(tree: Parser.Tree): {
62
62
  * the tree is **returned anyway** — error recovery is a downgrade, never a
63
63
  * drop. Callers wanting the boolean use {@link parseHadErrors}.
64
64
  *
65
- * @param label optional context (e.g. file path) attached to timeout errors
66
- * and degraded-parse logs. Non-breaking trailing param.
65
+ * 4. **Embedded NUL recovery.** U+0000 is replaced with one ASCII space in
66
+ * the parser-only input. The one-for-one substitution keeps tree indices
67
+ * aligned with the original source while preventing language lexers from
68
+ * swallowing declarations during error recovery.
69
+ *
70
+ * @param label optional context (e.g. file path) attached to timeout errors,
71
+ * recovery warnings, and degraded-parse logs. Non-breaking trailing param.
67
72
  */
68
73
  export declare function parseSourceSafe(parser: Parser, sourceText: string, oldTree?: Parser.Tree, options?: Parser.Options, label?: string): Parser.Tree;
@@ -155,7 +155,7 @@ export function getParseDiagnostics(tree) {
155
155
  /**
156
156
  * Parse `sourceText` safely on every platform.
157
157
  *
158
- * This is the single "parse safely" entry point and its contract covers three
158
+ * This is the single "parse safely" entry point and its contract covers four
159
159
  * concerns:
160
160
  *
161
161
  * 1. **Windows crash workaround.** Inputs longer than 32 767 chars are fed
@@ -175,22 +175,36 @@ export function getParseDiagnostics(tree) {
175
175
  * the tree is **returned anyway** — error recovery is a downgrade, never a
176
176
  * drop. Callers wanting the boolean use {@link parseHadErrors}.
177
177
  *
178
- * @param label optional context (e.g. file path) attached to timeout errors
179
- * and degraded-parse logs. Non-breaking trailing param.
178
+ * 4. **Embedded NUL recovery.** U+0000 is replaced with one ASCII space in
179
+ * the parser-only input. The one-for-one substitution keeps tree indices
180
+ * aligned with the original source while preventing language lexers from
181
+ * swallowing declarations during error recovery.
182
+ *
183
+ * @param label optional context (e.g. file path) attached to timeout errors,
184
+ * recovery warnings, and degraded-parse logs. Non-breaking trailing param.
180
185
  */
181
186
  export function parseSourceSafe(parser, sourceText, oldTree, options, label) {
187
+ let parserInput = sourceText;
188
+ if (sourceText.includes('\0')) {
189
+ let nullByteCount = 0;
190
+ parserInput = sourceText.replaceAll('\0', () => {
191
+ nullByteCount += 1;
192
+ return ' ';
193
+ });
194
+ logger.warn({ ...(label ? { file: label } : {}), nullByteCount }, 'replaced embedded NUL bytes before tree-sitter parsing');
195
+ }
182
196
  const budgetMs = resolveParseTimeoutMs();
183
197
  const armed = armParseBudget(parser, budgetMs);
184
198
  let tree;
185
199
  try {
186
- if (sourceText.length <= DIRECT_PARSE_LIMIT_CHARS) {
187
- tree = parser.parse(sourceText, oldTree, options);
200
+ if (parserInput.length <= DIRECT_PARSE_LIMIT_CHARS) {
201
+ tree = parser.parse(parserInput, oldTree, options);
188
202
  }
189
203
  else {
190
204
  const input = (index) => {
191
- if (index >= sourceText.length)
205
+ if (index >= parserInput.length)
192
206
  return null;
193
- return sourceText.slice(index, index + SAFE_PARSE_CHUNK_CHARS);
207
+ return parserInput.slice(index, index + SAFE_PARSE_CHUNK_CHARS);
194
208
  };
195
209
  tree = parser.parse(input, oldTree, options);
196
210
  }
@@ -5,6 +5,7 @@
5
5
  * Uses the MCP-style pooled lbug-adapter for connection management.
6
6
  */
7
7
  import { initLbug, executeQuery, closeLbug, touchRepo, pinRepo } from '../lbug/pool-adapter.js';
8
+ import { escapeCypherString } from '../lbug/cypher-escape.js';
8
9
  const REPO_ID = '__wiki__';
9
10
  /**
10
11
  * Touch the wiki DB connection to prevent idle timeout during long LLM calls.
@@ -98,7 +99,7 @@ export async function getInterFileCallEdges() {
98
99
  export async function getIntraModuleCallEdges(filePaths) {
99
100
  if (filePaths.length === 0)
100
101
  return [];
101
- const fileList = filePaths.map((f) => `'${f.replace(/'/g, "''")}'`).join(', ');
102
+ const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
102
103
  const rows = await executeQuery(REPO_ID, `
103
104
  MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b)
104
105
  WHERE a.filePath IN [${fileList}] AND b.filePath IN [${fileList}]
@@ -118,7 +119,7 @@ export async function getIntraModuleCallEdges(filePaths) {
118
119
  export async function getInterModuleCallEdges(filePaths) {
119
120
  if (filePaths.length === 0)
120
121
  return { outgoing: [], incoming: [] };
121
- const fileList = filePaths.map((f) => `'${f.replace(/'/g, "''")}'`).join(', ');
122
+ const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
122
123
  const outRows = await executeQuery(REPO_ID, `
123
124
  MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b)
124
125
  WHERE a.filePath IN [${fileList}] AND NOT b.filePath IN [${fileList}]
@@ -155,7 +156,7 @@ export async function getInterModuleCallEdges(filePaths) {
155
156
  export async function getProcessesForFiles(filePaths, limit = 5) {
156
157
  if (filePaths.length === 0)
157
158
  return [];
158
- const fileList = filePaths.map((f) => `'${f.replace(/'/g, "''")}'`).join(', ');
159
+ const fileList = filePaths.map((f) => `'${escapeCypherString(f)}'`).join(', ');
159
160
  // Find processes that have steps in the given files
160
161
  const procRows = await executeQuery(REPO_ID, `
161
162
  MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
@@ -173,7 +174,7 @@ export async function getProcessesForFiles(filePaths, limit = 5) {
173
174
  const stepCount = row.stepCount || row[3] || 0;
174
175
  // Get the full step trace for this process
175
176
  const stepRows = await executeQuery(REPO_ID, `
176
- MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${procId.replace(/'/g, "''")}'})
177
+ MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${escapeCypherString(procId)}'})
177
178
  RETURN s.name AS name, s.filePath AS filePath, labels(s)[0] AS type, r.step AS step
178
179
  ORDER BY r.step
179
180
  `);
@@ -210,7 +211,7 @@ export async function getAllProcesses(limit = 20) {
210
211
  const type = row.type || row[2] || 'unknown';
211
212
  const stepCount = row.stepCount || row[3] || 0;
212
213
  const stepRows = await executeQuery(REPO_ID, `
213
- MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${procId.replace(/'/g, "''")}'})
214
+ MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process {id: '${escapeCypherString(procId)}'})
214
215
  RETURN s.name AS name, s.filePath AS filePath, labels(s)[0] AS type, r.step AS step
215
216
  ORDER BY r.step
216
217
  `);
@@ -23,6 +23,8 @@ export interface LLMConfig {
23
23
  requestTimeoutMs?: number;
24
24
  /** Max fetch attempts before giving up (default: 3). */
25
25
  maxAttempts?: number;
26
+ /** Exact hostnames allowed for explicit http:// LLM endpoints. */
27
+ allowedInsecureHttpHosts?: readonly string[];
26
28
  }
27
29
  export interface LLMResponse {
28
30
  content: string;
@@ -40,6 +42,8 @@ export declare function resolveLLMConfig(overrides?: Partial<LLMConfig>): Promis
40
42
  * Estimate token count from text (rough heuristic: ~4 chars per token).
41
43
  */
42
44
  export declare function estimateTokens(text: string): number;
45
+ export declare const LLM_ALLOW_INSECURE_CONNECTION_ENV = "GITNEXUS_ALLOW_INSECURE_CONNECTION";
46
+ export declare function parseLLMAllowedInsecureHttpHosts(value: string | undefined): string[];
43
47
  /**
44
48
  * Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
45
49
  * endpoint (CWE-918 / CodeQL js/http-to-file-access).
@@ -47,15 +51,17 @@ export declare function estimateTokens(text: string): number;
47
51
  * Allowed:
48
52
  * - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
49
53
  * - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
54
+ * - http:// to exact hosts explicitly allowlisted for LAN/self-hosted LLMs
50
55
  *
51
56
  * Rejected:
52
57
  * - file://, data:, javascript:, and any other non-HTTP scheme
53
- * - http:// aimed at non-loopback hosts (avoids SSRF against internal networks)
58
+ * - http:// aimed at non-loopback hosts unless explicitly allowlisted
59
+ * (avoids SSRF against internal networks by default)
54
60
  *
55
61
  * Throws with a descriptive message on validation failure so callers surface a
56
62
  * clear error rather than an opaque network error.
57
63
  */
58
- export declare function validateLLMBaseUrl(baseUrl: string): void;
64
+ export declare function validateLLMBaseUrl(baseUrl: string, allowedInsecureHttpHosts?: readonly string[]): void;
59
65
  /**
60
66
  * Returns true if the given base URL is an Azure OpenAI endpoint.
61
67
  * Uses proper hostname matching to avoid spoofed URLs like
@@ -43,6 +43,8 @@ export async function resolveLLMConfig(overrides) {
43
43
  provider: savedProvider ?? 'openai',
44
44
  apiVersion: overrides?.apiVersion || process.env.GITNEXUS_AZURE_API_VERSION || savedConfig.apiVersion,
45
45
  isReasoningModel: overrides?.isReasoningModel ?? savedConfig.isReasoningModel,
46
+ allowedInsecureHttpHosts: overrides?.allowedInsecureHttpHosts ??
47
+ parseLLMAllowedInsecureHttpHosts(process.env[LLM_ALLOW_INSECURE_CONNECTION_ENV]),
46
48
  };
47
49
  }
48
50
  /**
@@ -64,6 +66,36 @@ function isTimeoutLikeError(err) {
64
66
  return true;
65
67
  return /time(d)?\s*out|timeout/i.test(err.message);
66
68
  }
69
+ export const LLM_ALLOW_INSECURE_CONNECTION_ENV = 'GITNEXUS_ALLOW_INSECURE_CONNECTION';
70
+ function normalizeAllowedInsecureHttpHost(host) {
71
+ const trimmed = host.trim().toLowerCase();
72
+ const fail = () => {
73
+ throw new Error(`--allow-insecure-connection / ${LLM_ALLOW_INSECURE_CONNECTION_ENV} entries must be exact hostnames or IP addresses`);
74
+ };
75
+ if (!trimmed || /[/@?#]/.test(trimmed))
76
+ fail();
77
+ if (trimmed.startsWith('[')) {
78
+ if (!trimmed.endsWith(']'))
79
+ fail();
80
+ const normalized = trimmed.slice(1, -1);
81
+ if (!normalized || /[\[\]]/.test(normalized))
82
+ fail();
83
+ return normalized;
84
+ }
85
+ if (/[\[\]]/.test(trimmed))
86
+ fail();
87
+ if ((trimmed.match(/:/g)?.length ?? 0) === 1) {
88
+ // URL.hostname never includes the port, so accepting "host:port" would
89
+ // create a confusing no-op allowlist entry.
90
+ fail();
91
+ }
92
+ return trimmed;
93
+ }
94
+ export function parseLLMAllowedInsecureHttpHosts(value) {
95
+ if (value === undefined || value.trim() === '')
96
+ return [];
97
+ return [...new Set(value.split(',').map(normalizeAllowedInsecureHttpHost))];
98
+ }
67
99
  /**
68
100
  * Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
69
101
  * endpoint (CWE-918 / CodeQL js/http-to-file-access).
@@ -71,15 +103,17 @@ function isTimeoutLikeError(err) {
71
103
  * Allowed:
72
104
  * - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
73
105
  * - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
106
+ * - http:// to exact hosts explicitly allowlisted for LAN/self-hosted LLMs
74
107
  *
75
108
  * Rejected:
76
109
  * - file://, data:, javascript:, and any other non-HTTP scheme
77
- * - http:// aimed at non-loopback hosts (avoids SSRF against internal networks)
110
+ * - http:// aimed at non-loopback hosts unless explicitly allowlisted
111
+ * (avoids SSRF against internal networks by default)
78
112
  *
79
113
  * Throws with a descriptive message on validation failure so callers surface a
80
114
  * clear error rather than an opaque network error.
81
115
  */
82
- export function validateLLMBaseUrl(baseUrl) {
116
+ export function validateLLMBaseUrl(baseUrl, allowedInsecureHttpHosts = parseLLMAllowedInsecureHttpHosts(process.env[LLM_ALLOW_INSECURE_CONNECTION_ENV])) {
83
117
  let parsed;
84
118
  try {
85
119
  parsed = new URL(baseUrl);
@@ -96,9 +130,11 @@ export function validateLLMBaseUrl(baseUrl) {
96
130
  // Node's URL parser preserves IPv6 brackets in hostname (e.g. "[::1]"),
97
131
  // so strip them before comparing to bare address literals.
98
132
  const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, '');
99
- if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1') {
133
+ const allowedHosts = new Set(allowedInsecureHttpHosts.map(normalizeAllowedInsecureHttpHost));
134
+ if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1' && !allowedHosts.has(host)) {
100
135
  // Use parsed.origin (scheme+host+port, no credentials) instead of the full URL.
101
- throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1. ` +
136
+ throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1 ` +
137
+ `or hosts listed by --allow-insecure-connection / ${LLM_ALLOW_INSECURE_CONNECTION_ENV}. ` +
102
138
  `Use https:// for remote endpoints (got ${parsed.origin})`);
103
139
  }
104
140
  }
@@ -145,7 +181,7 @@ export function buildRequestUrl(baseUrl, apiVersion) {
145
181
  */
146
182
  export async function callLLM(prompt, config, systemPrompt, options) {
147
183
  // Validate base URL before any fetch (CodeQL js/http-to-file-access)
148
- validateLLMBaseUrl(config.baseUrl);
184
+ validateLLMBaseUrl(config.baseUrl, config.allowedInsecureHttpHosts);
149
185
  const messages = [];
150
186
  if (systemPrompt) {
151
187
  messages.push({ role: 'system', content: systemPrompt });
@@ -7,8 +7,9 @@
7
7
  import { isHttpMode, getHttpDimensions, httpEmbedQuery, } from '../../core/embeddings/http-client.js';
8
8
  import { resolveEmbeddingConfig } from '../../core/embeddings/config.js';
9
9
  import { applyHfEnvOverrides, isHfDownloadFailure, withHfDownloadRetry, } from '../../core/embeddings/hf-env.js';
10
- import { getLocalEmbeddingRuntimeBlocker } from '../../core/embeddings/runtime-support.js';
10
+ import { getLocalEmbeddingRuntimeBlocker, getMissingLocalEmbeddingStackMessage, } from '../../core/embeddings/runtime-support.js';
11
11
  import { ensureOnnxRuntimeCommonResolvable } from '../../core/embeddings/onnxruntime-common-resolver.js';
12
+ import { ensureEmbeddingStackResolvable } from '../../core/embeddings/runtime-install.js';
12
13
  import { ensureOnnxRuntimeNodeMatchesSystem } from '../../core/embeddings/onnxruntime-node-resolver.js';
13
14
  import { silenceStdout, restoreStdout, realStderrWrite } from '../../core/lbug/pool-adapter.js';
14
15
  import { logger } from '../../core/logger.js';
@@ -45,6 +46,11 @@ export const initEmbedder = async () => {
45
46
  try {
46
47
  // Lazy-load transformers.js only after the runtime guard has passed, so
47
48
  // unsupported platforms never reach the native ONNX import (#1515).
49
+ // Registered FIRST so it sits last in the hook chain (registerHooks runs
50
+ // the most recent hook first): when the optional stack was pruned at
51
+ // install time (#2370), its bare specifiers fall back to the on-demand
52
+ // runtime prefix.
53
+ ensureEmbeddingStackResolvable();
48
54
  // Under pnpm-strict / `pnpm dlx`, transformers' phantom `onnxruntime-common`
49
55
  // import is unresolvable; register the fallback resolver first (#307).
50
56
  ensureOnnxRuntimeCommonResolvable();
@@ -55,7 +61,15 @@ export const initEmbedder = async () => {
55
61
  // Windows/DirectML, and macOS. Mirrors the core embedder's call site so
56
62
  // MCP query-time embedding gets the same CUDA-13 fix.
57
63
  ensureOnnxRuntimeNodeMatchesSystem();
58
- const { pipeline, env } = await import('@huggingface/transformers');
64
+ // The stack is an optionalDependency: npm prunes it when onnxruntime-node's
65
+ // postinstall can't reach api.nuget.org (#2370). Rethrow with actionable
66
+ // reinstall guidance instead of a raw ERR_MODULE_NOT_FOUND.
67
+ const { pipeline, env } = await import('@huggingface/transformers').catch((err) => {
68
+ const missing = getMissingLocalEmbeddingStackMessage(err);
69
+ if (missing)
70
+ throw new Error(missing);
71
+ throw err;
72
+ });
59
73
  env.allowLocalModels = false;
60
74
  // Bridge user-controlled env vars to transformers.js: HF_HOME →
61
75
  // env.cacheDir, HF_ENDPOINT → env.remoteHost (#1205). Centralised in
@@ -23,6 +23,7 @@ import type { Server as HttpServer } from 'http';
23
23
  import { type Request, type Response, type NextFunction } from 'express';
24
24
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
25
25
  import type { LocalBackend } from './local/local-backend.js';
26
+ import { type McpRepositoryPolicy } from './repository-policy.js';
26
27
  /** HTTP server configuration options. */
27
28
  export interface McpHttpOptions {
28
29
  /** Listening port. */
@@ -31,6 +32,8 @@ export interface McpHttpOptions {
31
32
  host: string;
32
33
  /** Bearer auth token (optional; no auth when omitted). */
33
34
  authToken?: string;
35
+ /** Prevalidated repository policy shared by startup logging and transports. */
36
+ repositoryPolicy?: McpRepositoryPolicy;
34
37
  }
35
38
  /**
36
39
  * Creates a Bearer Token authentication middleware.
@@ -93,6 +96,7 @@ export declare function createStreamableHttpHandler(backend: LocalBackend, opts?
93
96
  createServer?: () => Server;
94
97
  host?: string;
95
98
  port?: number;
99
+ repositoryPolicy?: McpRepositoryPolicy;
96
100
  }): {
97
101
  handler: (req: Request, res: Response) => Promise<void>;
98
102
  cleanup: () => Promise<void>;
@@ -113,6 +117,7 @@ export declare function createSseHandlers(backend: LocalBackend, messagesPath?:
113
117
  maxSessions?: number;
114
118
  host?: string;
115
119
  port?: number;
120
+ repositoryPolicy?: McpRepositoryPolicy;
116
121
  }): {
117
122
  sseHandler: (req: Request, res: Response) => Promise<void>;
118
123
  messageHandler: (req: Request, res: Response) => Promise<void>;
@@ -27,6 +27,7 @@ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
27
27
  import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
28
28
  import { createMCPServer, installSignalShutdown } from './server.js';
29
29
  import { logger } from '../core/logger.js';
30
+ import { createMcpRepositoryPolicy, mcpRepositoryPolicyConfigured, } from './repository-policy.js';
30
31
  /** Sessions idle longer than this are evicted. */
31
32
  const SESSION_TTL_MS = 30 * 60 * 1000;
32
33
  /** Cleanup sweep runs every 5 minutes. */
@@ -170,8 +171,14 @@ export function startIdleSweep(sessions, ttlMs, intervalMs) {
170
171
  * route mount in server/mcp-http.ts (/api/mcp).
171
172
  */
172
173
  export function createStreamableHttpHandler(backend, opts = {}) {
174
+ if (opts.createServer && !opts.repositoryPolicy && mcpRepositoryPolicyConfigured()) {
175
+ throw new Error('A custom MCP server factory cannot bypass configured repository policy.');
176
+ }
173
177
  // Seam: tests inject createServer to observe the per-session Server lifecycle.
174
- const createServer = opts.createServer ?? (() => createMCPServer(backend));
178
+ let repositoryPolicy = opts.repositoryPolicy
179
+ ? Promise.resolve(opts.repositoryPolicy)
180
+ : undefined;
181
+ const getRepositoryPolicy = () => (repositoryPolicy ??= createMcpRepositoryPolicy(backend));
175
182
  // DNS-rebinding protection (Host-header allowlist) when the bind host is known.
176
183
  const dnsRebinding = dnsRebindingOptions(opts.host, opts.port);
177
184
  const sessions = new Map();
@@ -226,7 +233,9 @@ export function createStreamableHttpHandler(backend, opts = {}) {
226
233
  sessionIdGenerator: () => randomUUID(),
227
234
  ...dnsRebinding,
228
235
  });
229
- const server = createServer();
236
+ const server = opts.createServer
237
+ ? opts.createServer()
238
+ : createMCPServer(backend, { repositoryPolicy: await getRepositoryPolicy() });
230
239
  await server.connect(transport);
231
240
  await transport.handleRequest(req, res, req.body);
232
241
  if (transport.sessionId) {
@@ -282,6 +291,10 @@ export function createStreamableHttpHandler(backend, opts = {}) {
282
291
  */
283
292
  export function createSseHandlers(backend, messagesPath = '/messages', opts = {}) {
284
293
  const maxSessions = opts.maxSessions ?? MAX_SESSIONS;
294
+ let repositoryPolicy = opts.repositoryPolicy
295
+ ? Promise.resolve(opts.repositoryPolicy)
296
+ : undefined;
297
+ const getRepositoryPolicy = () => (repositoryPolicy ??= createMcpRepositoryPolicy(backend));
285
298
  // DNS-rebinding protection (Host-header allowlist) when the bind host is known.
286
299
  const dnsRebinding = dnsRebindingOptions(opts.host, opts.port);
287
300
  const sseSessions = new Map();
@@ -300,7 +313,7 @@ export function createSseHandlers(backend, messagesPath = '/messages', opts = {}
300
313
  }
301
314
  // SSEServerTransport(endpoint, res, options): endpoint is the path clients POST to.
302
315
  const transport = new SSEServerTransport(messagesPath, res, dnsRebinding);
303
- const server = createMCPServer(backend);
316
+ const server = createMCPServer(backend, { repositoryPolicy: await getRepositoryPolicy() });
304
317
  sseSessions.set(transport.sessionId, { server, transport, lastActivity: Date.now() });
305
318
  transport.onclose = () => {
306
319
  sseSessions.delete(transport.sessionId);
@@ -370,6 +383,7 @@ export async function startMcpHttpServer(backend, options) {
370
383
  'Pass --auth-token (or set GITNEXUS_MCP_AUTH_TOKEN), or bind --host 127.0.0.1. ' +
371
384
  'This applies to --host 0.0.0.0 and --host :: as well.');
372
385
  }
386
+ const repositoryPolicy = options.repositoryPolicy ?? (await createMcpRepositoryPolicy(backend));
373
387
  const app = express();
374
388
  // Suppress X-Powered-By to reduce information leakage.
375
389
  app.disable('x-powered-by');
@@ -410,7 +424,7 @@ export async function startMcpHttpServer(backend, options) {
410
424
  res.json({ status: 'ok' });
411
425
  });
412
426
  // Streamable HTTP (modern MCP clients) at POST /mcp.
413
- const streamable = createStreamableHttpHandler(backend, { host, port });
427
+ const streamable = createStreamableHttpHandler(backend, { host, port, repositoryPolicy });
414
428
  app.all('/mcp', auth, jsonBody, (req, res) => {
415
429
  void streamable.handler(req, res).catch((err) => {
416
430
  logger.error({ err }, 'MCP /mcp request failed');
@@ -424,7 +438,7 @@ export async function startMcpHttpServer(backend, options) {
424
438
  });
425
439
  });
426
440
  // Legacy SSE: GET /sse opens the stream; POST /messages receives JSON-RPC messages.
427
- const sse = createSseHandlers(backend, '/messages', { host, port });
441
+ const sse = createSseHandlers(backend, '/messages', { host, port, repositoryPolicy });
428
442
  app.get('/sse', auth, (req, res) => {
429
443
  void sse.sseHandler(req, res).catch((err) => {
430
444
  logger.error({ err }, 'MCP /sse failed');
@@ -0,0 +1,2 @@
1
+ import { type SpringBeanMetadata } from '../../core/ingestion/frameworks/spring/bean-catalog.js';
2
+ export declare function queryClassBeanMetadata(lbugPath: string, symbolId: string, symbolType: string): Promise<SpringBeanMetadata | undefined>;
@@ -0,0 +1,25 @@
1
+ import { executeParameterized } from '../../core/lbug/pool-adapter.js';
2
+ import { deriveSpringBeanMetadata, } from '../../core/ingestion/frameworks/spring/bean-catalog.js';
3
+ export async function queryClassBeanMetadata(lbugPath, symbolId, symbolType) {
4
+ if (symbolType !== 'Class')
5
+ return undefined;
6
+ try {
7
+ const rows = await executeParameterized(lbugPath, `
8
+ MATCH (c:Class {id: $symbolId})
9
+ RETURN c.frameworkAnnotations AS frameworkAnnotations
10
+ LIMIT 1
11
+ `, { symbolId });
12
+ const row = rows[0];
13
+ if (!row)
14
+ return undefined;
15
+ const value = row.frameworkAnnotations ?? row[0];
16
+ if (!Array.isArray(value))
17
+ return undefined;
18
+ return deriveSpringBeanMetadata(value.filter((annotation) => typeof annotation === 'string'));
19
+ }
20
+ catch {
21
+ // Older or partially upgraded indexes may not have the column. This
22
+ // enrichment is additive, so context and impact must still succeed.
23
+ return undefined;
24
+ }
25
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Convert a 0-based GraphNode `startLine`/`endLine` to the 1-based line number
3
+ * shown to humans and LLMs in MCP tool output.
4
+ *
5
+ * Storage is 0-based (tree-sitter `startPosition.row`; see
6
+ * `ingestion/utils/line-base.ts`), which matches editors/`sed`/`less -N` only
7
+ * after `+ 1`. The `context`, `query`, and `impact` tools present line numbers a
8
+ * user cross-references against source, so they convert here at the response
9
+ * boundary (#2377).
10
+ *
11
+ * Apply ONLY to a symbol node's 0-based `startLine`/`endLine`. Do NOT apply to:
12
+ * - BasicBlock / CFG `functionStartLine` and PDG statement lines — already
13
+ * 1-based (they use `startPosition.row + 1`);
14
+ * - the internal `sym.startLine + 1` join params that target the 1-based
15
+ * BasicBlock id space;
16
+ * - raw `cypher` results, which pass LadybugDB columns through verbatim and
17
+ * stay 0-based (documented).
18
+ *
19
+ * `undefined`/`null` pass through so optional line fields stay absent.
20
+ */
21
+ export declare function toDisplayLine(zeroBasedLine: number): number;
22
+ export declare function toDisplayLine(zeroBasedLine: number | null | undefined): number | undefined;
@@ -0,0 +1,3 @@
1
+ export function toDisplayLine(zeroBasedLine) {
2
+ return typeof zeroBasedLine === 'number' ? zeroBasedLine + 1 : undefined;
3
+ }