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
@@ -12,11 +12,14 @@
12
12
  */
13
13
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
14
14
  import type { LocalBackend } from './local/local-backend.js';
15
+ import { McpRepositoryPolicy } from './repository-policy.js';
15
16
  /**
16
17
  * Create a configured MCP Server with all handlers registered.
17
18
  * Transport-agnostic — caller connects the desired transport.
18
19
  */
19
- export declare function createMCPServer(backend: LocalBackend): Server;
20
+ export declare function createMCPServer(backend: LocalBackend, options?: {
21
+ repositoryPolicy?: McpRepositoryPolicy;
22
+ }): Server;
20
23
  /** Conventional 128 + signal-number exit codes for graceful termination. */
21
24
  export declare const SHUTDOWN_EXIT_CODES: {
22
25
  readonly SIGINT: 130;
@@ -34,5 +37,5 @@ type SignalRegistrar = (event: 'SIGINT' | 'SIGTERM', listener: (...args: unknown
34
37
  * mapping can be unit-tested without touching the real process.
35
38
  */
36
39
  export declare function installSignalShutdown(shutdown: (exitCode?: number) => unknown, on?: SignalRegistrar): void;
37
- export declare function startMCPServer(backend: LocalBackend): Promise<void>;
40
+ export declare function startMCPServer(backend: LocalBackend, repositoryPolicy?: McpRepositoryPolicy): Promise<void>;
38
41
  export {};
@@ -17,6 +17,9 @@ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSche
17
17
  import { GITNEXUS_TOOLS } from './tools.js';
18
18
  import { installGlobalStdoutSentinel } from './stdio-context.js';
19
19
  import { getResourceDefinitions, getResourceTemplates, readResource } from './resources.js';
20
+ import { assertMcpReadOnlyResource, assertMcpReadOnlyToolCall, filterMcpReadOnlyResourceContent, MCP_READ_ONLY_TOOLS, readOnlyResourceTemplateAllowed, resolveMcpReadOnlyMode, toolForReadOnlyMcp, } from './read-only-policy.js';
21
+ import { createMcpRepositoryPolicy, McpRepositoryPolicy, mcpRepositoryPolicyConfigured, } from './repository-policy.js';
22
+ import { applyMcpMaxTokens, resolveMcpMaxTokens, withoutMcpBudgetArg } from './output-budget.js';
20
23
  /**
21
24
  * Next-step hints appended to tool responses.
22
25
  *
@@ -60,7 +63,13 @@ function getNextStepHint(toolName, args) {
60
63
  * Create a configured MCP Server with all handlers registered.
61
64
  * Transport-agnostic — caller connects the desired transport.
62
65
  */
63
- export function createMCPServer(backend) {
66
+ export function createMCPServer(backend, options = {}) {
67
+ const readOnly = resolveMcpReadOnlyMode();
68
+ if (!options.repositoryPolicy && mcpRepositoryPolicyConfigured()) {
69
+ throw new Error('Configured MCP repository policy must be validated before server creation.');
70
+ }
71
+ const repositoryPolicy = options.repositoryPolicy ?? McpRepositoryPolicy.unrestricted();
72
+ const scopedBackend = repositoryPolicy.scopeBackend(backend);
64
73
  const require = createRequire(import.meta.url);
65
74
  const pkgVersion = require('../../package.json').version;
66
75
  const server = new Server({
@@ -87,7 +96,8 @@ export function createMCPServer(backend) {
87
96
  });
88
97
  // Handle list resource templates request (for dynamic resources)
89
98
  server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
90
- const templates = getResourceTemplates();
99
+ const templates = getResourceTemplates().filter((template) => readOnlyResourceTemplateAllowed(template.uriTemplate, readOnly) &&
100
+ repositoryPolicy.resourceTemplateAllowed(template.uriTemplate));
91
101
  return {
92
102
  resourceTemplates: templates.map((t) => ({
93
103
  uriTemplate: t.uriTemplate,
@@ -101,7 +111,9 @@ export function createMCPServer(backend) {
101
111
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
102
112
  const { uri } = request.params;
103
113
  try {
104
- const content = await readResource(uri, backend);
114
+ assertMcpReadOnlyResource(uri, readOnly);
115
+ repositoryPolicy.assertResourceUri(uri);
116
+ const content = filterMcpReadOnlyResourceContent(await readResource(uri, scopedBackend), readOnly);
105
117
  return {
106
118
  contents: [
107
119
  {
@@ -126,7 +138,10 @@ export function createMCPServer(backend) {
126
138
  });
127
139
  // Handle list tools request
128
140
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
129
- tools: GITNEXUS_TOOLS.map((tool) => ({
141
+ tools: GITNEXUS_TOOLS.filter((tool) => (!readOnly || MCP_READ_ONLY_TOOLS.has(tool.name)) &&
142
+ repositoryPolicy.toolAllowed(tool.name))
143
+ .map((tool) => toolForReadOnlyMcp(repositoryPolicy.toolForMcp(tool), readOnly))
144
+ .map((tool) => ({
130
145
  name: tool.name,
131
146
  description: tool.description,
132
147
  inputSchema: tool.inputSchema,
@@ -136,15 +151,19 @@ export function createMCPServer(backend) {
136
151
  // Handle tool calls — append next-step hints to guide agent workflow
137
152
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
138
153
  const { name, arguments: args } = request.params;
154
+ let maxTokens;
139
155
  try {
140
- const result = await backend.callTool(name, args);
156
+ const typedArgs = args;
157
+ assertMcpReadOnlyToolCall(name, typedArgs, readOnly);
158
+ maxTokens = resolveMcpMaxTokens(name, typedArgs);
159
+ const result = await scopedBackend.callTool(name, withoutMcpBudgetArg(typedArgs));
141
160
  const resultText = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
142
161
  const hint = getNextStepHint(name, args);
143
162
  return {
144
163
  content: [
145
164
  {
146
165
  type: 'text',
147
- text: resultText + hint,
166
+ text: applyMcpMaxTokens(resultText + hint, maxTokens),
148
167
  },
149
168
  ],
150
169
  };
@@ -155,7 +174,7 @@ export function createMCPServer(backend) {
155
174
  content: [
156
175
  {
157
176
  type: 'text',
158
- text: `Error: ${message}`,
177
+ text: applyMcpMaxTokens(`Error: ${message}`, maxTokens),
159
178
  },
160
179
  ],
161
180
  isError: true,
@@ -265,8 +284,9 @@ export function installSignalShutdown(shutdown, on = (event, listener) => {
265
284
  on('SIGINT', () => void shutdown(SHUTDOWN_EXIT_CODES.SIGINT));
266
285
  on('SIGTERM', () => void shutdown(SHUTDOWN_EXIT_CODES.SIGTERM));
267
286
  }
268
- export async function startMCPServer(backend) {
269
- const server = createMCPServer(backend);
287
+ export async function startMCPServer(backend, repositoryPolicy) {
288
+ const validatedRepositoryPolicy = repositoryPolicy ?? (await createMcpRepositoryPolicy(backend));
289
+ const server = createMCPServer(backend, { repositoryPolicy: validatedRepositoryPolicy });
270
290
  // Idempotent global sentinel install. cli/mcp.ts calls this first thing
271
291
  // (before warnMissingOptionalGrammars / backend.init can emit to stdout);
272
292
  // calling again here is a safety net for direct callers of startMCPServer
@@ -24,14 +24,6 @@ export interface ToolDefinition {
24
24
  minLength?: number;
25
25
  }>;
26
26
  required: string[];
27
- /**
28
- * JSON-Schema `anyOf` for cross-property constraints `required` cannot express
29
- * — e.g. "at least one of route/file". Forwarded verbatim to clients by the
30
- * server's ListTools handler, so MCP clients see the constraint.
31
- */
32
- anyOf?: Array<{
33
- required: string[];
34
- }>;
35
27
  };
36
28
  }
37
29
  /**
package/dist/mcp/tools.js CHANGED
@@ -141,6 +141,11 @@ SERVICE: optional monorepo path prefix (POSIX-style, case-sensitive segments). W
141
141
  description: 'Include full symbol source code (default: false)',
142
142
  default: false,
143
143
  },
144
+ maxTokens: {
145
+ type: 'integer',
146
+ minimum: 1,
147
+ description: 'Maximum estimated tokens in the complete formatted MCP response. Explicit request overrides GITNEXUS_MCP_DEFAULT_MAX_TOKENS.',
148
+ },
144
149
  repo: {
145
150
  type: 'string',
146
151
  description: 'Indexed repository name or path, or group mode "@<groupName>" / "@<groupName>/<memberPath>" (member path keys from group.yaml). Omit when only one indexed repo exists.',
@@ -253,6 +258,10 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
253
258
  description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup)',
254
259
  },
255
260
  file_path: { type: 'string', description: 'File path to disambiguate common names' },
261
+ file: {
262
+ type: 'string',
263
+ description: 'Compatibility alias for file_path; values must agree when both are present',
264
+ },
256
265
  kind: {
257
266
  type: 'string',
258
267
  description: "Kind filter to disambiguate common names (e.g. 'Function', 'Class', 'Method', 'Interface', 'Constructor')",
@@ -262,6 +271,11 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
262
271
  description: 'Include full symbol source code (default: false)',
263
272
  default: false,
264
273
  },
274
+ maxTokens: {
275
+ type: 'integer',
276
+ minimum: 1,
277
+ description: 'Maximum estimated tokens in the complete formatted MCP response. Explicit request overrides GITNEXUS_MCP_DEFAULT_MAX_TOKENS.',
278
+ },
265
279
  repo: {
266
280
  type: 'string',
267
281
  description: 'Indexed repository name or path, or group mode "@<groupName>" / "@<groupName>/<memberPath>". Omit if only one repo is indexed.',
@@ -379,7 +393,7 @@ MODE (opt-in): "callgraph" (default) walks symbol→symbol edges (CALLS/IMPORTS/
379
393
 
380
394
  STATEMENT-ANCHORED PDG SLICE: with mode:'pdg', pass "line" (1-based source line within the target symbol) to seed the dependence slice on the statement at that line and return what depends on it in affectedStatements (line + text). Inter-procedural symbols are still reported through interproceduralByDepth/pdgInterprocedural and the compatibility byDepth bucket. Without "line", pdg returns whole-symbol inter-procedural reach plus local whole-symbol PDG diagnostics.
381
395
 
382
- PDG OUTPUT CONTRACT: every mode:'pdg' result (success, empty, degraded, or error) carries pdgResultVersion:1 — a stable discriminator for external consumers that bumps on any breaking change to the PDG result shape (distinct from the DB schema version). Successful PDG results include mode:'pdg', a full target envelope (id/name/type/filePath), affectedStatements, affectedStatementCount, interproceduralByDepth/pdgInterprocedural for cross-function reach, compatibility byDepth/byDepthCounts, risk:'UNKNOWN', and a note describing the unified contract. Degraded PDG results (no-layer, sub-layer-missing, unknown) keep mode:'pdg', pdgResultVersion:1, target metadata when the target resolves, risk:'UNKNOWN', note/remediation, and empty byDepth parity fields — never a false-safe zero. If depth and limit both bound the slice, truncatedByReasons reports both causes while truncatedBy remains scalar.
396
+ PDG OUTPUT CONTRACT: every mode:'pdg' result (success, empty, degraded, or error) carries pdgResultVersion:2 — a stable discriminator for external consumers that bumps on any breaking change to the PDG result shape (distinct from the DB schema version). Successful PDG results include mode:'pdg', a full target envelope (id/name/type/filePath), affectedStatements, affectedStatementCount, interproceduralByDepth/pdgInterprocedural for cross-function reach, compatibility byDepth/byDepthCounts, risk:'UNKNOWN', and a note describing the unified contract. Degraded PDG results (no-layer, sub-layer-missing, unknown) keep mode:'pdg', pdgResultVersion:2, target metadata when the target resolves, risk:'UNKNOWN', note/remediation, and empty byDepth parity fields — never a false-safe zero. If depth and limit both bound the slice, truncatedByReasons reports both causes while truncatedBy remains scalar.
383
397
 
384
398
  WHEN TO USE: Before making code changes — especially refactoring, renaming, or modifying shared code. Shows what would break.
385
399
  AFTER THIS: Review d=1 items (WILL BREAK). Use context() on high-risk symbols.
@@ -413,6 +427,14 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
413
427
  type: 'object',
414
428
  properties: {
415
429
  target: { type: 'string', description: 'Name of function, class, or file to analyze' },
430
+ name: {
431
+ type: 'string',
432
+ description: 'Compatibility alias for target; all supplied target aliases must agree',
433
+ },
434
+ symbol: {
435
+ type: 'string',
436
+ description: 'Compatibility alias for target; all supplied target aliases must agree',
437
+ },
416
438
  target_uid: {
417
439
  type: 'string',
418
440
  description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup, skips target resolution)',
@@ -503,6 +525,11 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
503
525
  description: 'When true, returns target, summary, risk, byDepthCounts, affected_processes, and affected_modules — omits byDepth. Single-repo only; ignored in group mode (@groupName). Use for hub symbols to get actionable signal without output explosion.',
504
526
  default: false,
505
527
  },
528
+ maxTokens: {
529
+ type: 'integer',
530
+ minimum: 1,
531
+ description: 'Maximum estimated tokens in the complete formatted MCP response. Explicit request overrides GITNEXUS_MCP_DEFAULT_MAX_TOKENS.',
532
+ },
506
533
  timeoutMs: {
507
534
  type: 'number',
508
535
  description: 'Wall-clock budget in milliseconds for the Phase-1 local impact leg (default 30000)',
@@ -516,7 +543,7 @@ SERVICE: optional monorepo path prefix (case-sensitive path segments). When "rep
516
543
  maximum: 3600000,
517
544
  },
518
545
  },
519
- required: ['target', 'direction'],
546
+ required: ['direction'],
520
547
  },
521
548
  },
522
549
  {
@@ -699,9 +726,6 @@ Response shape is keyed on how many routes match, not on the data: exactly one m
699
726
  repo: { type: 'string', description: 'Repository name or path.' },
700
727
  },
701
728
  required: [],
702
- // Exactly one lookup key is needed, but either works (route wins if both
703
- // are passed) — so the structural constraint is "at least one of route/file".
704
- anyOf: [{ required: ['route'] }, { required: ['file'] }],
705
729
  },
706
730
  },
707
731
  {
@@ -804,6 +828,76 @@ DESTINATION TRACE (cross-repo): for an "@groupName" trace, OMIT to/to_uid/to_fil
804
828
  required: [],
805
829
  },
806
830
  },
831
+ {
832
+ name: 'move_entries',
833
+ description: `List Move/Aptos entry points (compiler-sourced).
834
+
835
+ WHEN TO USE: To enumerate a Move package's external surface - \`entry\` functions (transaction entry points) and \`#[view]\` functions (read-only queries). Filter by module, kind, or attribute.
836
+
837
+ Returns: { entries: [{ name, qualifiedName, filePath, isEntry, isView, visibility, acquires, attributes, returnType }], count }.`,
838
+ annotations: READ_ONLY_TOOL_ANNOTATIONS,
839
+ inputSchema: {
840
+ type: 'object',
841
+ properties: {
842
+ module: {
843
+ type: 'string',
844
+ description: 'Filter to one module (qualified name, e.g. 0xa::coin).',
845
+ },
846
+ kind: {
847
+ type: 'string',
848
+ enum: ['entry', 'view', 'inline', 'native'],
849
+ description: 'Restrict to a single entry kind. Omit for entry+view.',
850
+ },
851
+ attribute: {
852
+ type: 'string',
853
+ description: 'Only functions carrying this attribute (e.g. "view").',
854
+ },
855
+ repo: { type: 'string', description: 'Repository name or path.' },
856
+ },
857
+ required: [],
858
+ },
859
+ },
860
+ {
861
+ name: 'move_resources',
862
+ description: `List Move/Aptos resources (structs/enums with the \`key\` ability) and their accessors.
863
+
864
+ WHEN TO USE: To audit on-chain storage — which resources exist and which functions read/write/acquire them (from READS_RESOURCE / WRITES_RESOURCE / ACQUIRES edges).
865
+
866
+ Returns: { resources: [{ name, qualifiedName, filePath, abilities, fieldList, accessors: [{ caller, reason, isEntry, isView }] }], count }.`,
867
+ annotations: READ_ONLY_TOOL_ANNOTATIONS,
868
+ inputSchema: {
869
+ type: 'object',
870
+ properties: {
871
+ module: { type: 'string', description: 'Filter to one module (qualified name).' },
872
+ repo: { type: 'string', description: 'Repository name or path.' },
873
+ },
874
+ required: [],
875
+ },
876
+ },
877
+ {
878
+ name: 'move_impact',
879
+ description: `Blast radius for a Move/Aptos symbol over Move edges (CALLS / READS_RESOURCE / WRITES_RESOURCE / ACQUIRES / USES_TYPE).
880
+
881
+ WHEN TO USE: BEFORE editing a Move function or resource/type. Reports callers, resource-access dependents, and signature type users. Restricts the generic impact traversal to Move semantic edges.`,
882
+ annotations: READ_ONLY_TOOL_ANNOTATIONS,
883
+ inputSchema: {
884
+ type: 'object',
885
+ properties: {
886
+ target: {
887
+ type: 'string',
888
+ description: 'Move symbol (qualified name preferred, e.g. 0xa::coin::transfer).',
889
+ },
890
+ direction: {
891
+ type: 'string',
892
+ enum: ['upstream', 'downstream'],
893
+ description: 'upstream = who depends on the target (default); downstream = what the target depends on.',
894
+ },
895
+ maxDepth: { type: 'number', description: 'Traversal depth (default 3).' },
896
+ repo: { type: 'string', description: 'Repository name or path.' },
897
+ },
898
+ required: ['target'],
899
+ },
900
+ },
807
901
  ];
808
902
  /**
809
903
  * Per-repo tools that accept an optional `branch` scope (#2106). Single source
@@ -827,6 +921,9 @@ const BRANCH_SCOPED_TOOLS = new Set([
827
921
  'shape_check',
828
922
  'api_impact',
829
923
  'trace',
924
+ 'move_entries',
925
+ 'move_resources',
926
+ 'move_impact',
830
927
  ]);
831
928
  for (const tool of GITNEXUS_TOOLS) {
832
929
  if (!BRANCH_SCOPED_TOOLS.has(tool.name))
@@ -30,6 +30,7 @@ export interface AnalyzeJob {
30
30
  export declare class JobManager {
31
31
  private jobs;
32
32
  private children;
33
+ private abortControllers;
33
34
  private timeouts;
34
35
  private emitter;
35
36
  private cleanupTimer;
@@ -45,6 +46,8 @@ export declare class JobManager {
45
46
  updateJob(id: string, update: Partial<Pick<AnalyzeJob, 'status' | 'progress' | 'error' | 'repoPath' | 'repoName' | 'completedAt'>>): void;
46
47
  /** Register a child process for a job — enables cancellation and timeout. */
47
48
  registerChild(jobId: string, child: ChildProcess): void;
49
+ /** Register cancellable in-process work for a job. */
50
+ registerAbortController(jobId: string, controller: AbortController): void;
48
51
  /** Cancel a running job — sends SIGTERM to child process. */
49
52
  cancelJob(jobId: string, reason?: string): boolean;
50
53
  /** Subscribe to progress events for a job. Returns unsubscribe function. */
@@ -16,6 +16,7 @@ const JOB_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
16
16
  export class JobManager {
17
17
  jobs = new Map();
18
18
  children = new Map();
19
+ abortControllers = new Map();
19
20
  timeouts = new Map();
20
21
  emitter = new EventEmitter();
21
22
  cleanupTimer;
@@ -72,6 +73,7 @@ export class JobManager {
72
73
  Object.assign(job, update);
73
74
  if (this.isTerminal(job.status)) {
74
75
  job.completedAt = job.completedAt ?? Date.now();
76
+ this.abortControllers.delete(id);
75
77
  }
76
78
  // Emit exactly one event per updateJob call to prevent SSE double-write
77
79
  if (update.status === 'complete' || update.status === 'failed') {
@@ -107,6 +109,15 @@ export class JobManager {
107
109
  }
108
110
  });
109
111
  }
112
+ /** Register cancellable in-process work for a job. */
113
+ registerAbortController(jobId, controller) {
114
+ const job = this.jobs.get(jobId);
115
+ if (!job || this.isTerminal(job.status)) {
116
+ controller.abort();
117
+ return;
118
+ }
119
+ this.abortControllers.set(jobId, controller);
120
+ }
110
121
  /** Cancel a running job — sends SIGTERM to child process. */
111
122
  cancelJob(jobId, reason) {
112
123
  const job = this.jobs.get(jobId);
@@ -116,6 +127,8 @@ export class JobManager {
116
127
  if (child) {
117
128
  child.kill('SIGTERM');
118
129
  }
130
+ this.abortControllers.get(jobId)?.abort();
131
+ this.abortControllers.delete(jobId);
119
132
  this.updateJob(jobId, {
120
133
  status: 'failed',
121
134
  error: reason || 'Analysis cancelled',
@@ -134,6 +147,9 @@ export class JobManager {
134
147
  child.kill('SIGTERM');
135
148
  }
136
149
  this.children.clear();
150
+ for (const controller of this.abortControllers.values())
151
+ controller.abort();
152
+ this.abortControllers.clear();
137
153
  // Clear all timeouts
138
154
  for (const timer of this.timeouts.values()) {
139
155
  clearTimeout(timer);
@@ -150,6 +166,7 @@ export class JobManager {
150
166
  for (const [id, job] of this.jobs) {
151
167
  if (this.isTerminal(job.status) && job.completedAt && now - job.completedAt > JOB_TTL_MS) {
152
168
  this.jobs.delete(id);
169
+ this.abortControllers.delete(id);
153
170
  }
154
171
  }
155
172
  }
@@ -17,6 +17,12 @@ export interface LaunchDeps {
17
17
  };
18
18
  acquireRepoLock: (key: string) => string | null;
19
19
  releaseRepoLock: (key: string) => void;
20
+ /**
21
+ * Drops the server's cached LadybugDB handle (closeLbug). The worker
22
+ * process rewrites the repo's DB files on disk, so a connection opened
23
+ * before the rewrite keeps reading the pre-rewrite state until evicted.
24
+ */
25
+ closeDbHandle: () => Promise<void>;
20
26
  }
21
27
  export interface LaunchOptions {
22
28
  force?: boolean;
@@ -10,16 +10,83 @@
10
10
  * path is resolved relative to `import.meta.url`.
11
11
  */
12
12
  import path from 'path';
13
+ import { existsSync, statSync } from 'node:fs';
13
14
  import { fork } from 'child_process';
14
15
  import { fileURLToPath, pathToFileURL } from 'url';
15
16
  import { createRequire } from 'node:module';
16
- import { getStoragePath } from '../storage/repo-manager.js';
17
+ import { canonicalizePath, getStoragePath, INDEX_METADATA_FILE, listRegisteredRepos, registryPathEquals, } from '../storage/repo-manager.js';
17
18
  import { logger } from '../core/logger.js';
18
19
  const _require = createRequire(import.meta.url);
19
20
  const MAX_WORKER_RETRIES = 2;
21
+ /**
22
+ * The worker reports `complete` over IPC before its on-disk finalization
23
+ * (LadybugDB checkpoint + native handle release + metadata write) is visible
24
+ * at `getStoragePath(targetPath)` — observed up to ~6.5s behind the IPC
25
+ * message. Opening the database inside that window is what the pre-IPC
26
+ * ordering was meant to prevent and is actively dangerous: reads fail with
27
+ * binder errors or return an empty graph, the open can quarantine the
28
+ * in-flight WAL, and the native layer racing the rewrite has crashed the
29
+ * whole server (SIGSEGV-class exit, no output) on slow CI runners.
30
+ */
31
+ const FINALIZE_SETTLE_TIMEOUT_MS = 60_000;
32
+ const FINALIZE_SETTLE_POLL_MS = 200;
33
+ /**
34
+ * Resolve once the analyzed repo's index is settled at `storagePath`: the
35
+ * LadybugDB file and metadata both exist AND were (re)written by THIS job
36
+ * (mtime >= jobStartMs — bare existence is not enough, a re-analysis leaves
37
+ * the previous index in place while it works), and no transient WAL/shadow/
38
+ * checkpoint sidecars remain (the worker's native close has finished).
39
+ *
40
+ * Never rejects. Timing out logs and proceeds (pre-gate behavior) rather
41
+ * than failing a job whose analysis genuinely succeeded — e.g. a no-op
42
+ * non-force analyze legitimately rewrites nothing.
43
+ */
44
+ /**
45
+ * Look up the analyzed repo's registered storage path. The request's
46
+ * user-provided path is used only as a comparison key; the filesystem probes
47
+ * below run against the registry's own `storagePath` — the server-owned
48
+ * record readers resolve through, and not a user-controlled value
49
+ * (CodeQL js/path-injection).
50
+ */
51
+ const registeredStoragePath = async (targetPath) => {
52
+ const target = canonicalizePath(path.resolve(targetPath));
53
+ const entries = await listRegisteredRepos();
54
+ const entry = entries.find((e) => registryPathEquals(canonicalizePath(e.path), target));
55
+ return entry?.storagePath ?? null;
56
+ };
57
+ const waitForSettledIndex = async (targetPath, jobStartMs) => {
58
+ const settled = (storagePath) => {
59
+ try {
60
+ const lbugStat = statSync(path.join(storagePath, 'lbug'));
61
+ const metaStat = statSync(path.join(storagePath, INDEX_METADATA_FILE));
62
+ return (lbugStat.mtimeMs >= jobStartMs &&
63
+ metaStat.mtimeMs >= jobStartMs &&
64
+ ['lbug.wal', 'lbug.shadow', 'lbug.wal.checkpoint'].every((f) => !existsSync(path.join(storagePath, f))));
65
+ }
66
+ catch {
67
+ return false; // not written yet
68
+ }
69
+ };
70
+ const deadline = Date.now() + FINALIZE_SETTLE_TIMEOUT_MS;
71
+ for (;;) {
72
+ // Re-resolved each round: the worker registers the repo as part of the
73
+ // finalization this gate is waiting out.
74
+ const storagePath = await registeredStoragePath(targetPath);
75
+ if (storagePath && settled(storagePath))
76
+ return;
77
+ if (Date.now() > deadline) {
78
+ logger.warn({ targetPath }, 'analyze finalization not visible after timeout; completing job anyway');
79
+ return;
80
+ }
81
+ await new Promise((resolve) => setTimeout(resolve, FINALIZE_SETTLE_POLL_MS));
82
+ }
83
+ };
20
84
  export function createLaunchAnalysisWorker(deps) {
21
- const { jobManager, backend, acquireRepoLock, releaseRepoLock } = deps;
85
+ const { jobManager, backend, acquireRepoLock, releaseRepoLock, closeDbHandle } = deps;
22
86
  return function launchAnalysisWorker(job, targetPath, opts) {
87
+ // For waitForSettledIndex: files (re)written by this job have mtimes at or
88
+ // after this instant. Taken before the fork so no worker write predates it.
89
+ const jobStartMs = Date.now();
23
90
  // Acquire shared repo lock (keyed on storagePath to match embed handler)
24
91
  const analyzeLockKey = getStoragePath(targetPath);
25
92
  const lockErr = acquireRepoLock(analyzeLockKey);
@@ -67,10 +134,17 @@ export function createLaunchAnalysisWorker(deps) {
67
134
  }
68
135
  else if (msg.type === 'complete') {
69
136
  releaseRepoLock(analyzeLockKey);
70
- // Reinitialize backend BEFORE marking complete — ensures the new repo
71
- // is queryable when the client receives the SSE complete event.
72
- backend
73
- .init()
137
+ // Before marking complete: (1) wait for the worker's on-disk
138
+ // finalization to settle (see waitForSettledIndex), (2) evict the
139
+ // cached DB handle — same invalidation DELETE /api/repo performs, a
140
+ // handle opened before the rewrite reads pre-rewrite state — and
141
+ // only then (3) reinitialize the backend. This makes the ordering
142
+ // comment below true in practice: the repo is actually queryable
143
+ // when the client receives the SSE complete event.
144
+ waitForSettledIndex(targetPath, jobStartMs)
145
+ .then(() => closeDbHandle())
146
+ .catch(() => { }) // best-effort: eviction failure must not fail the job
147
+ .then(() => backend.init())
74
148
  .then(() => {
75
149
  jobManager.updateJob(job.id, { status: 'complete', repoName: msg.result.repoName });
76
150
  })
@@ -84,6 +158,8 @@ export function createLaunchAnalysisWorker(deps) {
84
158
  }
85
159
  else if (msg.type === 'error') {
86
160
  releaseRepoLock(analyzeLockKey);
161
+ // A failed (force) analyze may still have rewritten DB files first.
162
+ void closeDbHandle().catch(() => { });
87
163
  jobManager.updateJob(job.id, { status: 'failed', error: msg.message });
88
164
  }
89
165
  });
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import type { AnalyzeOptions } from '../core/run-analyze.js';
16
16
  import type { WorkerMessage } from './analyze-worker.js';
17
+ import type { AnalyzerRunnerIdentity } from '../storage/repo-manager.js';
17
18
  export interface WorkerAnalysisDeps {
18
19
  runFullAnalysis: typeof import('../core/run-analyze.js').runFullAnalysis;
19
20
  assertAnalysisFinalized: typeof import('../storage/repo-manager.js').assertAnalysisFinalized;
@@ -32,7 +33,7 @@ export interface WorkerAnalysisDeps {
32
33
  * already claimed the terminal slot — and never throws; the caller schedules
33
34
  * `process.exit` after this resolves.
34
35
  */
35
- export declare function runWorkerAnalysis(repoPath: string, options: AnalyzeOptions, deps: WorkerAnalysisDeps): Promise<void>;
36
+ export declare function runWorkerAnalysis(repoPath: string, options: AnalyzeOptions, deps: WorkerAnalysisDeps, runnerIdentityAtBootstrap?: AnalyzerRunnerIdentity): Promise<void>;
36
37
  /**
37
38
  * Create the single-use terminal-outcome claim shared by the worker's message
38
39
  * handler and its SIGTERM handler. The first call returns `true`; every later
@@ -5,9 +5,12 @@ import { projectAnalyzeResultForIpc } from './analyze-worker-ipc.js';
5
5
  * already claimed the terminal slot — and never throws; the caller schedules
6
6
  * `process.exit` after this resolves.
7
7
  */
8
- export async function runWorkerAnalysis(repoPath, options, deps) {
8
+ export async function runWorkerAnalysis(repoPath, options, deps, runnerIdentityAtBootstrap) {
9
9
  let terminal;
10
10
  try {
11
+ const bootstrapArgs = runnerIdentityAtBootstrap
12
+ ? [runnerIdentityAtBootstrap]
13
+ : [];
11
14
  const result = await deps.runFullAnalysis(repoPath,
12
15
  // This worker force-exits right after reporting, so skip the native close
13
16
  // (it can double-free in LadybugDB's ClientContext destructor after --pdg
@@ -15,7 +18,7 @@ export async function runWorkerAnalysis(repoPath, options, deps) {
15
18
  { ...options, skipNativeCloseOnExit: true }, {
16
19
  onProgress: (phase, percent, message) => deps.send({ type: 'progress', phase, percent, message }),
17
20
  onLog: (message) => deps.send({ type: 'progress', phase: 'log', percent: -1, message }),
18
- });
21
+ }, ...bootstrapArgs);
19
22
  // P2 (#2264): a half-finalized repo — meta.json written but the global
20
23
  // registry entry missing (e.g. a prior collision-aborted run, or a wiped
21
24
  // registry) — must NOT be reported as a successful analysis. Mirror the CLI's
@@ -10,10 +10,7 @@
10
10
  * Child -> Parent: { type: 'complete', result: AnalyzeResult }
11
11
  * Child -> Parent: { type: 'error', message: string }
12
12
  */
13
- import { runFullAnalysis } from '../core/run-analyze.js';
14
13
  import { runWorkerAnalysis, createTerminalClaim } from './analyze-worker-core.js';
15
- import { assertAnalysisFinalized } from '../storage/repo-manager.js';
16
- import { boundedCheckpointBeforeExit } from '../core/lbug/shutdown-helpers.js';
17
14
  function send(msg) {
18
15
  // No try/catch: if the IPC channel is gone, process.send throws
19
16
  // (ERR_IPC_CHANNEL_CLOSED) and that failure must NOT be swallowed. Every caller
@@ -26,6 +23,7 @@ function send(msg) {
26
23
  // terminal send, so a cancel near the finish line can't also report success and a
27
24
  // late SIGTERM can't flip an already-reported job (#2264 P3).
28
25
  const claimTerminal = createTerminalClaim();
26
+ let boundedCheckpointBeforeExit = null;
29
27
  // Catch uncaught exceptions and unhandled rejections — report them to the parent
30
28
  // over IPC (the same channel the analysis path uses), then exit. The report runs
31
29
  // in `try` and the exit in `finally` so a throw from send() on a closed channel
@@ -61,6 +59,10 @@ process.on('SIGTERM', () => {
61
59
  if (claimTerminal()) {
62
60
  send({ type: 'error', message: 'Analysis cancelled (worker received SIGTERM)' });
63
61
  }
62
+ if (!boundedCheckpointBeforeExit) {
63
+ process.exit(0);
64
+ return;
65
+ }
64
66
  void boundedCheckpointBeforeExit({
65
67
  exitCode: 0,
66
68
  onFlushError: (err) => {
@@ -76,16 +78,37 @@ process.on('message', async (msg) => {
76
78
  return;
77
79
  started = true;
78
80
  try {
81
+ // Capture the complete build/dependency receipt before evaluating the
82
+ // analyzer graph or loading LadybugDB. A replacement racing this boundary
83
+ // is compared against this receipt again immediately before metadata commit.
84
+ const identityModule = await import('../core/analyzer-identity.js');
85
+ const prepared = await identityModule.captureAnalyzerIdentityBeforeLoad(import.meta.url, async () => {
86
+ const [analysisModule, repoManager, shutdownHelpers] = await Promise.all([
87
+ import('../core/run-analyze.js'),
88
+ import('../storage/repo-manager.js'),
89
+ import('../core/lbug/shutdown-helpers.js'),
90
+ ]);
91
+ return { analysisModule, repoManager, shutdownHelpers };
92
+ });
93
+ boundedCheckpointBeforeExit = prepared.loaded.shutdownHelpers.boundedCheckpointBeforeExit;
79
94
  // The run → finalize → report contract lives in the side-effect-free
80
95
  // analyze-worker-core seam (unit-testable without this entry module's
81
96
  // process.on side effects). It reports exactly one terminal message and
82
97
  // never throws.
83
98
  await runWorkerAnalysis(msg.repoPath, msg.options, {
84
- runFullAnalysis,
85
- assertAnalysisFinalized,
99
+ runFullAnalysis: prepared.loaded.analysisModule.runFullAnalysis,
100
+ assertAnalysisFinalized: prepared.loaded.repoManager.assertAnalysisFinalized,
86
101
  send,
87
102
  claimTerminal,
88
- });
103
+ }, prepared.runnerIdentity);
104
+ }
105
+ catch (error) {
106
+ if (claimTerminal()) {
107
+ send({
108
+ type: 'error',
109
+ message: error instanceof Error ? error.message : 'Analysis worker bootstrap failed',
110
+ });
111
+ }
89
112
  }
90
113
  finally {
91
114
  // LadybugDB's native module prevents clean exit — force it (same reason the