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
@@ -8,7 +8,9 @@
8
8
  * CORS is restricted to localhost, private/LAN networks, and the deployed site.
9
9
  */
10
10
  import express from 'express';
11
+ import { type RegistryEntry } from '../storage/repo-manager.js';
11
12
  import { type GraphNode, type GraphRelationship } from '../_shared/index.js';
13
+ import { JobManager } from './analyze-job.js';
12
14
  /**
13
15
  * Determine whether an HTTP Origin header value is allowed by CORS policy.
14
16
  *
@@ -49,6 +51,34 @@ export declare const registerWebUI: (app: express.Express, staticDir: string | n
49
51
  export declare const writeNdjsonRecord: (res: express.Response, record: GraphStreamRecord, signal?: AbortSignal) => Promise<void>;
50
52
  export declare const getNodeQuery: (table: string, includeContent: boolean) => string;
51
53
  export declare const streamGraphNdjson: (res: express.Response, includeContent?: boolean, signal?: AbortSignal) => Promise<void>;
54
+ /**
55
+ * Mount an SSE progress endpoint for a JobManager.
56
+ * Handles: initial state, terminal events, heartbeat, event IDs, client disconnect.
57
+ *
58
+ * Terminal payloads carry `repoPath` (the analyzed path) alongside the display
59
+ * `repoName` so clients can reconnect by path identity — with duplicate
60
+ * basenames, a name-only reconnect resolves to the first same-named sibling.
61
+ * Exported for unit tests that lock the wire payload shape.
62
+ */
63
+ export declare const mountSSEProgress: (app: express.Express, routePath: string, jm: JobManager) => void;
64
+ /**
65
+ * Resolve a `?repo=` request param against the registry in two tiers:
66
+ *
67
+ * 1. Path claim — any input containing a separator ('/' or '\\', which
68
+ * cover path.sep on every platform) is treated as a path claim and
69
+ * resolved by canonical registry path ONLY. A miss fails closed
70
+ * (null, never a basename fallback) so a stale or wrong path can
71
+ * never silently retarget a same-named sibling repo (#2419).
72
+ * Within this tier, only absolute or Windows-shaped ('\\') claims
73
+ * are worth canonicalizing; relative claims like 'org/name' or
74
+ * './repo' are rejected immediately WITHOUT touching the filesystem
75
+ * — canonicalizing them would run an attacker-influenced
76
+ * CWD-relative realpathSync probe on un-rate-limited GET routes,
77
+ * and no legitimate caller sends relative paths.
78
+ * 2. Name fallback — bare names (no separators) keep the legacy
79
+ * basename/name match for older callers.
80
+ */
81
+ export declare const resolveRegisteredRepoEntry: (repos: RegistryEntry[], repoName?: string) => RegistryEntry | null;
52
82
  /**
53
83
  * Handle a GET /api/file request body. Extracted from createServer's route
54
84
  * registration so it can be unit-tested without spinning up an HTTP server
@@ -12,12 +12,13 @@ import cors from 'cors';
12
12
  import path from 'path';
13
13
  import fs from 'fs/promises';
14
14
  import { createRequire } from 'node:module';
15
- import { loadMeta, listRegisteredRepos, getStoragePath } from '../storage/repo-manager.js';
15
+ import { canonicalizePath, cloneDirBelongsToEntry, loadMeta, saveMeta, listRegisteredRepos, getStoragePath, registryPathEquals, } from '../storage/repo-manager.js';
16
16
  import { executeQuery, executePrepared, executeWithReusedStatement, streamQuery, flushWAL, closeLbug, withLbugDb, isReadOnlyDbError, } from '../core/lbug/lbug-adapter.js';
17
17
  import { isValidQueryParams } from '../core/lbug/query-params.js';
18
18
  import { NODE_TABLES } from '../_shared/index.js';
19
19
  import { searchFTSFromLbug } from '../core/search/bm25-index.js';
20
20
  import { hybridSearch } from '../core/search/hybrid-search.js';
21
+ import { ftsDegradedWarning } from '../core/search/fts-indexes.js';
21
22
  import { LocalBackend } from '../mcp/local/local-backend.js';
22
23
  import { mountMCPEndpoints } from './mcp-http.js';
23
24
  import { fileURLToPath } from 'url';
@@ -380,8 +381,13 @@ export const streamGraphNdjson = async (res, includeContent = false, signal) =>
380
381
  /**
381
382
  * Mount an SSE progress endpoint for a JobManager.
382
383
  * Handles: initial state, terminal events, heartbeat, event IDs, client disconnect.
384
+ *
385
+ * Terminal payloads carry `repoPath` (the analyzed path) alongside the display
386
+ * `repoName` so clients can reconnect by path identity — with duplicate
387
+ * basenames, a name-only reconnect resolves to the first same-named sibling.
388
+ * Exported for unit tests that lock the wire payload shape.
383
389
  */
384
- const mountSSEProgress = (app, routePath, jm) => {
390
+ export const mountSSEProgress = (app, routePath, jm) => {
385
391
  app.get(routePath, (req, res) => {
386
392
  let jobId;
387
393
  try {
@@ -411,6 +417,7 @@ const mountSSEProgress = (app, routePath, jm) => {
411
417
  eventId++;
412
418
  res.write(`id: ${eventId}\nevent: ${job.status}\ndata: ${JSON.stringify({
413
419
  repoName: job.repoName,
420
+ repoPath: job.repoPath,
414
421
  error: job.error,
415
422
  })}\n\n`);
416
423
  res.end();
@@ -434,6 +441,7 @@ const mountSSEProgress = (app, routePath, jm) => {
434
441
  const eventJob = jm.getJob(jobId);
435
442
  res.write(`id: ${eventId}\nevent: ${progress.phase}\ndata: ${JSON.stringify({
436
443
  repoName: eventJob?.repoName,
444
+ repoPath: eventJob?.repoPath,
437
445
  error: eventJob?.error,
438
446
  })}\n\n`);
439
447
  clearInterval(heartbeat);
@@ -476,6 +484,43 @@ const requestedRepo = (req) => {
476
484
  }
477
485
  return undefined;
478
486
  };
487
+ const repoParamBasename = (repoName) => repoName.replace(/\\/g, '/').split('/').filter(Boolean).pop() ?? repoName;
488
+ /**
489
+ * Resolve a `?repo=` request param against the registry in two tiers:
490
+ *
491
+ * 1. Path claim — any input containing a separator ('/' or '\\', which
492
+ * cover path.sep on every platform) is treated as a path claim and
493
+ * resolved by canonical registry path ONLY. A miss fails closed
494
+ * (null, never a basename fallback) so a stale or wrong path can
495
+ * never silently retarget a same-named sibling repo (#2419).
496
+ * Within this tier, only absolute or Windows-shaped ('\\') claims
497
+ * are worth canonicalizing; relative claims like 'org/name' or
498
+ * './repo' are rejected immediately WITHOUT touching the filesystem
499
+ * — canonicalizing them would run an attacker-influenced
500
+ * CWD-relative realpathSync probe on un-rate-limited GET routes,
501
+ * and no legitimate caller sends relative paths.
502
+ * 2. Name fallback — bare names (no separators) keep the legacy
503
+ * basename/name match for older callers.
504
+ */
505
+ export const resolveRegisteredRepoEntry = (repos, repoName) => {
506
+ if (!repoName)
507
+ return repos[0] ?? null;
508
+ const looksLikePath = path.isAbsolute(repoName) || repoName.includes('/') || repoName.includes('\\');
509
+ if (looksLikePath) {
510
+ // Relative path claims fail closed with zero filesystem probes.
511
+ if (!path.isAbsolute(repoName) && !repoName.includes('\\'))
512
+ return null;
513
+ const requestedPath = canonicalizePath(repoName);
514
+ const pathMatch = repos.find((r) => registryPathEquals(canonicalizePath(r.path), requestedPath));
515
+ if (pathMatch)
516
+ return pathMatch;
517
+ return null;
518
+ }
519
+ const normalizedName = repoParamBasename(repoName);
520
+ return (repos.find((r) => r.name === normalizedName) ||
521
+ repos.find((r) => r.name.toLowerCase() === normalizedName.toLowerCase()) ||
522
+ null);
523
+ };
479
524
  /**
480
525
  * Handle a GET /api/file request body. Extracted from createServer's route
481
526
  * registration so it can be unit-tested without spinning up an HTTP server
@@ -678,7 +723,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
678
723
  // Initialize MCP backend (multi-repo, shared across all MCP sessions)
679
724
  const backend = new LocalBackend();
680
725
  await backend.init();
681
- const cleanupMcp = mountMCPEndpoints(app, backend);
726
+ const cleanupMcp = await mountMCPEndpoints(app, backend);
682
727
  const jobManager = new JobManager();
683
728
  // Backstop: remove any upload staging dirs orphaned by a previous crash.
684
729
  void sweepStaleUploads().catch(() => { });
@@ -702,6 +747,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
702
747
  backend,
703
748
  acquireRepoLock,
704
749
  releaseRepoLock,
750
+ closeDbHandle: closeLbug,
705
751
  });
706
752
  /**
707
753
  * Maximum time the hold-queue will wait for an active analysis job to complete.
@@ -712,19 +758,8 @@ export const createServer = async (port, host = '127.0.0.1') => {
712
758
  // Pass `req` to enable early exit if the client disconnects during the hold-queue wait.
713
759
  const resolveRepo = async (repoName, isRetry = false, req) => {
714
760
  const repos = await listRegisteredRepos();
715
- let found = null;
716
- // Normalize: if a full path is passed, extract just the basename.
717
- // e.g. "C:\Users\LENOVO\.gitnexus\repos\todo.txt-cli" -> "todo.txt-cli"
718
- const normalizedName = repoName ? path.basename(repoName) : undefined;
719
- if (normalizedName) {
720
- found =
721
- repos.find((r) => r.name === normalizedName) ||
722
- repos.find((r) => r.name.toLowerCase() === normalizedName.toLowerCase()) ||
723
- null;
724
- }
725
- else if (repos.length > 0) {
726
- found = repos[0]; // default to first repo
727
- }
761
+ const found = resolveRegisteredRepoEntry(repos, repoName);
762
+ const normalizedName = repoName ? repoParamBasename(repoName) : undefined;
728
763
  // If not yet in the registry, check whether a background job is actively cloning or
729
764
  // analyzing this repo. Hold the connection open (up to 5 minutes) until it completes.
730
765
  // We only wait for in-progress jobs ('queued'|'cloning'|'analyzing') — a 'complete' job
@@ -757,7 +792,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
757
792
  if (currentJob.status === 'complete') {
758
793
  await backend.init();
759
794
  const freshRepos = await listRegisteredRepos();
760
- return freshRepos.find((r) => r.name === normalizedName) || null;
795
+ return resolveRegisteredRepoEntry(freshRepos, repoName);
761
796
  }
762
797
  await new Promise((r) => setTimeout(r, 1000));
763
798
  }
@@ -774,7 +809,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
774
809
  logger.debug({ repoName: String(normalizedName).replace(/[\r\n]/g, ' ') }, '[debug] resolveRepo 404, triggering deep init');
775
810
  }
776
811
  await backend.init();
777
- return await resolveRepo(normalizedName, true, req);
812
+ return await resolveRepo(repoName, true, req);
778
813
  }
779
814
  return found;
780
815
  };
@@ -826,6 +861,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
826
861
  res.json(repos.map((r) => ({
827
862
  name: r.name,
828
863
  path: r.path,
864
+ repoPath: r.path,
829
865
  indexedAt: r.indexedAt,
830
866
  lastCommit: r.lastCommit,
831
867
  stats: r.stats,
@@ -836,7 +872,11 @@ export const createServer = async (port, host = '127.0.0.1') => {
836
872
  }
837
873
  });
838
874
  // Get repo info
839
- app.get('/api/repo', async (req, res) => {
875
+ // Rate-limited (CodeQL js/missing-rate-limiting): resolveRepo canonicalizes
876
+ // the attacker-supplied ?repo= param (realpathSync probe for absolute /
877
+ // Windows-shaped claims). Default 60 rpm/IP — web callers hit this route
878
+ // only on connect/switch, never in a polling loop.
879
+ app.get('/api/repo', createRouteLimiter(), async (req, res) => {
840
880
  try {
841
881
  const entry = await resolveRepo(requestedRepo(req), false, req);
842
882
  if (!entry) {
@@ -906,7 +946,10 @@ export const createServer = async (port, host = '127.0.0.1') => {
906
946
  catch {
907
947
  /* repo name not eligible for a clone dir (local repo) */
908
948
  }
909
- if (cloneDir) {
949
+ // Only remove the clone dir when it is *this* entry's path — a local
950
+ // repo registered under the same name would otherwise take a cloned
951
+ // sibling's checkout down with it (see cloneDirBelongsToEntry).
952
+ if (cloneDir && cloneDirBelongsToEntry(cloneDir, entry.path)) {
910
953
  try {
911
954
  const stat = await fs.stat(cloneDir);
912
955
  if (stat.isDirectory()) {
@@ -921,7 +964,10 @@ export const createServer = async (port, host = '127.0.0.1') => {
921
964
  // UPLOAD_ROOT. Drive this off entry.path (not a name-rederived dir) so
922
965
  // a same-named clone is never affected.
923
966
  const resolvedEntry = path.resolve(entry.path);
924
- if (resolvedEntry === UPLOAD_ROOT || resolvedEntry.startsWith(UPLOAD_ROOT + path.sep)) {
967
+ const safeUploadRoot = UPLOAD_ROOT.endsWith(path.sep)
968
+ ? UPLOAD_ROOT
969
+ : UPLOAD_ROOT + path.sep;
970
+ if (resolvedEntry === UPLOAD_ROOT || resolvedEntry.startsWith(safeUploadRoot)) {
925
971
  await fs.rm(resolvedEntry, { recursive: true, force: true }).catch(() => { });
926
972
  }
927
973
  // 3. Unregister from the global registry
@@ -1140,8 +1186,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
1140
1186
  }, { readOnly: true });
1141
1187
  const response = { results: results.searchResults ?? results };
1142
1188
  if (results.ftsAvailable === false) {
1143
- response.warning =
1144
- 'FTS indexes missing — keyword search degraded. Run: gitnexus analyze --repair-fts (or gitnexus analyze --force) to rebuild indexes.';
1189
+ response.warning = ftsDegradedWarning();
1145
1190
  }
1146
1191
  res.json(response);
1147
1192
  }
@@ -1219,7 +1264,8 @@ export const createServer = async (port, host = '127.0.0.1') => {
1219
1264
  const filePath = row.filePath || '';
1220
1265
  const fullPath = path.resolve(repoRoot, filePath);
1221
1266
  // Path traversal guard
1222
- if (!fullPath.startsWith(repoRoot + path.sep) && fullPath !== repoRoot)
1267
+ const safeRepoRoot = repoRoot.endsWith(path.sep) ? repoRoot : repoRoot + path.sep;
1268
+ if (!fullPath.startsWith(safeRepoRoot) && fullPath !== repoRoot)
1223
1269
  continue;
1224
1270
  let content;
1225
1271
  try {
@@ -1477,16 +1523,14 @@ export const createServer = async (port, host = '127.0.0.1') => {
1477
1523
  status: 'analyzing',
1478
1524
  progress: { phase: 'analyzing', percent: 0, message: 'Starting embedding generation...' },
1479
1525
  });
1526
+ const embedController = new AbortController();
1527
+ embedJobManager.registerAbortController(job.id, embedController);
1480
1528
  // 30-minute timeout for embedding jobs (same as analyze jobs)
1481
1529
  const EMBED_TIMEOUT_MS = 30 * 60 * 1000;
1482
1530
  const embedTimeout = setTimeout(() => {
1483
1531
  const current = embedJobManager.getJob(job.id);
1484
1532
  if (current && current.status !== 'complete' && current.status !== 'failed') {
1485
- releaseRepoLock(repoLockPath);
1486
- embedJobManager.updateJob(job.id, {
1487
- status: 'failed',
1488
- error: 'Embedding timed out (30 minute limit)',
1489
- });
1533
+ embedJobManager.cancelJob(job.id, 'Embedding timed out (30 minute limit)');
1490
1534
  }
1491
1535
  }, EMBED_TIMEOUT_MS);
1492
1536
  // Run embedding pipeline asynchronously
@@ -1495,6 +1539,36 @@ export const createServer = async (port, host = '127.0.0.1') => {
1495
1539
  const lbugPath = path.join(entry.storagePath, 'lbug');
1496
1540
  await withLbugDb(lbugPath, async () => {
1497
1541
  const { runEmbeddingPipeline } = await import('../core/embeddings/embedding-pipeline.js');
1542
+ const { resolveEmbeddingIdentity } = await import('../core/embeddings/embedding-identity.js');
1543
+ const embeddingIdentity = resolveEmbeddingIdentity();
1544
+ let embeddingMeta = await loadMeta(entry.storagePath);
1545
+ if (!embeddingMeta) {
1546
+ throw new Error('Repository metadata is missing; run gitnexus analyze first');
1547
+ }
1548
+ const priorCheckpoint = embeddingMeta.embeddingCheckpoint;
1549
+ if (priorCheckpoint && priorCheckpoint.provider !== embeddingIdentity.provider) {
1550
+ throw new Error('Cannot resume embedding checkpoint: the embedding provider configuration differs.');
1551
+ }
1552
+ if (priorCheckpoint &&
1553
+ (priorCheckpoint.model !== embeddingIdentity.model ||
1554
+ priorCheckpoint.dimensions !== embeddingIdentity.dimensions)) {
1555
+ throw new Error(`Cannot resume embedding checkpoint: it uses ${priorCheckpoint.model} at ` +
1556
+ `${priorCheckpoint.dimensions} dimensions, but this run resolves ` +
1557
+ `${embeddingIdentity.model} at ${embeddingIdentity.dimensions}.`);
1558
+ }
1559
+ const forceReembedNodeIds = new Set(priorCheckpoint?.pendingNodeIds ?? []);
1560
+ const saveEmbeddingCheckpoint = async (checkpoint, pendingNodeIds) => {
1561
+ embeddingMeta = {
1562
+ ...embeddingMeta,
1563
+ embeddingCheckpoint: {
1564
+ at: new Date().toISOString(),
1565
+ ...checkpoint,
1566
+ ...embeddingIdentity,
1567
+ pendingNodeIds,
1568
+ },
1569
+ };
1570
+ await saveMeta(entry.storagePath, embeddingMeta);
1571
+ };
1498
1572
  // Fetch existing content hashes for incremental embedding.
1499
1573
  // Delegated to lbug-adapter which owns the DB query logic and legacy-fallback handling.
1500
1574
  const { fetchExistingEmbeddingHashes } = await import('../core/lbug/lbug-adapter.js');
@@ -1520,15 +1594,25 @@ export const createServer = async (port, host = '127.0.0.1') => {
1520
1594
  });
1521
1595
  }, {}, // config: use defaults
1522
1596
  undefined, // skipNodeIds
1523
- existingEmbeddings);
1597
+ existingEmbeddings, {
1598
+ signal: embedController.signal,
1599
+ forceReembedNodeIds,
1600
+ onCheckpointWindowStart: async ({ nodeIds, ...checkpoint }) => {
1601
+ await saveEmbeddingCheckpoint(checkpoint, nodeIds);
1602
+ },
1603
+ onCheckpoint: async (checkpoint) => {
1604
+ await flushWAL();
1605
+ await saveEmbeddingCheckpoint(checkpoint, []);
1606
+ },
1607
+ });
1524
1608
  // Flush WAL so subsequent /api/search requests see the new
1525
1609
  // embeddings immediately (#1149). In the CLI path closeLbug()
1526
1610
  // handles this during process exit, but the server keeps the
1527
1611
  // connection open for other routes — a CHECKPOINT is enough.
1528
1612
  await flushWAL();
1613
+ embeddingMeta = { ...embeddingMeta, embeddingCheckpoint: undefined };
1614
+ await saveMeta(entry.storagePath, embeddingMeta);
1529
1615
  });
1530
- clearTimeout(embedTimeout);
1531
- releaseRepoLock(repoLockPath);
1532
1616
  // Don't overwrite 'failed' if the job was cancelled while the pipeline was running
1533
1617
  const current = embedJobManager.getJob(job.id);
1534
1618
  if (!current || current.status !== 'failed') {
@@ -1536,8 +1620,6 @@ export const createServer = async (port, host = '127.0.0.1') => {
1536
1620
  }
1537
1621
  }
1538
1622
  catch (err) {
1539
- clearTimeout(embedTimeout);
1540
- releaseRepoLock(repoLockPath);
1541
1623
  const current = embedJobManager.getJob(job.id);
1542
1624
  if (!current || current.status !== 'failed') {
1543
1625
  embedJobManager.updateJob(job.id, {
@@ -1546,6 +1628,10 @@ export const createServer = async (port, host = '127.0.0.1') => {
1546
1628
  });
1547
1629
  }
1548
1630
  }
1631
+ finally {
1632
+ clearTimeout(embedTimeout);
1633
+ releaseRepoLock(repoLockPath);
1634
+ }
1549
1635
  })();
1550
1636
  res.status(202).json({ jobId: job.id, status: 'analyzing' });
1551
1637
  }
@@ -9,4 +9,4 @@
9
9
  */
10
10
  import type { Express } from 'express';
11
11
  import type { LocalBackend } from '../mcp/local/local-backend.js';
12
- export declare function mountMCPEndpoints(app: Express, backend: LocalBackend): () => Promise<void>;
12
+ export declare function mountMCPEndpoints(app: Express, backend: LocalBackend): Promise<() => Promise<void>>;
@@ -8,9 +8,11 @@
8
8
  * Used by server/api.ts to wire up the full web server.
9
9
  */
10
10
  import { createStreamableHttpHandler } from '../mcp/http-transport.js';
11
+ import { createMcpRepositoryPolicy } from '../mcp/repository-policy.js';
11
12
  import { logger } from '../core/logger.js';
12
- export function mountMCPEndpoints(app, backend) {
13
- const { handler, cleanup } = createStreamableHttpHandler(backend);
13
+ export async function mountMCPEndpoints(app, backend) {
14
+ const repositoryPolicy = await createMcpRepositoryPolicy(backend);
15
+ const { handler, cleanup } = createStreamableHttpHandler(backend, { repositoryPolicy });
14
16
  app.all('/api/mcp', (req, res) => {
15
17
  void handler(req, res).catch((err) => {
16
18
  logger.error({ err }, 'MCP HTTP request failed:');
@@ -65,7 +65,8 @@ export function resolveContainedDest(stageRoot, rel) {
65
65
  }
66
66
  const dest = path.resolve(stageRoot, segments.join(path.sep));
67
67
  // Suffix path.sep so a sibling prefix (/sandbox-evil vs /sandbox) can't pass.
68
- if (dest !== stageRoot && !dest.startsWith(stageRoot + path.sep)) {
68
+ const safePrefix = stageRoot.endsWith(path.sep) ? stageRoot : stageRoot + path.sep;
69
+ if (dest !== stageRoot && !dest.startsWith(safePrefix)) {
69
70
  throw new BadRequestError('Upload path escapes the sandbox');
70
71
  }
71
72
  return dest;
@@ -77,7 +77,8 @@ export function assertSafePath(rawPath, root) {
77
77
  }
78
78
  const resolvedRoot = path.resolve(root);
79
79
  const fullPath = path.resolve(resolvedRoot, rawPath);
80
- if (fullPath !== resolvedRoot && !fullPath.startsWith(resolvedRoot + path.sep)) {
80
+ const safePrefix = resolvedRoot.endsWith(path.sep) ? resolvedRoot : resolvedRoot + path.sep;
81
+ if (fullPath !== resolvedRoot && !fullPath.startsWith(safePrefix)) {
81
82
  throw new ForbiddenError('Path traversal denied');
82
83
  }
83
84
  return fullPath;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * True when the working tree has uncommitted changes that analyze would
3
+ * re-index, even at a matching HEAD. Excludes the paths GitNexus writes during
4
+ * analyze (.gitnexus/, .claude/, .cursor/, AGENTS.md, CLAUDE.md) so its own
5
+ * output never counts as dirty (regression vs PR #1233 behavior). Conservative
6
+ * on any git failure. Shared so `analyze`'s fast-path gate and `status`'s
7
+ * freshness report agree on what "dirty" means.
8
+ */
9
+ export declare const isWorkingTreeDirty: (repoPath: string) => boolean;
1
10
  export declare const isGitRepo: (repoPath: string) => boolean;
2
11
  export declare const getCurrentCommit: (repoPath: string) => string;
3
12
  /**
@@ -56,6 +65,28 @@ export declare const getGitRoot: (fromPath: string) => string | null;
56
65
  * path if the caller later resolved it from a different directory.
57
66
  */
58
67
  export declare const getCanonicalRepoRoot: (fromPath: string) => string | null;
68
+ /**
69
+ * Path to the repo's `$GIT_COMMON_DIR/info/exclude` file — git's own
70
+ * per-repo, untracked exclude list (same tier as `.gitignore` in
71
+ * precedence, but never committed, so it works even when the caller has
72
+ * no write access to the repo's tracked content). Shared across every
73
+ * linked worktree of a repo, matching git's own resolution (#2606).
74
+ *
75
+ * Returns `null` when `fromPath` is not inside a git repository or `git`
76
+ * is unavailable; callers should treat that the same as "no file".
77
+ */
78
+ export declare const getGitInfoExcludePath: (fromPath: string) => string | null;
79
+ /**
80
+ * Path to git's own global, all-repos ignore file: the value of
81
+ * `core.excludesFile` (any config scope — system/global/local, resolved
82
+ * the same way `git` itself would from `fromPath`), or git's documented
83
+ * default of `$XDG_CONFIG_HOME/git/ignore` when unset (gitignore(5)).
84
+ * Lowest-precedence source, mirroring git's own behavior (#2606).
85
+ *
86
+ * Never throws: an unset key or unavailable `git` falls through to the
87
+ * default path, which is always computable without `git`.
88
+ */
89
+ export declare const getCoreExcludesFilePath: (fromPath: string) => string;
59
90
  /**
60
91
  * Resolve `fromPath` to the directory whose basename should drive the
61
92
  * registry name (#1259) — the *identity root*. Three outcomes:
@@ -1,8 +1,44 @@
1
- import { execSync } from 'child_process';
1
+ import { execFileSync, execSync } from 'child_process';
2
2
  import { statSync } from 'fs';
3
3
  import path from 'path';
4
+ import os from 'os';
4
5
  // Git utilities for repository detection, commit tracking, and diff analysis
5
6
  const chompGitOutput = (value) => value.toString().replace(/\r?\n$/, '');
7
+ /**
8
+ * True when the working tree has uncommitted changes that analyze would
9
+ * re-index, even at a matching HEAD. Excludes the paths GitNexus writes during
10
+ * analyze (.gitnexus/, .claude/, .cursor/, AGENTS.md, CLAUDE.md) so its own
11
+ * output never counts as dirty (regression vs PR #1233 behavior). Conservative
12
+ * on any git failure. Shared so `analyze`'s fast-path gate and `status`'s
13
+ * freshness report agree on what "dirty" means.
14
+ */
15
+ export const isWorkingTreeDirty = (repoPath) => {
16
+ try {
17
+ const out = execFileSync('git', [
18
+ 'status',
19
+ '--porcelain',
20
+ '--',
21
+ '.',
22
+ ':(exclude).gitnexus',
23
+ ':(exclude).gitnexus/**',
24
+ ':(exclude).claude',
25
+ ':(exclude).claude/**',
26
+ ':(exclude).cursor',
27
+ ':(exclude).cursor/**',
28
+ ':(exclude)AGENTS.md',
29
+ ':(exclude)CLAUDE.md',
30
+ ], {
31
+ cwd: repoPath,
32
+ stdio: ['ignore', 'pipe', 'ignore'],
33
+ windowsHide: true,
34
+ encoding: 'utf8',
35
+ });
36
+ return out.trim().length > 0;
37
+ }
38
+ catch {
39
+ return true; // conservative on git failure
40
+ }
41
+ };
6
42
  export const isGitRepo = (repoPath) => {
7
43
  try {
8
44
  execSync('git rev-parse --is-inside-work-tree', {
@@ -163,6 +199,80 @@ export const getCanonicalRepoRoot = (fromPath) => {
163
199
  return null;
164
200
  }
165
201
  };
202
+ // getGitInfoExcludePath/getCoreExcludesFilePath are called once per repo
203
+ // PER language/contract extractor during group sync (#2606) — an N-repo
204
+ // group fans out to 6+ extractors each calling these, so an uncached
205
+ // execSync per call turns into O(extractors × repos) blocking subprocess
206
+ // spawns. Both resolve to the same value for the same fromPath for the
207
+ // life of the process (git config/exclude files don't change mid-run), so
208
+ // memoize by fromPath. ponytail: process-lifetime cache, never invalidated
209
+ // — fine for one-shot CLI runs; the long-lived MCP server would need a
210
+ // TTL or explicit invalidation if a user edits core.excludesFile mid-session.
211
+ const gitInfoExcludePathCache = new Map();
212
+ const coreExcludesFilePathCache = new Map();
213
+ /**
214
+ * Path to the repo's `$GIT_COMMON_DIR/info/exclude` file — git's own
215
+ * per-repo, untracked exclude list (same tier as `.gitignore` in
216
+ * precedence, but never committed, so it works even when the caller has
217
+ * no write access to the repo's tracked content). Shared across every
218
+ * linked worktree of a repo, matching git's own resolution (#2606).
219
+ *
220
+ * Returns `null` when `fromPath` is not inside a git repository or `git`
221
+ * is unavailable; callers should treat that the same as "no file".
222
+ */
223
+ export const getGitInfoExcludePath = (fromPath) => {
224
+ const cached = gitInfoExcludePathCache.get(fromPath);
225
+ if (cached !== undefined)
226
+ return cached;
227
+ let result;
228
+ try {
229
+ const commonDir = chompGitOutput(execSync('git rev-parse --path-format=absolute --git-common-dir', {
230
+ cwd: fromPath,
231
+ stdio: ['ignore', 'pipe', 'ignore'],
232
+ windowsHide: true,
233
+ }));
234
+ result = commonDir ? path.join(path.resolve(commonDir), 'info', 'exclude') : null;
235
+ }
236
+ catch {
237
+ result = null;
238
+ }
239
+ gitInfoExcludePathCache.set(fromPath, result);
240
+ return result;
241
+ };
242
+ /**
243
+ * Path to git's own global, all-repos ignore file: the value of
244
+ * `core.excludesFile` (any config scope — system/global/local, resolved
245
+ * the same way `git` itself would from `fromPath`), or git's documented
246
+ * default of `$XDG_CONFIG_HOME/git/ignore` when unset (gitignore(5)).
247
+ * Lowest-precedence source, mirroring git's own behavior (#2606).
248
+ *
249
+ * Never throws: an unset key or unavailable `git` falls through to the
250
+ * default path, which is always computable without `git`.
251
+ */
252
+ export const getCoreExcludesFilePath = (fromPath) => {
253
+ const cached = coreExcludesFilePathCache.get(fromPath);
254
+ if (cached !== undefined)
255
+ return cached;
256
+ let result;
257
+ try {
258
+ const configured = chompGitOutput(execSync('git config --get --type=path core.excludesFile', {
259
+ cwd: fromPath,
260
+ stdio: ['ignore', 'pipe', 'ignore'],
261
+ windowsHide: true,
262
+ }));
263
+ if (configured)
264
+ result = configured;
265
+ }
266
+ catch {
267
+ // Unset, or git unavailable — fall through to git's documented default.
268
+ }
269
+ if (!result) {
270
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
271
+ result = path.join(xdgConfigHome, 'git', 'ignore');
272
+ }
273
+ coreExcludesFilePathCache.set(fromPath, result);
274
+ return result;
275
+ };
166
276
  /**
167
277
  * Resolve `fromPath` to the directory whose basename should drive the
168
278
  * registry name (#1259) — the *identity root*. Three outcomes:
@@ -52,7 +52,13 @@ import { fileURLToPath } from 'url';
52
52
  // the main thread (the #1983 OOM). Because the two stores share this version,
53
53
  // any future change to the `ParsedFile` serialization shape MUST bump
54
54
  // SCHEMA_BUMP so both invalidate in lockstep.
55
- const SCHEMA_BUMP = 10; // PR #2200: Property nodes gained `rawDeclaredType` + `annotations` (Spring DI); warm caches must invalidate or the DI phase silently no-ops on replayed pre-upgrade nodes
55
+ // v20: Java/Kotlin capture side-channels persist package and class-annotation
56
+ // facts for shared Spring Bean resolution.
57
+ // v19: Java enum constant bodies emit E$N Class nodes; anonymous naming uses
58
+ // JLS 13.1 immediate-host chains (#2555).
59
+ // v18: Worker$N anonymous bodies. v17: callable-value-flow operand identity.
60
+ // v16: direct callee identity.
61
+ const SCHEMA_BUMP = 20;
56
62
  const GITNEXUS_PKG_VERSION = (() => {
57
63
  try {
58
64
  // package.json sits at gitnexus/package.json — two levels up from
@@ -100,6 +100,14 @@ export declare const persistParsedFileShardSync: (storagePath: string, shardId:
100
100
  export declare const loadParsedFilesForPaths: (storagePath: string, wantPaths: ReadonlySet<string>) => Promise<Map<string, ParsedFile>>;
101
101
  /** Durable store dir — a sibling of `parsedfile-store/`, NEVER cleared per run. */
102
102
  export declare const getDurableParsedFileDir: (storagePath: string) => string;
103
+ /**
104
+ * Start a fresh durable generation for one content-addressed parse chunk.
105
+ * The main thread calls this once before dispatching a cache miss, before any
106
+ * worker can write that chunk. Recreating the directory immediately keeps the
107
+ * worker-side mkdir memoization valid while preventing old worker shard names
108
+ * from accumulating across analyses.
109
+ */
110
+ export declare const prepareDurableParsedFileChunk: (durableDir: string, chunkHash: string) => Promise<void>;
103
111
  /**
104
112
  * Synchronous durable-shard writer for use INSIDE a parse worker, alongside
105
113
  * {@link persistParsedFileShardSync}. Writes the SAME bytes to a content-addressed