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
@@ -349,6 +349,49 @@ function runGitNexusCli(cliPath, args, cwd, timeout) {
349
349
  });
350
350
  }
351
351
 
352
+ /**
353
+ * Fallback augmentation for the #2396 path: when a GitNexus process holds the
354
+ * lbug DB write lock the CLI `augment` can't run, so point the agent at the MCP
355
+ * `query` tool instead. Phrased conditionally ("if the MCP tools are live") so it
356
+ * stays truthful on every owner path — a confirmed MCP owner, a `serve` owner, or
357
+ * a fail-closed probe where no server is actually confirmed. `pattern` is embedded
358
+ * verbatim; the caller (sendHookResponse) JSON-escapes it structurally.
359
+ */
360
+ function buildMcpQueryHint(pattern) {
361
+ return (
362
+ `[GitNexus] Local augment is unavailable (the graph DB is held by another ` +
363
+ `GitNexus process). If the GitNexus MCP tools are live in this session, call ` +
364
+ `the GitNexus \`query\` MCP tool (e.g. mcp__gitnexus__query) with ` +
365
+ `search_query "${pattern}".`
366
+ );
367
+ }
368
+
369
+ /**
370
+ * #2396 throttle: emit the MCP-query hint at most once per repo per window, so an
371
+ * owner-locked session isn't nudged on every search. Window (ms) via
372
+ * GITNEXUS_MCP_HINT_THROTTLE_MS (default 10min; 0/invalid disables). Best-effort —
373
+ * any fs error falls back to emitting.
374
+ * ponytail: per-repo mtime marker, shared across concurrent sessions on the same
375
+ * repo; add per-session dedup only if that sharing becomes a problem.
376
+ */
377
+ function shouldEmitMcpHint(gitNexusDir) {
378
+ const raw = process.env.GITNEXUS_MCP_HINT_THROTTLE_MS;
379
+ const windowMs = raw === undefined || raw === '' ? 600000 : Number(raw);
380
+ if (!Number.isFinite(windowMs) || windowMs <= 0) return true;
381
+ const marker = path.join(gitNexusDir, '.mcp-hint-shown');
382
+ try {
383
+ if (Date.now() - fs.statSync(marker).mtimeMs < windowMs) return false;
384
+ } catch {
385
+ /* marker missing/unreadable → emit */
386
+ }
387
+ try {
388
+ fs.writeFileSync(marker, '');
389
+ } catch {
390
+ /* best-effort; still emit */
391
+ }
392
+ return true;
393
+ }
394
+
352
395
  /**
353
396
  * PreToolUse handler — augment searches with graph context.
354
397
  */
@@ -385,18 +428,25 @@ function handlePreToolUse(input) {
385
428
  let result = '';
386
429
  try {
387
430
  if (hasGitNexusServerOwner(gitNexusDir)) {
388
- // Normal skip path: the MCP server owns the DB, so the CLI augment would
389
- // contend on the lock. Stay silent for strict hook runners (issue #1913);
390
- // surface the reason only when diagnostics are explicitly requested.
431
+ // #2396: the MCP server holds the DB write lock, so a competing CLI
432
+ // `augment` would only contend on it (LadybugDB is single-writer). But the
433
+ // session that triggered this hook has the GitNexus MCP tools live — route
434
+ // the augmentation to the agent via additionalContext instead of silently
435
+ // doing nothing. Mirror the skip reason to stderr only under GITNEXUS_DEBUG
436
+ // (strict-runner contract, #1913); the hint itself rides the sanctioned
437
+ // additionalContext stdout channel the successful augment already uses.
391
438
  if (isDebugEnabled()) {
392
439
  process.stderr.write('[GitNexus] augment skipped: MCP server owns DB\n');
393
440
  }
394
- return;
395
- }
396
- const cliPath = resolveCliPath();
397
- const child = runGitNexusCli(cliPath, ['augment', '--', pattern], cwd, 7000);
398
- if (!child.error && child.status === 0) {
399
- result = extractAugmentContext(child.stderr || '');
441
+ if (shouldEmitMcpHint(gitNexusDir)) {
442
+ result = buildMcpQueryHint(pattern);
443
+ }
444
+ } else {
445
+ const cliPath = resolveCliPath();
446
+ const child = runGitNexusCli(cliPath, ['augment', '--', pattern], cwd, 7000);
447
+ if (!child.error && child.status === 0) {
448
+ result = extractAugmentContext(child.stderr || '');
449
+ }
400
450
  }
401
451
  } catch {
402
452
  /* graceful failure */
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.9",
3
+ "version": "1.6.10-aptos.0",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",
@@ -35,7 +35,12 @@
35
35
  "hooks",
36
36
  "scripts",
37
37
  "skills",
38
- "vendor",
38
+ "vendor/leiden",
39
+ "vendor/tree-sitter-c",
40
+ "vendor/tree-sitter-dart",
41
+ "vendor/tree-sitter-kotlin",
42
+ "vendor/tree-sitter-proto",
43
+ "vendor/tree-sitter-swift",
39
44
  "web"
40
45
  ],
41
46
  "scripts": {
@@ -52,11 +57,11 @@
52
57
  "postinstall": "node scripts/build-tree-sitter-grammars.cjs",
53
58
  "assert-publish-coverage": "node scripts/assert-publish-grammar-coverage.cjs",
54
59
  "prepare": "node scripts/build.js",
55
- "prepack": "node scripts/assert-publish-grammar-coverage.cjs && node scripts/build.js"
60
+ "prepack": "node scripts/assert-publish-grammar-coverage.cjs && node scripts/build.js",
61
+ "version": "node scripts/sync-plugin-manifests.mjs"
56
62
  },
57
63
  "dependencies": {
58
- "@huggingface/transformers": "^4.1.0",
59
- "@ladybugdb/core": "^0.18.0",
64
+ "@ladybugdb/core": "^0.18.3",
60
65
  "@modelcontextprotocol/sdk": "^1.0.0",
61
66
  "@scarf/scarf": "^1.4.0",
62
67
  "busboy": "^1.6.0",
@@ -70,13 +75,12 @@
70
75
  "graphology-indices": "^0.17.0",
71
76
  "graphology-utils": "^2.3.0",
72
77
  "ignore": "^7.0.5",
73
- "js-yaml": "^4.1.1",
78
+ "js-yaml": "^5.0.0",
74
79
  "jsonc-parser": "^3.3.1",
75
80
  "mnemonist": "^0.40.3",
76
81
  "node-addon-api": "^8.0.0",
77
82
  "node-gyp-build": "^4.8.0",
78
83
  "onnxruntime-common": "^1.26.0",
79
- "onnxruntime-node": "^1.24.0",
80
84
  "pandemonium": "^2.4.0",
81
85
  "pino": "^10.3.1",
82
86
  "pino-pretty": "^13.1.3",
@@ -93,18 +97,20 @@
93
97
  "tree-sitter-typescript": "^0.23.2",
94
98
  "uuid": "^14.0.0"
95
99
  },
100
+ "optionalDependencies": {
101
+ "@huggingface/transformers": "^4.1.0",
102
+ "onnxruntime-node": "^1.24.0"
103
+ },
96
104
  "devDependencies": {
97
- "@babel/generator": "^7.29.7",
98
- "@babel/parser": "^7.29.7",
99
- "@babel/traverse": "^7.29.7",
100
- "@babel/types": "^7.29.7",
105
+ "@babel/generator": "^8.0.0",
106
+ "@babel/parser": "^8.0.0",
107
+ "@babel/traverse": "^8.0.0",
108
+ "@babel/types": "^8.0.0",
101
109
  "@types/busboy": "^1.5.4",
102
110
  "@types/cli-progress": "^3.11.6",
103
111
  "@types/cors": "^2.8.17",
104
112
  "@types/express": "^5.0.6",
105
- "@types/js-yaml": "^4.0.9",
106
- "@types/node": "^25.6.0",
107
- "@types/uuid": "^11.0.0",
113
+ "@types/node": "^26.0.0",
108
114
  "@vitest/coverage-v8": "^4.0.18",
109
115
  "gitnexus-shared": "file:../gitnexus-shared",
110
116
  "tsx": "^4.0.0",
@@ -117,6 +123,6 @@
117
123
  }
118
124
  },
119
125
  "engines": {
120
- "node": ">=22.0.0"
126
+ "node": "^22.18.0 || >=24.11.0"
121
127
  }
122
128
  }
@@ -30,8 +30,16 @@ const PLATFORM_LOGIC = [
30
30
  'test/unit/setup-jsonc.test.ts',
31
31
  'test/unit/setup-codex.test.ts',
32
32
  'test/unit/setup-antigravity.test.ts',
33
+ 'test/integration/setup-uninstall-roundtrip.test.ts',
33
34
  'test/unit/resolve-invocation.test.ts',
35
+ // CLI-spawn entry-point resolution; its path-separator assertion (cli[/\\]index)
36
+ // must exercise the Windows backslash branch, so run it on the OS matrix (#2394).
37
+ 'test/unit/cli-entry.test.ts',
34
38
  'test/unit/platform-capabilities.test.ts',
39
+ // getconf page-size probe: explicit process.platform gate (win32 short-circuit)
40
+ // plus a live-probe test whose only real non-4K coverage is macos-arm64's
41
+ // 16 KiB pages — the exact hardware class #1231 targets (#2424 review).
42
+ 'test/unit/lbug-config-pagesize.test.ts',
35
43
  'test/unit/worker-pool-windows-quarantine.test.ts',
36
44
  'test/unit/lbug-pool-fts-load.test.ts',
37
45
  'test/unit/repo-manager.test.ts',
@@ -42,12 +50,38 @@ const PLATFORM_LOGIC = [
42
50
  'test/unit/cursor-hook.test.ts',
43
51
  'test/unit/sidecar-recovery.test.ts',
44
52
  'test/unit/pool-wal-recovery.test.ts',
53
+ 'test/unit/lbug-adapter-wal-schema.test.ts',
45
54
  'test/unit/detect-changes-worktree.test.ts',
46
55
  'test/unit/eval-server-bind-restriction.test.ts',
47
56
  'test/unit/ignore-service.test.ts',
48
57
  'test/unit/group/bridge-db.test.ts',
49
58
  'test/unit/group/bridge-db-edge.test.ts',
50
59
  'test/unit/onnxruntime-node-resolver.test.ts',
60
+ // Windows cmd.exe arg-quoting + compose-and-spawn for the npm install (#2372):
61
+ // the quoting rules and win32 single-string spawn shape are OS-sensitive, so
62
+ // exercise them on real windows-latest. The spawn-shape/path tests force their
63
+ // platform branch and derive expected paths via the real fns, so they pass on
64
+ // any host (see the platform stubs + resolve() in the test file).
65
+ 'test/unit/embedding-runtime-install.test.ts',
66
+ // Real-spawn arg-delivery round-trip: proves the install spawn delivers args
67
+ // to the child intact on each platform — win32 via the cmd.exe -> .cmd %* ->
68
+ // node chain (real cmd.exe, not just our model), macos/linux via the no-shell
69
+ // array form. Runs on every platform (the ubuntu suite covers Linux; this
70
+ // registration adds windows + macos).
71
+ 'test/unit/embedding-install-arg-delivery.test.ts',
72
+ // Lazy MoveFlow install coordinates, PowerShell invocation data, archive
73
+ // streaming, and filesystem leases all vary across operating systems.
74
+ 'test/unit/move/install-move-flow.test.ts',
75
+ // Structural FTS-extension classifier against REAL binaries (#2374): on this
76
+ // matrix `process.execPath` / `lbugjs.node` are a real PE (windows) and Mach-O
77
+ // (macos), so the header parsing is proven on genuine binaries, not synthetic
78
+ // buffers (the ubuntu suite covers the ELF path).
79
+ 'test/integration/extension-binary-real.test.ts',
80
+ // Server repo resolver branches on path shape (path.isAbsolute, backslash
81
+ // detection) and canonicalizePath/realpathSync, all of which differ between
82
+ // POSIX and Windows — the fail-closed path-claim semantics must hold on the
83
+ // real windows-latest path implementation (#2419/#2420).
84
+ 'test/unit/server-api-repo-resolution.test.ts',
51
85
  ];
52
86
 
53
87
  // Native LadybugDB integration tests — exercise the @ladybugdb/core
@@ -64,6 +98,9 @@ const LBUG_NATIVE = [
64
98
  'test/integration/lbug-orphan-sidecar-recovery.test.ts',
65
99
  'test/integration/lbug-readonly-init.test.ts',
66
100
  'test/integration/lbug-non-ascii-path.test.ts',
101
+ // Shared Move/non-Move rows must retain their schema defaults through the
102
+ // real native database on every supported desktop platform.
103
+ 'test/integration/move-mixed-language-roundtrip.test.ts',
67
104
  // Cross-repo trace e2e: builds two real lbug indexes + a real bridge and
68
105
  // opens them through the pool adapter (native addon + bridge file locking).
69
106
  // Windows is skipped in-file (describeReopen) due to the bridge reopen lock.
@@ -77,6 +114,21 @@ const LBUG_NATIVE = [
77
114
  'test/integration/analyze-wal-checkpoint-failure.test.ts',
78
115
  'test/integration/fts-stemmer-sweep.test.ts',
79
116
  'test/integration/lbug-multiwriter-deadlock.test.ts',
117
+ // #2409 batched incremental writeback: chunked IN-list DETACH DELETEs +
118
+ // backslash quote escaping against the REAL native engine — the failing
119
+ // environment for #2409 was Windows, so the write pattern must be proven
120
+ // on the windows-latest native addon, not just Ubuntu.
121
+ 'test/integration/lbug-delete-nodes-for-files.test.ts',
122
+ // #2409 defect 2: dirty-flag recovery parks lbug.wal/.shadow (rename next
123
+ // to a live native DB, rm-then-rename over an existing parked copy) before
124
+ // any open — rename semantics are exactly what differs on Windows.
125
+ 'test/unit/incremental-dirty-recovery.test.ts',
126
+ // #2623: the incremental writeback must load VECTOR before the CodeEmbedding
127
+ // join-delete, and the blocked path must escalate instead of crashing. The
128
+ // win32 VECTOR gate was removed in the same PR, so this ordering must be
129
+ // proven on the windows-latest native addon, not just Ubuntu. Budget: ~25s
130
+ // on Linux → expect ~2min on the slowest Windows shard.
131
+ 'test/unit/incremental-vector-extension-ordering.test.ts',
80
132
  ];
81
133
 
82
134
  // Process spawning and CLI tests — exercise child_process with real
@@ -87,6 +139,10 @@ const SPAWN_CLI = [
87
139
  'test/integration/cli-limit-e2e.test.ts',
88
140
  'test/integration/hooks-e2e.test.ts',
89
141
  'test/integration/skills-e2e.test.ts',
142
+ // Spawns the real CLI across hermetic HOME/USERPROFILE homes to exercise the
143
+ // FTS extension lifecycle — the #2374 bug was Windows-reported, so this must
144
+ // run on the Windows/macOS matrix, not just the Ubuntu full suite.
145
+ 'test/integration/fts-extension-e2e.test.ts',
90
146
  'test/integration/server-http-startup.test.ts',
91
147
  'test/integration/mcp/server-startup.test.ts',
92
148
  'test/integration/analyze-heap-oom-e2e.test.ts',
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Install the LadybugDB FTS and VECTOR extensions into the shared home (~/.lbdb)
3
+ * up front, so every test in a sharded CI run finds them regardless of shard.
4
+ *
5
+ * FTS-dependent tests split two ways: the LOAD-path gate (skipUnlessFtsAvailable)
6
+ * self-installs on miss, but the FILE-path gate (requireFtsResourceOrSkip, e.g.
7
+ * extension-binary-real.test.ts) resolves the extension path at module load and
8
+ * cannot self-install. Sharding (and the balancing sequencer) can drop such a
9
+ * test into a shard with no installer sibling — this step removes that ordering
10
+ * dependency by installing FTS once before vitest starts. `auto` is LOAD-first,
11
+ * so a cache-warmed extension costs no network.
12
+ *
13
+ * Best-effort: exits 0 on failure (offline etc.) — the per-test gates still
14
+ * hard-fail under GITNEXUS_REQUIRE_FTS=1 if FTS is genuinely unavailable, which
15
+ * is where the loud signal belongs.
16
+ */
17
+ import { mkdtempSync, rmSync } from 'node:fs';
18
+ import { tmpdir } from 'node:os';
19
+ import { join } from 'node:path';
20
+ import {
21
+ initLbug,
22
+ loadFTSExtension,
23
+ loadVectorExtension,
24
+ closeLbug,
25
+ } from '../src/core/lbug/lbug-adapter.js';
26
+
27
+ const dir = mkdtempSync(join(tmpdir(), 'gn-ensure-fts-'));
28
+ try {
29
+ await initLbug(join(dir, 'ensure-fts.lbug'));
30
+ const ok = await loadFTSExtension(undefined, { policy: 'auto' });
31
+ console.log(ok ? 'FTS extension ready.' : 'FTS extension unavailable (continuing).');
32
+ // VECTOR rides the same pre-install (#2623): the win32 gate is gone, so the
33
+ // vector suites genuinely run on Windows/macOS — installing once here means
34
+ // every sharded test process LOADs from ~/.lbdb instead of racing its own
35
+ // out-of-process INSTALL (bounded 15s each when the server is unreachable).
36
+ const vec = await loadVectorExtension(undefined, { policy: 'auto' });
37
+ console.log(vec ? 'VECTOR extension ready.' : 'VECTOR extension unavailable (continuing).');
38
+ } catch (err) {
39
+ console.warn(`ensure-fts: skipped (${err instanceof Error ? err.message : String(err)})`);
40
+ } finally {
41
+ await closeLbug();
42
+ rmSync(dir, { recursive: true, force: true });
43
+ }
@@ -3,9 +3,41 @@ import fs from 'node:fs/promises';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { createRequire } from 'node:module';
6
+ import { pathToFileURL } from 'node:url';
6
7
 
7
8
  const EXTENSION_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/;
8
9
 
10
+ // Positive on-disk-corruption signatures. `FORCE INSTALL` re-downloads even when
11
+ // a file is already present; we only want that when the LOAD error proves the
12
+ // existing file is bad (truncated/wrong-platform, #2374). For everything else —
13
+ // a missing file (plain INSTALL downloads it), or a permanent non-file failure a
14
+ // re-download can never fix (missing runtime dep: "cannot open shared object") —
15
+ // plain INSTALL avoids re-downloading ~2 MB on every analyze run forever.
16
+ // Exported so a parity test keeps this byte-identical to the copy in
17
+ // src/core/lbug/extension-load-error.ts (this `.mjs` cannot import that `.ts`), #2383 F5b.
18
+ export const FILE_CORRUPTION_SIGNATURES = [
19
+ /invalid elf/i,
20
+ /file too short/i,
21
+ /not a valid/i,
22
+ /bad magic/i,
23
+ /wrong architecture/i,
24
+ /mach-o/i,
25
+ /truncat/i,
26
+ ];
27
+
28
+ /**
29
+ * Decide the install verb from the LOAD error that triggered this install.
30
+ * `FORCE INSTALL` only when the error positively indicates file-level breakage;
31
+ * otherwise plain `INSTALL` (missing file, missing-dependency dlopen failure,
32
+ * or unknown/absent error).
33
+ */
34
+ export function chooseInstallVerb(loadError) {
35
+ if (loadError && FILE_CORRUPTION_SIGNATURES.some((re) => re.test(loadError))) {
36
+ return 'FORCE INSTALL';
37
+ }
38
+ return 'INSTALL';
39
+ }
40
+
9
41
  function parseLbugMaxDbSize(raw) {
10
42
  const parsed = raw ? Number(raw) : NaN;
11
43
  if (!Number.isFinite(parsed) || parsed <= 0) {
@@ -14,28 +46,54 @@ function parseLbugMaxDbSize(raw) {
14
46
  return Math.floor(parsed);
15
47
  }
16
48
 
17
- async function installDuckDbExtension(extensionName, verifyOnly = false) {
18
- if (!extensionName || !EXTENSION_NAME_PATTERN.test(extensionName)) {
19
- throw new Error(`Invalid DuckDB extension name: ${extensionName ?? '<missing>'}`);
20
- }
21
-
22
- const require = createRequire(import.meta.url);
23
- const lbugModule = require('@ladybugdb/core');
24
- const lbug = lbugModule.default ?? lbugModule;
49
+ function resolveMaxDbSize() {
25
50
  // argv[3] is the optional positional size; ignore it when it is actually a
26
51
  // flag token (e.g. `--verify-only`) and fall back to the env default.
27
52
  const sizeArg =
28
53
  process.argv[3] && !process.argv[3].startsWith('--') ? process.argv[3] : undefined;
29
- const lbugMaxDbSize = parseLbugMaxDbSize(sizeArg ?? process.env.GITNEXUS_LBUG_MAX_DB_SIZE);
54
+ return parseLbugMaxDbSize(sizeArg ?? process.env.GITNEXUS_LBUG_MAX_DB_SIZE);
55
+ }
56
+
57
+ /** Open a scratch LadybugDB and return its connection plus a disposer. */
58
+ async function defaultConnect(lbugMaxDbSize) {
59
+ const require = createRequire(import.meta.url);
60
+ const lbugModule = require('@ladybugdb/core');
61
+ const lbug = lbugModule.default ?? lbugModule;
30
62
 
31
63
  const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-ext-install-'));
32
64
  const dbPath = path.join(tmpDir, 'install.lbug');
33
- let db;
34
- let conn;
65
+ const db = new lbug.Database(dbPath, 0, false, false, lbugMaxDbSize);
66
+ const conn = new lbug.Connection(db);
67
+ return {
68
+ conn,
69
+ dispose: async () => {
70
+ await conn.close().catch(() => {});
71
+ await db.close().catch(() => {});
72
+ await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
73
+ },
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Install (or verify) an optional LadybugDB extension in this short-lived process.
79
+ *
80
+ * @param {string} extensionName
81
+ * @param {object} [options]
82
+ * @param {boolean} [options.verifyOnly] LOAD-only Docker build gate — no install.
83
+ * @param {string} [options.loadError] The parent's LOAD failure; selects the verb.
84
+ * @param {(size: number) => Promise<{conn: {query: (sql: string) => Promise<unknown>}, dispose: () => Promise<void>}>} [options.connect]
85
+ * Connection factory; injectable for offline unit tests.
86
+ */
87
+ export async function installDuckDbExtension(extensionName, options = {}) {
88
+ const { verifyOnly = false, loadError, connect } = options;
89
+ if (!extensionName || !EXTENSION_NAME_PATTERN.test(extensionName)) {
90
+ throw new Error(`Invalid DuckDB extension name: ${extensionName ?? '<missing>'}`);
91
+ }
92
+
93
+ const makeConnection = connect ?? (() => defaultConnect(resolveMaxDbSize()));
94
+ const { conn, dispose } = await makeConnection();
35
95
 
36
96
  try {
37
- db = new lbug.Database(dbPath, 0, false, false, lbugMaxDbSize);
38
- conn = new lbug.Connection(db);
39
97
  if (verifyOnly) {
40
98
  // Prove a previously-baked extension is resolvable by a FRESH process
41
99
  // under the current HOME (the runtime `LOAD EXTENSION` path) — no INSTALL,
@@ -46,19 +104,22 @@ async function installDuckDbExtension(extensionName, verifyOnly = false) {
46
104
  `[install-ext] LOAD-only verify OK for '${extensionName}' (HOME=${process.env.HOME})`,
47
105
  );
48
106
  } else {
49
- await conn.query(`INSTALL ${extensionName}`);
107
+ // Plain INSTALL is a no-op when the file already exists; escalate to FORCE
108
+ // only when the LOAD error proves the on-disk file is broken (#2374).
109
+ await conn.query(`${chooseInstallVerb(loadError)} ${extensionName}`);
50
110
  }
51
111
  } finally {
52
- if (conn) await conn.close().catch(() => {});
53
- if (db) await db.close().catch(() => {});
54
- await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
112
+ await dispose();
55
113
  }
56
114
  }
57
115
 
58
- installDuckDbExtension(
59
- process.argv[2] ?? process.env.GITNEXUS_LBUG_EXTENSION_NAME,
60
- process.argv.includes('--verify-only'),
61
- ).catch((err) => {
62
- console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));
63
- process.exitCode = 1;
64
- });
116
+ // Only run when executed directly — imported (e.g. by unit tests) it stays inert.
117
+ if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
118
+ installDuckDbExtension(process.argv[2] ?? process.env.GITNEXUS_LBUG_EXTENSION_NAME, {
119
+ verifyOnly: process.argv.includes('--verify-only'),
120
+ loadError: process.env.GITNEXUS_LBUG_EXTENSION_LOAD_ERROR,
121
+ }).catch((err) => {
122
+ console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));
123
+ process.exitCode = 1;
124
+ });
125
+ }
@@ -14,6 +14,7 @@ import fs from 'fs';
14
14
  import path from 'path';
15
15
  import { fileURLToPath } from 'url';
16
16
  import { ALL_CROSS_PLATFORM } from './cross-platform-tests.js';
17
+ import { parseShardArg } from './shard-arg.js';
17
18
 
18
19
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
19
20
  const ROOT = path.resolve(__dirname, '..');
@@ -27,18 +28,72 @@ if (missing.length > 0) {
27
28
  process.exit(1);
28
29
  }
29
30
 
30
- console.log(`Running ${ALL_CROSS_PLATFORM.length} platform-sensitive tests...\n`);
31
+ // Optional sharding (CI): `--shard=<i>/<n>` splits the fixed file list across
32
+ // parallel matrix shards so each runner processes ~1/n of it. Passed straight
33
+ // through to vitest, which partitions the *given* files deterministically. The
34
+ // Windows runner is ~5x slower than macOS/Linux on this spawn-heavy suite (~50
35
+ // CLI/worker process spawns), so a single shard was creeping past the watchdog
36
+ // below; sharding keeps each runner well under it (see ci-tests.yml matrix).
37
+ // Fail loud on a malformed --shard arg (mirrors the missing-files check above):
38
+ // a silently-dropped shard flag would run the full unsharded suite and re-trip
39
+ // the watchdog. Kept outside the execFileSync try/catch below so the message
40
+ // isn't swallowed by that catch's watchdog-only branch.
41
+ let shardArg: string | undefined;
42
+ try {
43
+ shardArg = parseShardArg(process.argv.slice(2));
44
+ } catch (err) {
45
+ console.error(err instanceof Error ? err.message : String(err));
46
+ process.exit(1);
47
+ }
48
+
49
+ // Per-shard watchdog, default 15 min. Sharding splits the file list by COUNT, not
50
+ // runtime, so the heaviest spawn suites can cluster on one shard — what this
51
+ // bounds is the *busiest* shard, not an even 1/n of wall-clock. The busiest
52
+ // Windows shard has grown to the default (14m57s on the v1.6.10-rc.19 green
53
+ // run, one observed timeout since — #2449), so CI raises the budget to 20
54
+ // minutes via GITNEXUS_CROSS_PLATFORM_TIMEOUT_MINUTES; the default stays 15
55
+ // for local runs.
56
+ const DEFAULT_TIMEOUT_MIN = 15;
57
+ const timeoutMinutes = Number.parseInt(
58
+ process.env.GITNEXUS_CROSS_PLATFORM_TIMEOUT_MINUTES ?? String(DEFAULT_TIMEOUT_MIN),
59
+ 10,
60
+ );
61
+ const timeoutMs =
62
+ Number.isFinite(timeoutMinutes) && timeoutMinutes > 0
63
+ ? timeoutMinutes * 60 * 1000
64
+ : DEFAULT_TIMEOUT_MIN * 60 * 1000;
65
+
66
+ console.log(
67
+ `Running ${ALL_CROSS_PLATFORM.length} platform-sensitive tests` +
68
+ `${shardArg ? ` (${shardArg.replace('--shard=', 'shard ')})` : ''}...\n`,
69
+ );
31
70
 
71
+ const startedAt = Date.now();
32
72
  try {
33
- execFileSync('npx', ['vitest', 'run', ...ALL_CROSS_PLATFORM], {
73
+ execFileSync('npx', ['vitest', 'run', ...ALL_CROSS_PLATFORM, ...(shardArg ? [shardArg] : [])], {
34
74
  cwd: ROOT,
35
75
  stdio: 'inherit',
36
- timeout: 15 * 60 * 1000,
76
+ timeout: timeoutMs,
37
77
  shell: true,
38
78
  });
39
- } catch (err: any) {
40
- if (err.killed || err.signal) {
41
- console.error('vitest timed out after 15 minutes');
79
+ } catch (err) {
80
+ // execFileSync sets `killed`/`signal` when the watchdog above kills vitest.
81
+ const e = err as {
82
+ killed?: boolean;
83
+ signal?: NodeJS.Signals | null;
84
+ status?: number | null;
85
+ code?: string;
86
+ };
87
+ if (e.killed || e.signal) {
88
+ console.error(`vitest timed out after ${Math.round(timeoutMs / 60_000)} minutes`);
42
89
  }
90
+ // #2449: Windows shards have died with a bare `status: null`, empty stderr
91
+ // and nothing to triage from. Always leave the child's exit facts behind.
92
+ const elapsedSec = Math.round((Date.now() - startedAt) / 1000);
93
+ console.error(
94
+ `vitest exited abnormally: status=${e.status ?? 'null'} signal=${e.signal ?? 'none'} ` +
95
+ `killed=${e.killed === true} spawnCode=${e.code ?? 'none'} elapsed=${elapsedSec}s ` +
96
+ `budget=${Math.round(timeoutMs / 60_000)}min`,
97
+ );
43
98
  process.exit(1);
44
99
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resolves the optional `--shard=<index>/<total>` argument for
3
+ * `run-cross-platform.ts`.
4
+ *
5
+ * Extracted as a pure, side-effect-free function so the branch logic is
6
+ * unit-testable without the script's top-level `execFileSync` (see
7
+ * `test/unit/shard-arg.test.ts`). Mirrors the `computeSpawnPrefix` extraction
8
+ * pattern in `test/helpers/cli-entry.ts`.
9
+ */
10
+
11
+ const SHARD_RE = /^--shard=\d+\/\d+$/;
12
+
13
+ /**
14
+ * Returns the matched `--shard=<index>/<total>` token (e.g. `--shard=1/3`) to
15
+ * pass straight through to vitest, or `undefined` when no shard arg is present.
16
+ *
17
+ * Fails loud on a shard-shaped-but-malformed arg (e.g. `--shard=1`, `--shard`,
18
+ * `--shard=abc`): a silently-ignored malformed arg would drop the shard flag and
19
+ * run the full unsharded ~50-spawn suite, re-arming the Windows watchdog timeout
20
+ * with no signal. Only `--shard` / `--shard=…` args are inspected, so unrelated
21
+ * flags (including a hypothetical `--shardx=…`) pass through untouched.
22
+ */
23
+ export function parseShardArg(argv: string[]): string | undefined {
24
+ const shardArgs = argv.filter((a) => a === '--shard' || a.startsWith('--shard='));
25
+ const malformed = shardArgs.find((a) => !SHARD_RE.test(a));
26
+ if (malformed !== undefined) {
27
+ throw new Error(`Malformed --shard arg '${malformed}' — expected --shard=<index>/<total>`);
28
+ }
29
+ return shardArgs[0];
30
+ }