gitnexus 1.6.11-rc.8 → 1.6.11

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 (531) hide show
  1. package/README.md +95 -26
  2. package/dist/_shared/graph/types.d.ts +81 -2
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
  5. package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
  6. package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
  7. package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
  8. package/dist/_shared/language-detection.d.ts.map +1 -1
  9. package/dist/_shared/language-detection.js +2 -0
  10. package/dist/_shared/language-detection.js.map +1 -1
  11. package/dist/_shared/languages.d.ts +2 -1
  12. package/dist/_shared/languages.d.ts.map +1 -1
  13. package/dist/_shared/languages.js +1 -0
  14. package/dist/_shared/languages.js.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.d.ts +2 -2
  16. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  17. package/dist/_shared/lbug/schema-constants.js +4 -0
  18. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  19. package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
  20. package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -0
  21. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  22. package/dist/_shared/scope-resolution/language-classification.d.ts +3 -0
  23. package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
  24. package/dist/_shared/scope-resolution/language-classification.js +4 -0
  25. package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
  26. package/dist/_shared/scope-resolution/reference-site.d.ts +10 -0
  27. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  28. package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
  29. package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
  30. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  31. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  32. package/dist/_shared/scope-resolution/types.d.ts +15 -0
  33. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  34. package/dist/cli/ai-context.d.ts +4 -0
  35. package/dist/cli/ai-context.js +90 -14
  36. package/dist/cli/analyze-config.js +14 -0
  37. package/dist/cli/analyze-options.d.ts +14 -0
  38. package/dist/cli/analyze-watch.d.ts +20 -0
  39. package/dist/cli/analyze-watch.js +434 -0
  40. package/dist/cli/analyze.js +27 -9
  41. package/dist/cli/auto-sync.d.ts +1 -0
  42. package/dist/cli/auto-sync.js +107 -0
  43. package/dist/cli/command-banner.d.ts +15 -0
  44. package/dist/cli/command-banner.js +42 -0
  45. package/dist/cli/detect-changes-format.js +21 -0
  46. package/dist/cli/doctor.d.ts +7 -0
  47. package/dist/cli/doctor.js +14 -0
  48. package/dist/cli/group.js +7 -1
  49. package/dist/cli/help-i18n.js +4 -0
  50. package/dist/cli/i18n/en.d.ts +18 -3
  51. package/dist/cli/i18n/en.js +18 -3
  52. package/dist/cli/i18n/resources.d.ts +33 -3
  53. package/dist/cli/i18n/zh-CN.d.ts +15 -0
  54. package/dist/cli/i18n/zh-CN.js +18 -3
  55. package/dist/cli/index.js +34 -7
  56. package/dist/cli/mcp.d.ts +15 -0
  57. package/dist/cli/mcp.js +44 -0
  58. package/dist/cli/optional-grammars.d.ts +3 -2
  59. package/dist/cli/optional-grammars.js +19 -3
  60. package/dist/cli/setup.js +41 -15
  61. package/dist/cli/update-notice.d.ts +34 -0
  62. package/dist/cli/update-notice.js +91 -0
  63. package/dist/cli/update.d.ts +21 -0
  64. package/dist/cli/update.js +93 -0
  65. package/dist/cli/watch.d.ts +1 -20
  66. package/dist/cli/watch.js +5 -371
  67. package/dist/core/analysis-feature-registry.d.ts +2 -0
  68. package/dist/core/analysis-feature-registry.js +15 -0
  69. package/dist/core/analyzer-identity.js +21 -3
  70. package/dist/core/auto-sync/analysis-worker-launch.d.ts +30 -0
  71. package/dist/core/auto-sync/analysis-worker-launch.js +166 -0
  72. package/dist/core/auto-sync/config.d.ts +33 -0
  73. package/dist/core/auto-sync/config.js +320 -0
  74. package/dist/core/auto-sync/index.d.ts +6 -0
  75. package/dist/core/auto-sync/index.js +6 -0
  76. package/dist/core/auto-sync/path-security.d.ts +9 -0
  77. package/dist/core/auto-sync/path-security.js +251 -0
  78. package/dist/core/auto-sync/repo.d.ts +1 -0
  79. package/dist/core/auto-sync/repo.js +6 -0
  80. package/dist/core/auto-sync/runner.d.ts +44 -0
  81. package/dist/core/auto-sync/runner.js +428 -0
  82. package/dist/core/auto-sync/starter.d.ts +50 -0
  83. package/dist/core/auto-sync/starter.js +497 -0
  84. package/dist/core/auto-sync/state.d.ts +37 -0
  85. package/dist/core/auto-sync/state.js +119 -0
  86. package/dist/core/group/config-parser.js +8 -1
  87. package/dist/core/group/cross-impact.d.ts +3 -0
  88. package/dist/core/group/cross-impact.js +36 -4
  89. package/dist/core/group/extractors/http-patterns/java.js +22 -8
  90. package/dist/core/group/extractors/http-patterns/kotlin.js +86 -31
  91. package/dist/core/group/extractors/http-patterns/node.js +145 -8
  92. package/dist/core/group/extractors/http-patterns/python.js +11 -7
  93. package/dist/core/group/extractors/http-route-extractor.js +63 -17
  94. package/dist/core/group/extractors/java-workspace-extractor.js +244 -31
  95. package/dist/core/group/group-lock.js +5 -6
  96. package/dist/core/group/normalization.d.ts +38 -1
  97. package/dist/core/group/normalization.js +59 -3
  98. package/dist/core/group/service.d.ts +11 -0
  99. package/dist/core/group/service.js +13 -1
  100. package/dist/core/group/storage.js +2 -2
  101. package/dist/core/group/sync.d.ts +24 -1
  102. package/dist/core/group/sync.js +46 -8
  103. package/dist/core/group/types.d.ts +13 -0
  104. package/dist/core/incremental/derived-writeback.d.ts +36 -0
  105. package/dist/core/incremental/derived-writeback.js +68 -0
  106. package/dist/core/incremental/spring-config-drift.d.ts +12 -0
  107. package/dist/core/incremental/spring-config-drift.js +46 -0
  108. package/dist/core/incremental/subgraph-extract.d.ts +7 -4
  109. package/dist/core/incremental/subgraph-extract.js +30 -5
  110. package/dist/core/ingestion/asyncapi/document.d.ts +226 -0
  111. package/dist/core/ingestion/asyncapi/document.js +758 -0
  112. package/dist/core/ingestion/asyncapi/protocol.d.ts +79 -0
  113. package/dist/core/ingestion/asyncapi/protocol.js +203 -0
  114. package/dist/core/ingestion/call-extractors/configs/zig.d.ts +2 -0
  115. package/dist/core/ingestion/call-extractors/configs/zig.js +4 -0
  116. package/dist/core/ingestion/call-extractors/zig-static-gating.d.ts +100 -0
  117. package/dist/core/ingestion/call-extractors/zig-static-gating.js +319 -0
  118. package/dist/core/ingestion/call-processor.js +3 -1
  119. package/dist/core/ingestion/class-extractors/configs/zig.d.ts +2 -0
  120. package/dist/core/ingestion/class-extractors/configs/zig.js +32 -0
  121. package/dist/core/ingestion/class-extractors/generic.js +4 -1
  122. package/dist/core/ingestion/class-types.d.ts +6 -2
  123. package/dist/core/ingestion/destination-key.d.ts +59 -0
  124. package/dist/core/ingestion/destination-key.js +61 -0
  125. package/dist/core/ingestion/entry-point-scoring.d.ts +6 -2
  126. package/dist/core/ingestion/entry-point-scoring.js +8 -44
  127. package/dist/core/ingestion/export-detection.d.ts +37 -0
  128. package/dist/core/ingestion/export-detection.js +60 -0
  129. package/dist/core/ingestion/field-extractors/configs/zig.d.ts +8 -0
  130. package/dist/core/ingestion/field-extractors/configs/zig.js +49 -0
  131. package/dist/core/ingestion/field-extractors/generic.d.ts +1 -1
  132. package/dist/core/ingestion/field-extractors/generic.js +12 -1
  133. package/dist/core/ingestion/frameworks/spring/actuator-runtime.d.ts +26 -0
  134. package/dist/core/ingestion/frameworks/spring/actuator-runtime.js +843 -0
  135. package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +5 -0
  136. package/dist/core/ingestion/frameworks/spring/analysis-features.js +9 -0
  137. package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +8 -1
  138. package/dist/core/ingestion/frameworks/spring/argument-facts.d.ts +80 -0
  139. package/dist/core/ingestion/frameworks/spring/argument-facts.js +85 -0
  140. package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +1 -0
  141. package/dist/core/ingestion/frameworks/spring/config-bindings.js +2 -1
  142. package/dist/core/ingestion/frameworks/spring/destinations.d.ts +539 -0
  143. package/dist/core/ingestion/frameworks/spring/destinations.js +840 -0
  144. package/dist/core/ingestion/frameworks/spring/dynamic-lookups.d.ts +22 -0
  145. package/dist/core/ingestion/frameworks/spring/dynamic-lookups.js +124 -0
  146. package/dist/core/ingestion/frameworks/spring/message-producers.d.ts +78 -0
  147. package/dist/core/ingestion/frameworks/spring/message-producers.js +90 -0
  148. package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +29 -0
  149. package/dist/core/ingestion/frameworks/spring/vendor-prefixes.d.ts +7 -0
  150. package/dist/core/ingestion/frameworks/spring/vendor-prefixes.js +22 -0
  151. package/dist/core/ingestion/import-resolvers/configs/zig.d.ts +13 -0
  152. package/dist/core/ingestion/import-resolvers/configs/zig.js +26 -0
  153. package/dist/core/ingestion/import-resolvers/zig.d.ts +34 -0
  154. package/dist/core/ingestion/import-resolvers/zig.js +193 -0
  155. package/dist/core/ingestion/language-config.d.ts +177 -0
  156. package/dist/core/ingestion/language-config.js +719 -0
  157. package/dist/core/ingestion/language-provider.d.ts +178 -1
  158. package/dist/core/ingestion/language-provider.js +22 -0
  159. package/dist/core/ingestion/languages/csharp/razor-view-components.d.ts +62 -0
  160. package/dist/core/ingestion/languages/csharp/razor-view-components.js +954 -0
  161. package/dist/core/ingestion/languages/csharp/resolution-config.d.ts +3 -0
  162. package/dist/core/ingestion/languages/csharp/resolution-config.js +6 -1
  163. package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -0
  164. package/dist/core/ingestion/languages/index.d.ts +1 -0
  165. package/dist/core/ingestion/languages/index.js +2 -0
  166. package/dist/core/ingestion/languages/java/analysis-features.d.ts +1 -1
  167. package/dist/core/ingestion/languages/java/analysis-features.js +14 -6
  168. package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +8 -0
  169. package/dist/core/ingestion/languages/java/capture-side-channel.js +34 -0
  170. package/dist/core/ingestion/languages/java/captures.js +22 -1
  171. package/dist/core/ingestion/languages/java/lombok-synthesizer.d.ts +42 -0
  172. package/dist/core/ingestion/languages/java/lombok-synthesizer.js +439 -0
  173. package/dist/core/ingestion/languages/java/scope-resolver.js +2 -0
  174. package/dist/core/ingestion/languages/java/spring-actuator.d.ts +2 -0
  175. package/dist/core/ingestion/languages/java/spring-actuator.js +62 -0
  176. package/dist/core/ingestion/languages/java/spring-di.d.ts +17 -1
  177. package/dist/core/ingestion/languages/java/spring-di.js +44 -2
  178. package/dist/core/ingestion/languages/java/spring-dynamic-lookup.d.ts +8 -0
  179. package/dist/core/ingestion/languages/java/spring-dynamic-lookup.js +62 -0
  180. package/dist/core/ingestion/languages/java/spring-message-producers.d.ts +20 -0
  181. package/dist/core/ingestion/languages/java/spring-message-producers.js +83 -0
  182. package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +11 -1
  183. package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +13 -3
  184. package/dist/core/ingestion/languages/java.js +18 -8
  185. package/dist/core/ingestion/languages/jvm/accessor-synthesis.d.ts +99 -0
  186. package/dist/core/ingestion/languages/jvm/accessor-synthesis.js +173 -0
  187. package/dist/core/ingestion/languages/jvm/beanspec.d.ts +17 -0
  188. package/dist/core/ingestion/languages/jvm/beanspec.js +42 -0
  189. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
  190. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +50 -0
  191. package/dist/core/ingestion/languages/kotlin/captures.js +24 -1
  192. package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.d.ts +26 -0
  193. package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.js +417 -0
  194. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +4 -0
  195. package/dist/core/ingestion/languages/kotlin/spring-actuator.d.ts +4 -0
  196. package/dist/core/ingestion/languages/kotlin/spring-actuator.js +172 -0
  197. package/dist/core/ingestion/languages/kotlin/spring-config-bindings.d.ts +18 -0
  198. package/dist/core/ingestion/languages/kotlin/spring-config-bindings.js +411 -0
  199. package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +51 -1
  200. package/dist/core/ingestion/languages/kotlin/spring-di.js +86 -6
  201. package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.d.ts +8 -0
  202. package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.js +77 -0
  203. package/dist/core/ingestion/languages/kotlin/spring-message-producers.d.ts +17 -0
  204. package/dist/core/ingestion/languages/kotlin/spring-message-producers.js +119 -0
  205. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +16 -0
  206. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +77 -2
  207. package/dist/core/ingestion/languages/kotlin.js +24 -0
  208. package/dist/core/ingestion/languages/python.js +2 -0
  209. package/dist/core/ingestion/languages/rust/query.js +8 -8
  210. package/dist/core/ingestion/languages/zig/captures.d.ts +260 -0
  211. package/dist/core/ingestion/languages/zig/captures.js +2070 -0
  212. package/dist/core/ingestion/languages/zig/index.d.ts +4 -0
  213. package/dist/core/ingestion/languages/zig/index.js +4 -0
  214. package/dist/core/ingestion/languages/zig/interpret.d.ts +36 -0
  215. package/dist/core/ingestion/languages/zig/interpret.js +176 -0
  216. package/dist/core/ingestion/languages/zig/query.d.ts +3 -0
  217. package/dist/core/ingestion/languages/zig/query.js +426 -0
  218. package/dist/core/ingestion/languages/zig/range-binding.d.ts +37 -0
  219. package/dist/core/ingestion/languages/zig/range-binding.js +373 -0
  220. package/dist/core/ingestion/languages/zig/scope-resolver.d.ts +12 -0
  221. package/dist/core/ingestion/languages/zig/scope-resolver.js +58 -0
  222. package/dist/core/ingestion/languages/zig/simple-hooks.d.ts +25 -0
  223. package/dist/core/ingestion/languages/zig/simple-hooks.js +143 -0
  224. package/dist/core/ingestion/languages/zig.d.ts +32 -0
  225. package/dist/core/ingestion/languages/zig.js +130 -0
  226. package/dist/core/ingestion/method-extractors/configs/zig.d.ts +2 -0
  227. package/dist/core/ingestion/method-extractors/configs/zig.js +120 -0
  228. package/dist/core/ingestion/method-extractors/generic.js +16 -4
  229. package/dist/core/ingestion/method-types.d.ts +10 -4
  230. package/dist/core/ingestion/model/field-registry.d.ts +3 -3
  231. package/dist/core/ingestion/model/field-registry.js +11 -7
  232. package/dist/core/ingestion/model/method-registry.d.ts +3 -3
  233. package/dist/core/ingestion/model/method-registry.js +13 -8
  234. package/dist/core/ingestion/model/registration-table.js +3 -0
  235. package/dist/core/ingestion/model/type-registry.js +8 -4
  236. package/dist/core/ingestion/pipeline-phases/di.js +47 -14
  237. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  238. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  239. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +7 -1
  240. package/dist/core/ingestion/pipeline-phases/parse-impl.js +79 -91
  241. package/dist/core/ingestion/pipeline-phases/parse.d.ts +17 -0
  242. package/dist/core/ingestion/pipeline-phases/processes.d.ts +2 -1
  243. package/dist/core/ingestion/pipeline-phases/processes.js +39 -4
  244. package/dist/core/ingestion/pipeline-phases/routes.js +27 -18
  245. package/dist/core/ingestion/pipeline-phases/runner.d.ts +4 -1
  246. package/dist/core/ingestion/pipeline-phases/runner.js +34 -14
  247. package/dist/core/ingestion/pipeline-phases/scan.js +82 -1
  248. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +2 -0
  249. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +8 -0
  250. package/dist/core/ingestion/pipeline-phases/spring-destinations.d.ts +123 -0
  251. package/dist/core/ingestion/pipeline-phases/spring-destinations.js +688 -0
  252. package/dist/core/ingestion/pipeline.d.ts +30 -1
  253. package/dist/core/ingestion/pipeline.js +52 -14
  254. package/dist/core/ingestion/resolve-references.js +5 -0
  255. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +16 -0
  256. package/dist/core/ingestion/route-extractors/constant-resolver.js +10 -0
  257. package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +27 -1
  258. package/dist/core/ingestion/route-extractors/java-const-resolver.js +161 -13
  259. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +12 -18
  260. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +214 -33
  261. package/dist/core/ingestion/route-extractors/kotlin-spring.d.ts +13 -0
  262. package/dist/core/ingestion/route-extractors/kotlin-spring.js +259 -0
  263. package/dist/core/ingestion/route-extractors/python-decorator-handler.d.ts +6 -0
  264. package/dist/core/ingestion/route-extractors/python-decorator-handler.js +16 -0
  265. package/dist/core/ingestion/route-extractors/spring-shared.d.ts +30 -1
  266. package/dist/core/ingestion/route-extractors/spring-shared.js +77 -9
  267. package/dist/core/ingestion/route-extractors/spring.js +9 -5
  268. package/dist/core/ingestion/scope-extractor.js +8 -0
  269. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +62 -0
  270. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +4 -0
  271. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +2 -0
  272. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +28 -0
  273. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +11 -2
  274. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +23 -2
  275. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +24 -3
  276. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +11 -1
  277. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +26 -6
  278. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +11 -0
  279. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +29 -3
  280. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +8 -1
  281. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +35 -9
  282. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -4
  283. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +277 -9
  284. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
  285. package/dist/core/ingestion/scope-resolution/pipeline/run.js +7 -3
  286. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +43 -9
  287. package/dist/core/ingestion/scope-resolution/scope/walkers.js +71 -10
  288. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -0
  289. package/dist/core/ingestion/tree-sitter-queries.js +161 -0
  290. package/dist/core/ingestion/type-extractors/zig.d.ts +2 -0
  291. package/dist/core/ingestion/type-extractors/zig.js +17 -0
  292. package/dist/core/ingestion/utils/ast-helpers.d.ts +40 -1
  293. package/dist/core/ingestion/utils/ast-helpers.js +124 -6
  294. package/dist/core/ingestion/utils/callable-flow-captures.d.ts +9 -0
  295. package/dist/core/ingestion/utils/callable-flow-captures.js +75 -14
  296. package/dist/core/ingestion/utils/test-file-path.d.ts +28 -0
  297. package/dist/core/ingestion/utils/test-file-path.js +87 -0
  298. package/dist/core/ingestion/variable-extractors/configs/zig.d.ts +2 -0
  299. package/dist/core/ingestion/variable-extractors/configs/zig.js +71 -0
  300. package/dist/core/ingestion/workers/parse-worker.js +85 -14
  301. package/dist/core/install-context.d.ts +4 -0
  302. package/dist/core/install-context.js +152 -0
  303. package/dist/core/lbug/csv-generator.d.ts +10 -1
  304. package/dist/core/lbug/csv-generator.js +92 -22
  305. package/dist/core/lbug/graph-emit-sink.d.ts +3 -2
  306. package/dist/core/lbug/graph-emit-sink.js +4 -2
  307. package/dist/core/lbug/lbug-adapter.d.ts +100 -5
  308. package/dist/core/lbug/lbug-adapter.js +236 -24
  309. package/dist/core/lbug/schema.d.ts +6 -5
  310. package/dist/core/lbug/schema.js +84 -22
  311. package/dist/core/net/url-guard.d.ts +6 -0
  312. package/dist/core/net/url-guard.js +147 -0
  313. package/dist/core/package-version.d.ts +5 -0
  314. package/dist/core/package-version.js +10 -0
  315. package/dist/core/run-analyze.d.ts +21 -4
  316. package/dist/core/run-analyze.js +426 -117
  317. package/dist/core/search/fts-indexes.d.ts +19 -1
  318. package/dist/core/search/fts-indexes.js +28 -1
  319. package/dist/core/tree-sitter/parser-loader.js +16 -0
  320. package/dist/core/update-cache.d.ts +39 -0
  321. package/dist/core/update-cache.js +141 -0
  322. package/dist/core/update-check.d.ts +31 -0
  323. package/dist/core/update-check.js +274 -0
  324. package/dist/mcp/local/local-backend.d.ts +27 -13
  325. package/dist/mcp/local/local-backend.js +148 -60
  326. package/dist/mcp/repository-policy.d.ts +5 -1
  327. package/dist/mcp/repository-policy.js +48 -4
  328. package/dist/mcp/resources.js +10 -1
  329. package/dist/mcp/server.js +8 -9
  330. package/dist/mcp/tools.js +32 -22
  331. package/dist/server/analyze-launch.d.ts +2 -0
  332. package/dist/server/analyze-launch.js +2 -0
  333. package/dist/server/analyze-worker-protocol.d.ts +6 -1
  334. package/dist/server/analyze-worker.d.ts +1 -0
  335. package/dist/server/analyze-worker.js +38 -20
  336. package/dist/server/api.d.ts +5 -1
  337. package/dist/server/api.js +105 -88
  338. package/dist/server/git-clone.d.ts +40 -16
  339. package/dist/server/git-clone.js +253 -199
  340. package/dist/server/grep-params.d.ts +18 -0
  341. package/dist/server/grep-params.js +83 -0
  342. package/dist/server/grep-scan.d.ts +23 -0
  343. package/dist/server/grep-scan.js +107 -0
  344. package/dist/server/grep-worker.d.ts +1 -0
  345. package/dist/server/grep-worker.js +12 -0
  346. package/dist/server/mcp-http.d.ts +8 -0
  347. package/dist/server/mcp-http.js +16 -1
  348. package/dist/server/update-controller.d.ts +29 -0
  349. package/dist/server/update-controller.js +82 -0
  350. package/dist/storage/file-lock.d.ts +15 -0
  351. package/dist/storage/file-lock.js +155 -0
  352. package/dist/storage/fs-atomic.d.ts +24 -0
  353. package/dist/storage/fs-atomic.js +86 -2
  354. package/dist/storage/global-dir.d.ts +2 -0
  355. package/dist/storage/global-dir.js +6 -0
  356. package/dist/storage/parse-cache.d.ts +45 -7
  357. package/dist/storage/parse-cache.js +189 -42
  358. package/dist/storage/parsedfile-store.d.ts +41 -60
  359. package/dist/storage/parsedfile-store.js +247 -171
  360. package/dist/storage/repo-manager.d.ts +10 -4
  361. package/dist/storage/repo-manager.js +35 -25
  362. package/dist/storage/repo-meta.d.ts +34 -0
  363. package/dist/storage/v8-sidecar.d.ts +48 -0
  364. package/dist/storage/v8-sidecar.js +347 -0
  365. package/dist/types/pipeline.d.ts +14 -0
  366. package/dist/utils/process-identity.d.ts +2 -0
  367. package/dist/utils/process-identity.js +35 -0
  368. package/package.json +10 -4
  369. package/scripts/assert-web-assets.mjs +35 -0
  370. package/scripts/build-web.js +72 -0
  371. package/scripts/build.js +31 -28
  372. package/scripts/cross-platform-tests.ts +5 -0
  373. package/skills/gitnexus-cli.md +5 -1
  374. package/web/assets/ProcessFlowModal-DAeX2BHW.js +24 -0
  375. package/web/assets/{abnfDiagram-QNN2D4NM-Cq2djWWe.js → abnfDiagram-PAR5IXJI-J3OdeHLl.js} +1 -1
  376. package/web/assets/{agent-BWAXPjC5.js → agent-BMRqXorA.js} +6 -4
  377. package/web/assets/architecture-7GRP2DOG-M7G3SWCO-G3sWyX6M.js +1 -0
  378. package/web/assets/architectureDiagram-2PNWDENW-ysKcRlGT.js +36 -0
  379. package/web/assets/blockDiagram-PUWGUBOA-oLXTa1lY.js +129 -0
  380. package/web/assets/c4Diagram-3NLNHZP5-D3iu4eC0.js +38 -0
  381. package/web/assets/{chunk-2SREHG4O-Dip42xOq.js → chunk-2NMSUPJH-B24w-wng.js} +1 -1
  382. package/web/assets/{chunk-VJFVEZTB-CX66F2ep.js → chunk-32MCUW2P-ByUyt0Sa.js} +3 -3
  383. package/web/assets/{chunk-4RFN2BYJ-DHHWuC-n.js → chunk-3NPNU5GP-DocZ07Sg.js} +1 -1
  384. package/web/assets/{chunk-XNMVGMAZ-Cg_LnPtj.js → chunk-3SMGFRGC-CAu4JRLv.js} +1 -1
  385. package/web/assets/{chunk-W44A43WB-BN8EQc_u.js → chunk-4CAJECRU-DRYMwG9z.js} +1 -1
  386. package/web/assets/chunk-4OADUZ5Q-CxrSvOwZ.js +10 -0
  387. package/web/assets/{chunk-DMV4VAQV-Bn6WXDSX.js → chunk-5IQCK5RY-CCMhl4so.js} +2 -2
  388. package/web/assets/{chunk-RRFMTAIC-CMN0wcYA.js → chunk-5MVFYWFU-Db9KvrYO.js} +1 -1
  389. package/web/assets/chunk-CLS4B6BI-Uvx5QNsu.js +168 -0
  390. package/web/assets/chunk-DZP67EKU-B3Mt380j.js +70 -0
  391. package/web/assets/{chunk-6L755F7B-CMhLBxi2.js → chunk-EICP7K5X-CqwE9hui.js} +1 -1
  392. package/web/assets/{chunk-BI6VK774-D0oaWk8V.js → chunk-GDY2UAB4-CtQQR0a8.js} +1 -1
  393. package/web/assets/chunk-H7VHZCWX-CE1nAmt6.js +1 -0
  394. package/web/assets/chunk-IJBDOHL6-BUKtY6oF.js +1 -0
  395. package/web/assets/{chunk-OIYT25JQ-CQ6KOZGX.js → chunk-JFFVMJIA-0fJenqia.js} +1 -1
  396. package/web/assets/{chunk-HNC4WDU7-DoU3KnA7.js → chunk-JZGDI5JK-BeTMSSkJ.js} +1 -1
  397. package/web/assets/{chunk-EQFTRU2I-1ix7TzW9.js → chunk-KD6SPIPN-Qp1Pflah.js} +1 -1
  398. package/web/assets/chunk-NF366YI6-CpSpya3n.js +231 -0
  399. package/web/assets/chunk-NUDPKBEF-CU1-BQIW.js +34 -0
  400. package/web/assets/{chunk-SATU7PGQ-B1zhgOvc.js → chunk-OJINMHTS-zOCQe4eI.js} +1 -1
  401. package/web/assets/{chunk-E5QJAATJ-dh-5CtIV.js → chunk-Q6NGPIAH-yyBomb63.js} +1 -1
  402. package/web/assets/chunk-QJSWEUOL-D_rf9gPD.js +128 -0
  403. package/web/assets/chunk-R7JDMUKV-CRoqKpD6.js +1 -0
  404. package/web/assets/{chunk-VE5CLXGZ-C1vB7wpY.js → chunk-RCXAM2GK-CUqrWQDV.js} +1 -1
  405. package/web/assets/{chunk-66DQ2XMT-CM0xjFAN.js → chunk-RT4MAWR3-zXy9-Lvt.js} +1 -1
  406. package/web/assets/{chunk-TZUXEDM2-B7p9AcTw.js → chunk-SFMINX4W-J2UrvMpD.js} +1 -1
  407. package/web/assets/{chunk-LORZLZWG-B57uGw2N.js → chunk-SLDQ463B-CHY6e_bQ.js} +2 -2
  408. package/web/assets/{chunk-FWYVLQTC-BgDItRzJ.js → chunk-TCEHX7R3-CXPDEVbm.js} +1 -1
  409. package/web/assets/{chunk-224SPVON-B8gxtXpy.js → chunk-VQC2EELJ-Dc8fIy4R.js} +1 -1
  410. package/web/assets/chunk-VRZKL3EH-DB3KixTQ.js +1 -0
  411. package/web/assets/{chunk-A7VWPJGB-B4O3oQdQ.js → chunk-VTHDQ7BV-b7FsPQZO.js} +1 -1
  412. package/web/assets/chunk-VY2OSTJR-Dkgc3Brg.js +2 -0
  413. package/web/assets/chunk-WUBWJARI-7FwILJ3k.js +2 -0
  414. package/web/assets/{chunk-D6VWDJW2-BxcBdZ9c.js → chunk-YBMQ5JGJ-BSnyWZmd.js} +1 -1
  415. package/web/assets/chunk-YDMLL4PJ-IHhMngTz.js +2 -0
  416. package/web/assets/chunk-Z6V44ARX-BjCEsF0Q.js +62 -0
  417. package/web/assets/chunk-ZJJ7VQJP-Dz089b-K.js +321 -0
  418. package/web/assets/chunk-ZNLK7HRR-B0iFpmW4.js +1 -0
  419. package/web/assets/chunk-ZQN7UHIL-Cy7KAjQt.js +1 -0
  420. package/web/assets/{chunk-L5GCOVLC-CE2w8Nm_.js → chunk-ZS6VBONO-DBjJO0w9.js} +2 -2
  421. package/web/assets/{chunk-NV3KIAZN-5yvcpMiu.js → chunk-ZUNWM646-DNRJyNPe.js} +1 -1
  422. package/web/assets/classDiagram-FGAMPOII-C5Ibyode.js +1 -0
  423. package/web/assets/classDiagram-v2-AI5RJEK4-C5Ibyode.js +1 -0
  424. package/web/assets/{cose-bilkent-RZA4XIPR-BHpK4Crp.js → cose-bilkent-Q72C2OJ3-DMeFXnK8.js} +1 -1
  425. package/web/assets/cynefin-OW5HDTMX-6OCTWOGG-vlqakYcO.js +1 -0
  426. package/web/assets/{cynefinDiagram-TR7LZUCG-C3Iar9lZ.js → cynefinDiagram-2OOWUY4M-BY6DZkTt.js} +1 -1
  427. package/web/assets/dagre-MPVFI544-DWO70fy_.js +4 -0
  428. package/web/assets/diagram-AE4NWXFW-f7JRVRUL.js +24 -0
  429. package/web/assets/{diagram-L7DVE3PN-GIRyVUtt.js → diagram-BUJID5UG-BXZv1rCS.js} +2 -2
  430. package/web/assets/{diagram-JCD7PQ7C-DC5-9FRr.js → diagram-C44CZ5NI-CRNfvjCq.js} +1 -1
  431. package/web/assets/diagram-EYOLEXXS-DZOjKQVE.js +30 -0
  432. package/web/assets/diagram-P7B6PWOJ-D3SQmw3_.js +3 -0
  433. package/web/assets/{ebnfDiagram-DRHRQJWO-D8_CI4ZF.js → ebnfDiagram-FTPZ3PV6-jKWpIDN2.js} +1 -1
  434. package/web/assets/erDiagram-H3ERR26V-BqJntEuJ.js +99 -0
  435. package/web/assets/eventmodeling-NTZA5JFV-WKSWQHFS-Bq4FqtBL.js +1 -0
  436. package/web/assets/flowDiagram-YHGXBVSY-Dnlk2bEu.js +1 -0
  437. package/web/assets/ganttDiagram-RWFTB7ED-Bl6Y1K5T.js +292 -0
  438. package/web/assets/gitGraph-4MIJSDKK-JH2HKYUO-B3yc4GkH.js +1 -0
  439. package/web/assets/gitGraphDiagram-MAR6GKOP-CkNvsrdw.js +106 -0
  440. package/web/assets/{index-CJDpyH-n.css → index-C2_aej58.css} +1 -1
  441. package/web/assets/{index-DDRie6_8.js → index-Dj3vQOHK.js} +51 -51
  442. package/web/assets/info-A6RAGUB7-3TX3OFWW-BM3N5_Dv.js +1 -0
  443. package/web/assets/infoDiagram-LV547AFH-COkFutAf.js +2 -0
  444. package/web/assets/{ishikawaDiagram-4JDSWWDM-DmqWtjkl.js → ishikawaDiagram-PUJQGNDS-Bb8FylSR.js} +2 -2
  445. package/web/assets/{journeyDiagram-QUS3FAKT-XAzVzrQW.js → journeyDiagram-EW5QJT4W-BzoHUBhM.js} +4 -4
  446. package/web/assets/{kanban-definition-D4L7SQKK-YurRnmYn.js → kanban-definition-JSQERAZB-Uy2Pi0yQ.js} +4 -4
  447. package/web/assets/katex-CZ4GXH2S-C0Fcou7U.js +257 -0
  448. package/web/assets/{mindmap-definition-66QP5TD6-ChrWWnil.js → mindmap-definition-VBJCLQLM-B-CnOnt_.js} +3 -3
  449. package/web/assets/packet-AYTQ26CC-MKII6P3Y-Bd52ZE3V.js +1 -0
  450. package/web/assets/{pegDiagram-YKIO5C6U-QGeQLEq2.js → pegDiagram-7WILOQTJ-D9sneKXg.js} +1 -1
  451. package/web/assets/pie-WAS4IAKB-6B4OPMJ5-DW5Xy69Z.js +1 -0
  452. package/web/assets/pieDiagram-EFA7CBSB-Dx2NQofL.js +39 -0
  453. package/web/assets/{quadrantDiagram-VO5QLCXA-B7098wSc.js → quadrantDiagram-WARVYA7P-DPKL9_0A.js} +3 -3
  454. package/web/assets/radar-RG4KPBEZ-UPTR3XUL-CkzibT2h.js +1 -0
  455. package/web/assets/railroad-74A4TZTK-MEFUPFMS-D9zF-mDN.js +1 -0
  456. package/web/assets/railroad-abnf-HS5TGJTU-R5YG2S5D-ruacjUbX.js +1 -0
  457. package/web/assets/railroad-ebnf-LZEXJU2U-G5QEX2L6-S1zc5OiO.js +1 -0
  458. package/web/assets/railroad-peg-WCYAUIDC-H5I2ZRY2-Cbcr0XzY.js +1 -0
  459. package/web/assets/{railroadDiagram-M77LTMSB-AXu4vxk_.js → railroadDiagram-5NIQVNLQ-DsweTo14.js} +1 -1
  460. package/web/assets/{requirementDiagram-RASO5HTO-B-l8InpK.js → requirementDiagram-SXREGOKZ-CXwdNSVR.js} +4 -4
  461. package/web/assets/{sankeyDiagram-F32LOJ6L-Kd7zjJgX.js → sankeyDiagram-VV74M2VP-CA6jtP9P.js} +3 -3
  462. package/web/assets/{sequenceDiagram-URATNSBD-BlcdY9DS.js → sequenceDiagram-52ZFIFDL-k_5rEbzm.js} +15 -15
  463. package/web/assets/src-Df5C1Nz4.js +1 -0
  464. package/web/assets/stateDiagram-3QAKPIVI-BejHTf31.js +1 -0
  465. package/web/assets/stateDiagram-v2-HN2P4RDZ-BrfoRuOc.js +1 -0
  466. package/web/assets/swimlanes-QLVP42QD-CQSVO5D6.js +1 -0
  467. package/web/assets/swimlanesDiagram-JKPDBFCN-DrWB9kcD.js +8 -0
  468. package/web/assets/{timeline-definition-WJXWRH4I-DUfp1R3E.js → timeline-definition-GS45XAXW-C0Ks8rPP.js} +4 -4
  469. package/web/assets/treeView-Q6P3EWNA-ZRJGANNQ-DmKOCo6L.js +1 -0
  470. package/web/assets/treemap-WGGIJYW6-K64VN5AS-DO3xY92U.js +1 -0
  471. package/web/assets/{vennDiagram-K3VCMQLI-Bj-FN-XS.js → vennDiagram-QIQU2ZRJ-rgPiS837.js} +3 -3
  472. package/web/assets/wardley-WFR3VGLG-D67OWCCH-DiDPBNft.js +1 -0
  473. package/web/assets/wardleyDiagram-U6YNM66N-DRVr7SPi.js +78 -0
  474. package/web/assets/{xychartDiagram-5VRUVLCW-CK_rbSWE.js → xychartDiagram-XJAZEDNM-COtlZzYb.js} +3 -3
  475. package/web/index.html +19 -17
  476. package/web/assets/ProcessFlowModal-Badh2Pbg.js +0 -24
  477. package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +0 -1
  478. package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +0 -36
  479. package/web/assets/blockDiagram-54WLDVWM-Dg_hrRWE.js +0 -132
  480. package/web/assets/c4Diagram-X2LASM7V-CnhoT4aV.js +0 -10
  481. package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +0 -127
  482. package/web/assets/chunk-5VCL7Z4A-CQ-2dYWj.js +0 -1
  483. package/web/assets/chunk-6BELYETK-ChsYtfHW.js +0 -1
  484. package/web/assets/chunk-7CWYLC5S-DRgGkkpF.js +0 -2
  485. package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +0 -32
  486. package/web/assets/chunk-KRXBNO2N-C-UNuKKf.js +0 -1
  487. package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +0 -321
  488. package/web/assets/chunk-LIEV3EAG-pyKGssV3.js +0 -1
  489. package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +0 -62
  490. package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +0 -10
  491. package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +0 -156
  492. package/web/assets/chunk-SZD42YQK-ijyKKVr1.js +0 -70
  493. package/web/assets/chunk-TFPGFQPA-Dj6a-0pC.js +0 -231
  494. package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +0 -2
  495. package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +0 -1
  496. package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +0 -1
  497. package/web/assets/chunk-WJBAP47W-BckNkuEN.js +0 -1
  498. package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +0 -1
  499. package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +0 -1
  500. package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +0 -1
  501. package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +0 -4
  502. package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +0 -30
  503. package/web/assets/diagram-KFBZAVDW-Dfmf_4ti.js +0 -3
  504. package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +0 -24
  505. package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +0 -85
  506. package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +0 -1
  507. package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +0 -1
  508. package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +0 -292
  509. package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +0 -1
  510. package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +0 -106
  511. package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +0 -1
  512. package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +0 -2
  513. package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +0 -257
  514. package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +0 -1
  515. package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +0 -1
  516. package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +0 -39
  517. package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +0 -1
  518. package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +0 -1
  519. package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +0 -1
  520. package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +0 -1
  521. package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +0 -1
  522. package/web/assets/src-C5sx_gMp.js +0 -1
  523. package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +0 -1
  524. package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +0 -1
  525. package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +0 -2
  526. package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +0 -8
  527. package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +0 -1
  528. package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +0 -1
  529. package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +0 -1
  530. package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +0 -78
  531. /package/web/assets/{sizeCapture-5GORAGP4-BEqQzsxs.js → sizeCapture-FGA5AGYP-BEqQzsxs.js} +0 -0
@@ -59,6 +59,12 @@ export declare const SUPPORTED_FTS_STEMMERS: ReadonlySet<string>;
59
59
  export interface CreateSearchFTSIndexesOptions {
60
60
  onIndexStart?: (table: string, indexName: string) => void;
61
61
  onIndexReady?: (table: string, indexName: string) => void;
62
+ /**
63
+ * When set, only these node-table names are dropped/rebuilt (#3016).
64
+ * Omit to rebuild every configured FTS index (full analyze / deleted-file
65
+ * incremental / `--repair-fts`).
66
+ */
67
+ tables?: ReadonlySet<string>;
62
68
  }
63
69
  /**
64
70
  * Resolve + validate `GITNEXUS_FTS_STEMMER` once, up front at analyze startup,
@@ -98,7 +104,19 @@ export declare function getSearchFTSStemmer(): string;
98
104
  * contract, and the same one-shared-`SHOW_INDEXES`-read purpose, as the gates in
99
105
  * `lbug-adapter.ts`. Omit it to have the sweep read the catalog itself.
100
106
  */
101
- export declare function dropSearchFTSIndexes(indexRows?: IndexCatalogSnapshot): Promise<void>;
107
+ export declare function dropSearchFTSIndexes(indexRows?: IndexCatalogSnapshot, tables?: ReadonlySet<string>): Promise<void>;
108
+ /**
109
+ * The configured FTS tables whose index the catalog proves is ABSENT right now.
110
+ *
111
+ * `undefined` means the catalog could not be read, which proves nothing — the
112
+ * same fail-closed reading the sweep above applies. Callers narrowing a rebuild
113
+ * to a subset of tables (#3016) must union this in, or must not narrow at all
114
+ * when it is `undefined`: a run that rebuilds only the tables it wrote leaves
115
+ * keyword search permanently degraded on every table whose index went missing
116
+ * earlier (a prior escalation drops all of them, and only the next full rebuild
117
+ * would ever put them back).
118
+ */
119
+ export declare function missingSearchFTSIndexTables(indexRows?: IndexCatalogSnapshot): Promise<Set<string> | undefined>;
102
120
  /** One configured index that could not be (re)built, and why. */
103
121
  export interface FtsIndexBuildFailure {
104
122
  table: string;
@@ -172,7 +172,7 @@ export function getSearchFTSStemmer() {
172
172
  * contract, and the same one-shared-`SHOW_INDEXES`-read purpose, as the gates in
173
173
  * `lbug-adapter.ts`. Omit it to have the sweep read the catalog itself.
174
174
  */
175
- export async function dropSearchFTSIndexes(indexRows) {
175
+ export async function dropSearchFTSIndexes(indexRows, tables) {
176
176
  // One catalog read for the whole sweep, decided PER CONFIGURED INDEX on
177
177
  // IDENTITY (#2841 cleanup review). `undefined` = the catalog could not be
178
178
  // read, which proves nothing — attempt every drop rather than skip a real one,
@@ -193,6 +193,8 @@ export async function dropSearchFTSIndexes(indexRows) {
193
193
  // whether the sweep ran or not.
194
194
  const rows = await resolveGateRows(indexRows);
195
195
  for (const { table, indexName } of FTS_INDEXES) {
196
+ if (tables && !tables.has(table))
197
+ continue;
196
198
  // Skip only what the catalog POSITIVELY proves absent. Without this, a
197
199
  // machine whose FTS extension cannot load, analyzing a DB that never carried
198
200
  // an FTS index, pays one failed `CALL DROP_FTS_INDEX` per configured table on
@@ -209,6 +211,29 @@ export async function dropSearchFTSIndexes(indexRows) {
209
211
  await dropFTSIndex(table, indexName);
210
212
  }
211
213
  }
214
+ /**
215
+ * The configured FTS tables whose index the catalog proves is ABSENT right now.
216
+ *
217
+ * `undefined` means the catalog could not be read, which proves nothing — the
218
+ * same fail-closed reading the sweep above applies. Callers narrowing a rebuild
219
+ * to a subset of tables (#3016) must union this in, or must not narrow at all
220
+ * when it is `undefined`: a run that rebuilds only the tables it wrote leaves
221
+ * keyword search permanently degraded on every table whose index went missing
222
+ * earlier (a prior escalation drops all of them, and only the next full rebuild
223
+ * would ever put them back).
224
+ */
225
+ export async function missingSearchFTSIndexTables(indexRows) {
226
+ const rows = await resolveGateRows(indexRows);
227
+ if (rows === undefined)
228
+ return undefined;
229
+ const missing = new Set();
230
+ for (const { table, indexName } of FTS_INDEXES) {
231
+ const present = rows.some((row) => indexRowTable(row) === table && indexRowName(row) === indexName);
232
+ if (!present)
233
+ missing.add(table);
234
+ }
235
+ return missing;
236
+ }
212
237
  /**
213
238
  * Build every configured FTS index, and keep going when one of them fails
214
239
  * (#2889).
@@ -232,6 +257,8 @@ export async function createSearchFTSIndexes(options) {
232
257
  const stemmer = getSearchFTSStemmer();
233
258
  const failures = [];
234
259
  for (const { table, indexName, properties } of FTS_INDEXES) {
260
+ if (options?.tables && !options.tables.has(table))
261
+ continue;
235
262
  options?.onIndexStart?.(table, indexName);
236
263
  // Drop first so the live `properties` always win. `createFTSIndex` is
237
264
  // idempotent-by-name (skips when the index already exists), so without the
@@ -112,6 +112,22 @@ const SOURCES = {
112
112
  'Likely cause: no prebuilt `.node` for this platform/architecture. ' +
113
113
  `See ${ISSUES_URL}/2107.`,
114
114
  },
115
+ // Zig grammar declares peerOptional `tree-sitter@^0.22.1` but its native
116
+ // binding is ABI-compatible with the bundled `tree-sitter@0.21.x` runtime
117
+ // (verified by load-time smoke test). The peer-dep mismatch is suppressed
118
+ // via the `overrides` block in package.json. Listed as `optional: true`
119
+ // because the package is in `optionalDependencies` — users on platforms
120
+ // without a prebuild may not have it — and `userSkippable` because it is
121
+ // a genuinely-optional grammar: `GITNEXUS_SKIP_OPTIONAL_GRAMMARS` must be
122
+ // able to disable it at analyze time like swift/dart/kotlin.
123
+ [SupportedLanguages.Zig]: {
124
+ load: () => _require('@tree-sitter-grammars/tree-sitter-zig'),
125
+ optional: true,
126
+ userSkippable: true,
127
+ unavailableNote: 'Zig parsing disabled: `@tree-sitter-grammars/tree-sitter-zig` is an ' +
128
+ 'optionalDependency and is not installed (or its native binding failed ' +
129
+ 'to load on this platform).',
130
+ },
115
131
  };
116
132
  export const listGrammarSources = () => Object.entries(SOURCES).map(([key, source]) => ({
117
133
  key,
@@ -0,0 +1,39 @@
1
+ export declare const UPDATE_CACHE_TTL_MS: number;
2
+ export declare const STRICT_UPDATE_VERSION: RegExp;
3
+ export declare const DEFAULT_UPDATE_REGISTRY = "https://registry.npmjs.org";
4
+ export interface UpdateCacheEntry {
5
+ lastCheckAt: string;
6
+ registry: string;
7
+ latestVersion?: string;
8
+ }
9
+ export interface ValidatedUpdateCache {
10
+ lastCheckAt: number;
11
+ latestVersion?: string;
12
+ stale: boolean;
13
+ }
14
+ /** Broad truthy parsing shared by the update-notifier guards. */
15
+ export declare function isTruthyEnv(value: string | undefined): boolean;
16
+ /** The update notifier is disabled by either opt-out env or a CI environment. */
17
+ export declare function updateNotifierOptedOut(env: NodeJS.ProcessEnv): boolean;
18
+ /** Freshness gate for the 24h TTL; future-dated timestamps are stale. */
19
+ export declare function isUpdateCacheFresh(lastCheckAt: string, now: number): boolean;
20
+ /** Strict x.y.z numeric comparison. Invalid or prerelease versions are silent. */
21
+ export declare function isNewerVersion(installedVersion: string, latestVersion: string): boolean;
22
+ export declare function normalizedUpdateRegistry(env?: NodeJS.ProcessEnv): {
23
+ identity: string;
24
+ packageUrl: string;
25
+ };
26
+ export declare function updateCheckCachePath(env?: NodeJS.ProcessEnv): string;
27
+ export declare function updateCheckLockPath(env?: NodeJS.ProcessEnv): string;
28
+ /**
29
+ * Best-effort synchronous probe: is a refresh plausibly in flight? Used to
30
+ * coalesce detached refresh spawns. A dead same-host owner returns false so
31
+ * the spawned child can reclaim the stale lock; a foreign-host owner returns
32
+ * false and lets the child's full lock logic decide.
33
+ */
34
+ export declare function updateRefreshInProgress(env?: NodeJS.ProcessEnv): boolean;
35
+ export declare function parseUpdateCache(raw: string, registry: string): UpdateCacheEntry | null;
36
+ export declare function readValidatedUpdateCacheSync(options?: {
37
+ env?: NodeJS.ProcessEnv;
38
+ now?: number;
39
+ }): ValidatedUpdateCache | null;
@@ -0,0 +1,141 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { getGlobalDir } from '../storage/global-dir.js';
5
+ import { isProcessAlive, readProcessStartTime } from '../utils/process-identity.js';
6
+ export const UPDATE_CACHE_TTL_MS = 24 * 60 * 60 * 1_000;
7
+ export const STRICT_UPDATE_VERSION = /^\d+\.\d+\.\d+$/;
8
+ export const DEFAULT_UPDATE_REGISTRY = 'https://registry.npmjs.org';
9
+ /** Broad truthy parsing shared by the update-notifier guards. */
10
+ export function isTruthyEnv(value) {
11
+ if (!value)
12
+ return false;
13
+ return !['', '0', 'false', 'no', 'off'].includes(value.toLowerCase());
14
+ }
15
+ /** The update notifier is disabled by either opt-out env or a CI environment. */
16
+ export function updateNotifierOptedOut(env) {
17
+ return (isTruthyEnv(env.GITNEXUS_NO_UPDATE_NOTIFIER) ||
18
+ isTruthyEnv(env.NO_UPDATE_NOTIFIER) ||
19
+ isTruthyEnv(env.CI));
20
+ }
21
+ /** Freshness gate for the 24h TTL; future-dated timestamps are stale. */
22
+ export function isUpdateCacheFresh(lastCheckAt, now) {
23
+ const checkedAt = Date.parse(lastCheckAt);
24
+ return checkedAt <= now && now - checkedAt < UPDATE_CACHE_TTL_MS;
25
+ }
26
+ /** Strict x.y.z numeric comparison. Invalid or prerelease versions are silent. */
27
+ export function isNewerVersion(installedVersion, latestVersion) {
28
+ if (!STRICT_UPDATE_VERSION.test(installedVersion) || !STRICT_UPDATE_VERSION.test(latestVersion)) {
29
+ return false;
30
+ }
31
+ const installed = installedVersion.split('.').map(BigInt);
32
+ const latest = latestVersion.split('.').map(BigInt);
33
+ for (let index = 0; index < 3; index += 1) {
34
+ if (latest[index] !== installed[index])
35
+ return latest[index] > installed[index];
36
+ }
37
+ return false;
38
+ }
39
+ let registryMemo;
40
+ export function normalizedUpdateRegistry(env = process.env) {
41
+ const key = env.npm_config_registry ?? '';
42
+ if (registryMemo?.key === key)
43
+ return registryMemo.value;
44
+ const value = buildUpdateRegistry(key);
45
+ registryMemo = { key, value };
46
+ return value;
47
+ }
48
+ function buildUpdateRegistry(rawRegistry) {
49
+ const parsed = new URL(rawRegistry || DEFAULT_UPDATE_REGISTRY);
50
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
51
+ throw new Error('Unsupported npm registry protocol');
52
+ }
53
+ if (parsed.search || parsed.hash) {
54
+ throw new Error('Registry URL cannot contain query or fragment');
55
+ }
56
+ parsed.username = '';
57
+ parsed.password = '';
58
+ parsed.pathname = parsed.pathname.replace(/\/+$/, '') || '/';
59
+ const pathname = parsed.pathname === '/' ? '' : parsed.pathname;
60
+ const identity = `${parsed.protocol}//${parsed.host}${pathname}`;
61
+ // `/<pkg>/latest` is the small dist-tag document. The full packument at
62
+ // `/<pkg>` is multi-megabyte on this package and cannot fit the fetch cap.
63
+ const packagePath = `${pathname}/gitnexus/latest`.replace(/\/{2,}/g, '/');
64
+ return { identity, packageUrl: `${parsed.protocol}//${parsed.host}${packagePath}` };
65
+ }
66
+ export function updateCheckCachePath(env = process.env) {
67
+ return path.join(env.GITNEXUS_HOME || getGlobalDir(), 'update-check.json');
68
+ }
69
+ export function updateCheckLockPath(env = process.env) {
70
+ return path.join(env.GITNEXUS_HOME || getGlobalDir(), 'update-check.lock');
71
+ }
72
+ /**
73
+ * Best-effort synchronous probe: is a refresh plausibly in flight? Used to
74
+ * coalesce detached refresh spawns. A dead same-host owner returns false so
75
+ * the spawned child can reclaim the stale lock; a foreign-host owner returns
76
+ * false and lets the child's full lock logic decide.
77
+ */
78
+ export function updateRefreshInProgress(env = process.env) {
79
+ try {
80
+ const owner = JSON.parse(fs.readFileSync(updateCheckLockPath(env), 'utf8'));
81
+ if (typeof owner.pid !== 'number' || owner.pid <= 0)
82
+ return false;
83
+ if (owner.hostname !== os.hostname())
84
+ return false;
85
+ if (!isProcessAlive(owner.pid))
86
+ return false;
87
+ // Same rule as acquireFileLock: a live PID with a different start time is
88
+ // reuse, not the lock owner. Unreadable start time stays conservative
89
+ // (treat as in progress) so we don't spawn a racing child.
90
+ if (typeof owner.processStartTime === 'string' && owner.processStartTime) {
91
+ const currentStartTime = readProcessStartTime(owner.pid);
92
+ if (currentStartTime && currentStartTime !== owner.processStartTime)
93
+ return false;
94
+ }
95
+ return true;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ export function parseUpdateCache(raw, registry) {
102
+ try {
103
+ const parsed = JSON.parse(raw);
104
+ if (typeof parsed.lastCheckAt !== 'string' ||
105
+ !Number.isFinite(Date.parse(parsed.lastCheckAt)) ||
106
+ parsed.registry !== registry ||
107
+ (parsed.latestVersion !== undefined &&
108
+ (typeof parsed.latestVersion !== 'string' ||
109
+ !STRICT_UPDATE_VERSION.test(parsed.latestVersion)))) {
110
+ return null;
111
+ }
112
+ return {
113
+ lastCheckAt: parsed.lastCheckAt,
114
+ registry: parsed.registry,
115
+ ...(parsed.latestVersion === undefined ? {} : { latestVersion: parsed.latestVersion }),
116
+ };
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ export function readValidatedUpdateCacheSync(options = {}) {
123
+ try {
124
+ const env = options.env ?? process.env;
125
+ const registry = normalizedUpdateRegistry(env);
126
+ const raw = fs.readFileSync(updateCheckCachePath(env), 'utf8');
127
+ const entry = parseUpdateCache(raw, registry.identity);
128
+ if (!entry)
129
+ return null;
130
+ const lastCheckAt = Date.parse(entry.lastCheckAt);
131
+ const now = options.now ?? Date.now();
132
+ return {
133
+ lastCheckAt,
134
+ ...(entry.latestVersion === undefined ? {} : { latestVersion: entry.latestVersion }),
135
+ stale: !isUpdateCacheFresh(entry.lastCheckAt, now),
136
+ };
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
@@ -0,0 +1,31 @@
1
+ export interface UpdateState {
2
+ updateAvailable: boolean;
3
+ latestVersion?: string;
4
+ }
5
+ export interface UpdateCheckOptions {
6
+ /** Test/adapter override; omitted means classify process.argv[1]. */
7
+ eligible?: boolean;
8
+ /** Test override; omitted means this package's installed version. */
9
+ installedVersion?: string;
10
+ /** Test override in epoch milliseconds. */
11
+ now?: number;
12
+ /** Cache-only consumers can suppress stale-while-revalidate. */
13
+ refreshIfStale?: boolean;
14
+ /** Explicit `gitnexus update`: check even when CI/opt-out env is set. */
15
+ ignoreOptOut?: boolean;
16
+ }
17
+ export interface UpdateRefreshSchedulerOptions extends Omit<UpdateCheckOptions, 'now' | 'refreshIfStale'> {
18
+ now?: () => number;
19
+ }
20
+ /**
21
+ * Read update state cache-first. Every invalid/missing/stale cache starts one
22
+ * catch-isolated refresh unless the caller explicitly requests cache-only.
23
+ */
24
+ export declare function evaluate(options?: UpdateCheckOptions): Promise<UpdateState | null>;
25
+ /** Run one locked, fail-open registry refresh. */
26
+ export declare function refresh(options?: UpdateCheckOptions): Promise<UpdateState | null>;
27
+ /**
28
+ * Start an immediate evaluation and repeat on the cache TTL cadence. Timers
29
+ * never keep the process alive; refresh() supplies process-wide single-flight.
30
+ */
31
+ export declare function armUpdateRefreshScheduler(onState: (state: UpdateState | null) => void, options?: UpdateRefreshSchedulerOptions): () => void;
@@ -0,0 +1,274 @@
1
+ import fs from 'node:fs/promises';
2
+ import { getGlobalDir } from '../storage/global-dir.js';
3
+ import { writeFileAtomic } from '../storage/fs-atomic.js';
4
+ import { acquireFileLock, FileLockBusyError } from '../storage/file-lock.js';
5
+ import { validateGitUrl } from './net/url-guard.js';
6
+ import { updateEligibleInstall } from './install-context.js';
7
+ import { createLogger } from './logger.js';
8
+ import { packageVersion } from './package-version.js';
9
+ import { isNewerVersion, isUpdateCacheFresh, normalizedUpdateRegistry, parseUpdateCache, STRICT_UPDATE_VERSION, UPDATE_CACHE_TTL_MS, updateCheckCachePath, updateCheckLockPath, updateNotifierOptedOut, } from './update-cache.js';
10
+ const FETCH_TIMEOUT_MS = 3_000;
11
+ const MAX_RESPONSE_BYTES = 64 * 1024;
12
+ const MAX_REDIRECTS = 5;
13
+ /** Backoff when refresh cannot publish (lock-busy or still-stale cache). */
14
+ const LOCK_BUSY_RETRY_MIN_MS = 30_000;
15
+ const LOCK_BUSY_RETRY_JITTER_MS = 30_000;
16
+ const updateLogger = createLogger('update-check');
17
+ function defaultInstalledVersion() {
18
+ return packageVersion();
19
+ }
20
+ function nextSchedulerDelay(entry, now) {
21
+ if (entry && isUpdateCacheFresh(entry.lastCheckAt, now)) {
22
+ return Math.max(1, Date.parse(entry.lastCheckAt) + UPDATE_CACHE_TTL_MS - now);
23
+ }
24
+ // Missing, future-dated, or still stale after a lock-busy skip: back off
25
+ // from now instead of deriving 1ms from a past-due timestamp.
26
+ return LOCK_BUSY_RETRY_MIN_MS + Math.floor(Math.random() * LOCK_BUSY_RETRY_JITTER_MS);
27
+ }
28
+ function isOptedOut() {
29
+ return updateNotifierOptedOut(process.env);
30
+ }
31
+ async function isEligible(override) {
32
+ return override ?? (await updateEligibleInstall());
33
+ }
34
+ function cacheFile() {
35
+ return updateCheckCachePath();
36
+ }
37
+ function lockFile() {
38
+ return updateCheckLockPath();
39
+ }
40
+ function normalizedRegistry() {
41
+ const registry = normalizedUpdateRegistry();
42
+ validateGitUrl(registry.packageUrl);
43
+ return registry;
44
+ }
45
+ async function readCache(registry) {
46
+ try {
47
+ return parseUpdateCache(await fs.readFile(cacheFile(), 'utf8'), registry);
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ function stateFrom(entry, installedVersion) {
54
+ return {
55
+ updateAvailable: entry.latestVersion !== undefined && isNewerVersion(installedVersion, entry.latestVersion),
56
+ ...(entry.latestVersion === undefined ? {} : { latestVersion: entry.latestVersion }),
57
+ };
58
+ }
59
+ function installedVersionOf(options) {
60
+ return options.installedVersion ?? defaultInstalledVersion();
61
+ }
62
+ async function isNotifierActive(options = {}) {
63
+ return (options.ignoreOptOut === true || !isOptedOut()) && (await isEligible(options.eligible));
64
+ }
65
+ /**
66
+ * Read update state cache-first. Every invalid/missing/stale cache starts one
67
+ * catch-isolated refresh unless the caller explicitly requests cache-only.
68
+ */
69
+ export async function evaluate(options = {}) {
70
+ try {
71
+ if (!(await isNotifierActive(options)))
72
+ return null;
73
+ const registry = normalizedRegistry();
74
+ const now = options.now ?? Date.now();
75
+ const entry = await readCache(registry.identity);
76
+ if ((!entry || !isUpdateCacheFresh(entry.lastCheckAt, now)) &&
77
+ options.refreshIfStale !== false) {
78
+ void refresh(options).catch(() => { });
79
+ }
80
+ if (!entry)
81
+ return null;
82
+ return stateFrom(entry, installedVersionOf(options));
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ async function readResponseBody(response) {
89
+ const advertised = Number(response.headers.get('content-length'));
90
+ if (Number.isFinite(advertised) && advertised > MAX_RESPONSE_BYTES) {
91
+ await response.body?.cancel().catch(() => { });
92
+ throw new Error('Registry response too large');
93
+ }
94
+ if (!response.body)
95
+ return '';
96
+ const reader = response.body.getReader();
97
+ const chunks = [];
98
+ let bytes = 0;
99
+ try {
100
+ for (;;) {
101
+ const { done, value } = await reader.read();
102
+ if (done)
103
+ break;
104
+ bytes += value.byteLength;
105
+ if (bytes > MAX_RESPONSE_BYTES)
106
+ throw new Error('Registry response too large');
107
+ chunks.push(value);
108
+ }
109
+ }
110
+ finally {
111
+ if (bytes > MAX_RESPONSE_BYTES)
112
+ await reader.cancel().catch(() => { });
113
+ reader.releaseLock();
114
+ }
115
+ return Buffer.concat(chunks).toString('utf8');
116
+ }
117
+ function sanitizedHttpUrl(input, base) {
118
+ const parsed = new URL(input, base);
119
+ parsed.username = '';
120
+ parsed.password = '';
121
+ validateGitUrl(parsed.toString());
122
+ return parsed;
123
+ }
124
+ async function fetchLatest(packageUrl) {
125
+ let url = sanitizedHttpUrl(packageUrl);
126
+ for (let redirects = 0;; redirects += 1) {
127
+ const response = await fetch(url.toString(), {
128
+ method: 'GET',
129
+ redirect: 'manual',
130
+ headers: { accept: 'application/json' },
131
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
132
+ });
133
+ if (response.status >= 300 && response.status < 400) {
134
+ if (redirects >= MAX_REDIRECTS)
135
+ throw new Error('Too many registry redirects');
136
+ const location = response.headers.get('location');
137
+ await response.body?.cancel().catch(() => { });
138
+ if (!location)
139
+ throw new Error('Registry redirect missing location');
140
+ url = sanitizedHttpUrl(location, url.toString());
141
+ continue;
142
+ }
143
+ if (!response.ok) {
144
+ await response.body?.cancel().catch(() => { });
145
+ throw new Error(`Registry returned ${response.status}`);
146
+ }
147
+ const parsed = JSON.parse(await readResponseBody(response));
148
+ const latest = (typeof parsed.version === 'string' ? parsed.version : undefined) ??
149
+ (typeof parsed['dist-tags']?.latest === 'string' ? parsed['dist-tags'].latest : undefined);
150
+ if (typeof latest !== 'string' || !STRICT_UPDATE_VERSION.test(latest)) {
151
+ throw new Error('Registry latest version is invalid');
152
+ }
153
+ return latest;
154
+ }
155
+ }
156
+ async function publishMonotonically(entry, attemptStartedAt) {
157
+ const current = await readCache(entry.registry);
158
+ const currentAt = current ? Date.parse(current.lastCheckAt) : Number.NaN;
159
+ // A later in-the-past write wins. Future-dated entries (wall-clock) are
160
+ // clock-skew poison and must stay replaceable so a later holder can repair them.
161
+ if (Number.isFinite(currentAt) && currentAt <= Date.now() && currentAt > attemptStartedAt) {
162
+ return;
163
+ }
164
+ await fs.mkdir(getGlobalDir(), { recursive: true });
165
+ await writeFileAtomic(cacheFile(), `${JSON.stringify(entry)}\n`, 1);
166
+ }
167
+ let refreshInFlight = null;
168
+ /** Run one locked, fail-open registry refresh. */
169
+ export function refresh(options = {}) {
170
+ if (refreshInFlight)
171
+ return refreshInFlight;
172
+ const run = async () => {
173
+ let release;
174
+ try {
175
+ if (!(await isNotifierActive(options)))
176
+ return null;
177
+ const registry = normalizedRegistry();
178
+ const attemptStartedAt = options.now ?? Date.now();
179
+ try {
180
+ release = await acquireFileLock(lockFile(), { retries: 0 });
181
+ }
182
+ catch (error) {
183
+ if (error instanceof FileLockBusyError)
184
+ return null;
185
+ throw error;
186
+ }
187
+ let fetched;
188
+ try {
189
+ fetched = await fetchLatest(registry.packageUrl);
190
+ }
191
+ catch {
192
+ // Negative entries enforce the same TTL on offline/authenticated-only
193
+ // registries as successful checks. A known same-identity latestVersion
194
+ // must survive a later failed refresh so notices do not go silent
195
+ // for a day; only a first-ever miss stays version-less.
196
+ }
197
+ const latestVersion = fetched ?? (await readCache(registry.identity))?.latestVersion;
198
+ const entry = {
199
+ lastCheckAt: new Date(attemptStartedAt).toISOString(),
200
+ registry: registry.identity,
201
+ ...(latestVersion === undefined ? {} : { latestVersion }),
202
+ };
203
+ await publishMonotonically(entry, attemptStartedAt);
204
+ // Live fetch failed: keep the on-disk pin for notices, but do not
205
+ // return it as a confirmed refresh so `gitnexus update` cannot install
206
+ // from an unconfirmed cache.
207
+ if (fetched === undefined)
208
+ return null;
209
+ return stateFrom(entry, installedVersionOf(options));
210
+ }
211
+ catch (error) {
212
+ updateLogger.debug({ code: error.code }, 'Update check failed open');
213
+ return null;
214
+ }
215
+ finally {
216
+ if (release)
217
+ await release().catch(() => { });
218
+ }
219
+ };
220
+ refreshInFlight = run().finally(() => {
221
+ refreshInFlight = null;
222
+ });
223
+ return refreshInFlight;
224
+ }
225
+ /**
226
+ * Start an immediate evaluation and repeat on the cache TTL cadence. Timers
227
+ * never keep the process alive; refresh() supplies process-wide single-flight.
228
+ */
229
+ export function armUpdateRefreshScheduler(onState, options = {}) {
230
+ let stopped = false;
231
+ let timer;
232
+ const cycle = async () => {
233
+ if (stopped)
234
+ return;
235
+ const now = options.now?.() ?? Date.now();
236
+ let entry = null;
237
+ try {
238
+ const registry = normalizedRegistry();
239
+ entry = await readCache(registry.identity);
240
+ if (!entry || !isUpdateCacheFresh(entry.lastCheckAt, now)) {
241
+ await refresh({ ...options, now });
242
+ entry = await readCache(registry.identity);
243
+ }
244
+ }
245
+ catch {
246
+ // The public scheduler shares the service's fail-open contract.
247
+ }
248
+ // Derive state from the entry already read above; a full evaluate() here
249
+ // would re-run guards and re-read the cache on every tick.
250
+ let state = null;
251
+ try {
252
+ state =
253
+ !entry || !(await isNotifierActive(options))
254
+ ? null
255
+ : stateFrom(entry, installedVersionOf(options));
256
+ }
257
+ catch {
258
+ state = null;
259
+ }
260
+ if (!stopped)
261
+ onState(state);
262
+ if (!stopped) {
263
+ timer = setTimeout(() => void cycle(), nextSchedulerDelay(entry, now));
264
+ timer.unref();
265
+ }
266
+ };
267
+ timer = setTimeout(() => void cycle(), 0);
268
+ timer.unref();
269
+ return () => {
270
+ stopped = true;
271
+ if (timer)
272
+ clearTimeout(timer);
273
+ };
274
+ }
@@ -5,14 +5,12 @@
5
5
  * Supports multiple indexed repositories via a global registry.
6
6
  * LadybugDB connections are opened lazily per repo on first query.
7
7
  */
8
+ import { isTestFilePath } from '../../core/ingestion/utils/test-file-path.js';
8
9
  import { type RegistryEntry, type BranchSummary } from '../../storage/repo-manager.js';
9
10
  import { GroupService } from '../../core/group/service.js';
10
11
  import { type StalenessInfo } from '../../core/git-staleness.js';
11
- /**
12
- * Quick test-file detection for filtering impact results.
13
- * Matches common test file patterns across all supported languages.
14
- */
15
- export declare function isTestFilePath(filePath: string | null | undefined): boolean;
12
+ /** Shared predicate; re-exported so MCP importers keep the old public name. */
13
+ export { isTestFilePath };
16
14
  /** Valid LadybugDB node labels for safe Cypher query construction */
17
15
  export declare const VALID_NODE_LABELS: Set<string>;
18
16
  /** Valid relation types for impact analysis filtering */
@@ -371,10 +369,26 @@ export declare class LocalBackend {
371
369
  * - If only 1 repo, use it
372
370
  * - If 0 or multiple without param, throw with helpful message
373
371
  *
374
- * On a miss, re-reads the registry once in case a new repo was indexed
375
- * while the MCP server was running.
372
+ * Re-reads the registry before an omitted implicit target or after an
373
+ * explicit miss, so long-running servers see newly indexed repositories.
376
374
  */
377
375
  resolveRepo(repoParam?: string, branch?: string): Promise<RepoHandle>;
376
+ /**
377
+ * Internal resolver variant for CLI/MCP tool routing and discovery.
378
+ * - If repoParam is given, match by name or path
379
+ * - If only 1 repo, use it
380
+ * - If multiple repos exist and repoParam is omitted, callers may opt in to
381
+ * the registered repo containing process.cwd()
382
+ * - If 0 repos exist, or cwd cannot disambiguate multiple repos, throw
383
+ *
384
+ * Omitted-repo resolution re-reads the registry before accepting any
385
+ * implicit target, including a cached singleton. A caller that just obtained
386
+ * a fresh registry snapshot may disable that refresh explicitly.
387
+ */
388
+ selectToolRepository(repoParam?: string, branch?: string, options?: {
389
+ allowCwdDefault?: boolean;
390
+ refreshRegistry?: boolean;
391
+ }): Promise<RepoHandle>;
378
392
  /**
379
393
  * Re-point a resolved repo handle at a specific branch index (#2106).
380
394
  *
@@ -409,12 +423,13 @@ export declare class LocalBackend {
409
423
  */
410
424
  private resolveRepoFromCache;
411
425
  /**
412
- * Prefer the indexed repo whose path matches the git root of process.cwd().
426
+ * Match process.cwd() against indexed repositories.
413
427
  *
414
- * In MCP stdio server mode, `process.cwd()` is the server's launch directory,
415
- * not the agent client's cwd. If the server was started from an unrelated
416
- * directory, `getGitRoot` returns null and duplicate-name resolution throws
417
- * {@link RegistryAmbiguousTargetError} — callers should pass an absolute path.
428
+ * Explicit duplicate aliases use exact Git-root matching only. Omitted
429
+ * read-only calls opt into deepest containing-path selection. In that mode a
430
+ * candidate must not sit above cwd's Git root, so an unindexed nested checkout
431
+ * cannot fall through to an indexed ancestor. The `.git` ancestor fallback
432
+ * preserves that boundary when the git executable is unavailable.
418
433
  */
419
434
  private pickRepoHandleForCwd;
420
435
  private handleToRegistryEntry;
@@ -842,4 +857,3 @@ export declare class LocalBackend {
842
857
  queryProcessDetail(name: string, repoName?: string): Promise<any>;
843
858
  disconnect(): Promise<void>;
844
859
  }
845
- export {};