gitnexus 1.6.11-rc.8 → 1.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. package/README.md +95 -26
  2. package/dist/_shared/graph/types.d.ts +81 -2
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
  5. package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
  6. package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
  7. package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
  8. package/dist/_shared/language-detection.d.ts.map +1 -1
  9. package/dist/_shared/language-detection.js +2 -0
  10. package/dist/_shared/language-detection.js.map +1 -1
  11. package/dist/_shared/languages.d.ts +2 -1
  12. package/dist/_shared/languages.d.ts.map +1 -1
  13. package/dist/_shared/languages.js +1 -0
  14. package/dist/_shared/languages.js.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.d.ts +2 -2
  16. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  17. package/dist/_shared/lbug/schema-constants.js +4 -0
  18. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  19. package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
  20. package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -0
  21. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  22. package/dist/_shared/scope-resolution/language-classification.d.ts +3 -0
  23. package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
  24. package/dist/_shared/scope-resolution/language-classification.js +4 -0
  25. package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
  26. package/dist/_shared/scope-resolution/reference-site.d.ts +10 -0
  27. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  28. package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
  29. package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
  30. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  31. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  32. package/dist/_shared/scope-resolution/types.d.ts +15 -0
  33. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  34. package/dist/cli/ai-context.d.ts +4 -0
  35. package/dist/cli/ai-context.js +90 -14
  36. package/dist/cli/analyze-config.js +14 -0
  37. package/dist/cli/analyze-options.d.ts +14 -0
  38. package/dist/cli/analyze-watch.d.ts +20 -0
  39. package/dist/cli/analyze-watch.js +434 -0
  40. package/dist/cli/analyze.js +27 -9
  41. package/dist/cli/auto-sync.d.ts +1 -0
  42. package/dist/cli/auto-sync.js +107 -0
  43. package/dist/cli/command-banner.d.ts +15 -0
  44. package/dist/cli/command-banner.js +42 -0
  45. package/dist/cli/detect-changes-format.js +21 -0
  46. package/dist/cli/doctor.d.ts +7 -0
  47. package/dist/cli/doctor.js +14 -0
  48. package/dist/cli/group.js +7 -1
  49. package/dist/cli/help-i18n.js +4 -0
  50. package/dist/cli/i18n/en.d.ts +18 -3
  51. package/dist/cli/i18n/en.js +18 -3
  52. package/dist/cli/i18n/resources.d.ts +33 -3
  53. package/dist/cli/i18n/zh-CN.d.ts +15 -0
  54. package/dist/cli/i18n/zh-CN.js +18 -3
  55. package/dist/cli/index.js +34 -7
  56. package/dist/cli/mcp.d.ts +15 -0
  57. package/dist/cli/mcp.js +44 -0
  58. package/dist/cli/optional-grammars.d.ts +3 -2
  59. package/dist/cli/optional-grammars.js +19 -3
  60. package/dist/cli/setup.js +41 -15
  61. package/dist/cli/update-notice.d.ts +34 -0
  62. package/dist/cli/update-notice.js +91 -0
  63. package/dist/cli/update.d.ts +21 -0
  64. package/dist/cli/update.js +93 -0
  65. package/dist/cli/watch.d.ts +1 -20
  66. package/dist/cli/watch.js +5 -371
  67. package/dist/core/analysis-feature-registry.d.ts +2 -0
  68. package/dist/core/analysis-feature-registry.js +15 -0
  69. package/dist/core/analyzer-identity.js +21 -3
  70. package/dist/core/auto-sync/analysis-worker-launch.d.ts +30 -0
  71. package/dist/core/auto-sync/analysis-worker-launch.js +166 -0
  72. package/dist/core/auto-sync/config.d.ts +33 -0
  73. package/dist/core/auto-sync/config.js +320 -0
  74. package/dist/core/auto-sync/index.d.ts +6 -0
  75. package/dist/core/auto-sync/index.js +6 -0
  76. package/dist/core/auto-sync/path-security.d.ts +9 -0
  77. package/dist/core/auto-sync/path-security.js +251 -0
  78. package/dist/core/auto-sync/repo.d.ts +1 -0
  79. package/dist/core/auto-sync/repo.js +6 -0
  80. package/dist/core/auto-sync/runner.d.ts +44 -0
  81. package/dist/core/auto-sync/runner.js +428 -0
  82. package/dist/core/auto-sync/starter.d.ts +50 -0
  83. package/dist/core/auto-sync/starter.js +497 -0
  84. package/dist/core/auto-sync/state.d.ts +37 -0
  85. package/dist/core/auto-sync/state.js +119 -0
  86. package/dist/core/group/config-parser.js +8 -1
  87. package/dist/core/group/cross-impact.d.ts +3 -0
  88. package/dist/core/group/cross-impact.js +36 -4
  89. package/dist/core/group/extractors/http-patterns/java.js +22 -8
  90. package/dist/core/group/extractors/http-patterns/kotlin.js +86 -31
  91. package/dist/core/group/extractors/http-patterns/node.js +145 -8
  92. package/dist/core/group/extractors/http-patterns/python.js +11 -7
  93. package/dist/core/group/extractors/http-route-extractor.js +63 -17
  94. package/dist/core/group/extractors/java-workspace-extractor.js +244 -31
  95. package/dist/core/group/group-lock.js +5 -6
  96. package/dist/core/group/normalization.d.ts +38 -1
  97. package/dist/core/group/normalization.js +59 -3
  98. package/dist/core/group/service.d.ts +11 -0
  99. package/dist/core/group/service.js +13 -1
  100. package/dist/core/group/storage.js +2 -2
  101. package/dist/core/group/sync.d.ts +24 -1
  102. package/dist/core/group/sync.js +46 -8
  103. package/dist/core/group/types.d.ts +13 -0
  104. package/dist/core/incremental/derived-writeback.d.ts +36 -0
  105. package/dist/core/incremental/derived-writeback.js +68 -0
  106. package/dist/core/incremental/spring-config-drift.d.ts +12 -0
  107. package/dist/core/incremental/spring-config-drift.js +46 -0
  108. package/dist/core/incremental/subgraph-extract.d.ts +7 -4
  109. package/dist/core/incremental/subgraph-extract.js +30 -5
  110. package/dist/core/ingestion/asyncapi/document.d.ts +226 -0
  111. package/dist/core/ingestion/asyncapi/document.js +758 -0
  112. package/dist/core/ingestion/asyncapi/protocol.d.ts +79 -0
  113. package/dist/core/ingestion/asyncapi/protocol.js +203 -0
  114. package/dist/core/ingestion/call-extractors/configs/zig.d.ts +2 -0
  115. package/dist/core/ingestion/call-extractors/configs/zig.js +4 -0
  116. package/dist/core/ingestion/call-extractors/zig-static-gating.d.ts +100 -0
  117. package/dist/core/ingestion/call-extractors/zig-static-gating.js +319 -0
  118. package/dist/core/ingestion/call-processor.js +3 -1
  119. package/dist/core/ingestion/class-extractors/configs/zig.d.ts +2 -0
  120. package/dist/core/ingestion/class-extractors/configs/zig.js +32 -0
  121. package/dist/core/ingestion/class-extractors/generic.js +4 -1
  122. package/dist/core/ingestion/class-types.d.ts +6 -2
  123. package/dist/core/ingestion/destination-key.d.ts +59 -0
  124. package/dist/core/ingestion/destination-key.js +61 -0
  125. package/dist/core/ingestion/entry-point-scoring.d.ts +6 -2
  126. package/dist/core/ingestion/entry-point-scoring.js +8 -44
  127. package/dist/core/ingestion/export-detection.d.ts +37 -0
  128. package/dist/core/ingestion/export-detection.js +60 -0
  129. package/dist/core/ingestion/field-extractors/configs/zig.d.ts +8 -0
  130. package/dist/core/ingestion/field-extractors/configs/zig.js +49 -0
  131. package/dist/core/ingestion/field-extractors/generic.d.ts +1 -1
  132. package/dist/core/ingestion/field-extractors/generic.js +12 -1
  133. package/dist/core/ingestion/frameworks/spring/actuator-runtime.d.ts +26 -0
  134. package/dist/core/ingestion/frameworks/spring/actuator-runtime.js +843 -0
  135. package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +5 -0
  136. package/dist/core/ingestion/frameworks/spring/analysis-features.js +9 -0
  137. package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +8 -1
  138. package/dist/core/ingestion/frameworks/spring/argument-facts.d.ts +80 -0
  139. package/dist/core/ingestion/frameworks/spring/argument-facts.js +85 -0
  140. package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +1 -0
  141. package/dist/core/ingestion/frameworks/spring/config-bindings.js +2 -1
  142. package/dist/core/ingestion/frameworks/spring/destinations.d.ts +539 -0
  143. package/dist/core/ingestion/frameworks/spring/destinations.js +840 -0
  144. package/dist/core/ingestion/frameworks/spring/dynamic-lookups.d.ts +22 -0
  145. package/dist/core/ingestion/frameworks/spring/dynamic-lookups.js +124 -0
  146. package/dist/core/ingestion/frameworks/spring/message-producers.d.ts +78 -0
  147. package/dist/core/ingestion/frameworks/spring/message-producers.js +90 -0
  148. package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +29 -0
  149. package/dist/core/ingestion/frameworks/spring/vendor-prefixes.d.ts +7 -0
  150. package/dist/core/ingestion/frameworks/spring/vendor-prefixes.js +22 -0
  151. package/dist/core/ingestion/import-resolvers/configs/zig.d.ts +13 -0
  152. package/dist/core/ingestion/import-resolvers/configs/zig.js +26 -0
  153. package/dist/core/ingestion/import-resolvers/zig.d.ts +34 -0
  154. package/dist/core/ingestion/import-resolvers/zig.js +193 -0
  155. package/dist/core/ingestion/language-config.d.ts +177 -0
  156. package/dist/core/ingestion/language-config.js +719 -0
  157. package/dist/core/ingestion/language-provider.d.ts +178 -1
  158. package/dist/core/ingestion/language-provider.js +22 -0
  159. package/dist/core/ingestion/languages/csharp/razor-view-components.d.ts +62 -0
  160. package/dist/core/ingestion/languages/csharp/razor-view-components.js +954 -0
  161. package/dist/core/ingestion/languages/csharp/resolution-config.d.ts +3 -0
  162. package/dist/core/ingestion/languages/csharp/resolution-config.js +6 -1
  163. package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -0
  164. package/dist/core/ingestion/languages/index.d.ts +1 -0
  165. package/dist/core/ingestion/languages/index.js +2 -0
  166. package/dist/core/ingestion/languages/java/analysis-features.d.ts +1 -1
  167. package/dist/core/ingestion/languages/java/analysis-features.js +14 -6
  168. package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +8 -0
  169. package/dist/core/ingestion/languages/java/capture-side-channel.js +34 -0
  170. package/dist/core/ingestion/languages/java/captures.js +22 -1
  171. package/dist/core/ingestion/languages/java/lombok-synthesizer.d.ts +42 -0
  172. package/dist/core/ingestion/languages/java/lombok-synthesizer.js +439 -0
  173. package/dist/core/ingestion/languages/java/scope-resolver.js +2 -0
  174. package/dist/core/ingestion/languages/java/spring-actuator.d.ts +2 -0
  175. package/dist/core/ingestion/languages/java/spring-actuator.js +62 -0
  176. package/dist/core/ingestion/languages/java/spring-di.d.ts +17 -1
  177. package/dist/core/ingestion/languages/java/spring-di.js +44 -2
  178. package/dist/core/ingestion/languages/java/spring-dynamic-lookup.d.ts +8 -0
  179. package/dist/core/ingestion/languages/java/spring-dynamic-lookup.js +62 -0
  180. package/dist/core/ingestion/languages/java/spring-message-producers.d.ts +20 -0
  181. package/dist/core/ingestion/languages/java/spring-message-producers.js +83 -0
  182. package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +11 -1
  183. package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +13 -3
  184. package/dist/core/ingestion/languages/java.js +18 -8
  185. package/dist/core/ingestion/languages/jvm/accessor-synthesis.d.ts +99 -0
  186. package/dist/core/ingestion/languages/jvm/accessor-synthesis.js +173 -0
  187. package/dist/core/ingestion/languages/jvm/beanspec.d.ts +17 -0
  188. package/dist/core/ingestion/languages/jvm/beanspec.js +42 -0
  189. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
  190. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +50 -0
  191. package/dist/core/ingestion/languages/kotlin/captures.js +24 -1
  192. package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.d.ts +26 -0
  193. package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.js +417 -0
  194. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +4 -0
  195. package/dist/core/ingestion/languages/kotlin/spring-actuator.d.ts +4 -0
  196. package/dist/core/ingestion/languages/kotlin/spring-actuator.js +172 -0
  197. package/dist/core/ingestion/languages/kotlin/spring-config-bindings.d.ts +18 -0
  198. package/dist/core/ingestion/languages/kotlin/spring-config-bindings.js +411 -0
  199. package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +51 -1
  200. package/dist/core/ingestion/languages/kotlin/spring-di.js +86 -6
  201. package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.d.ts +8 -0
  202. package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.js +77 -0
  203. package/dist/core/ingestion/languages/kotlin/spring-message-producers.d.ts +17 -0
  204. package/dist/core/ingestion/languages/kotlin/spring-message-producers.js +119 -0
  205. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +16 -0
  206. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +77 -2
  207. package/dist/core/ingestion/languages/kotlin.js +24 -0
  208. package/dist/core/ingestion/languages/python.js +2 -0
  209. package/dist/core/ingestion/languages/rust/query.js +8 -8
  210. package/dist/core/ingestion/languages/zig/captures.d.ts +260 -0
  211. package/dist/core/ingestion/languages/zig/captures.js +2070 -0
  212. package/dist/core/ingestion/languages/zig/index.d.ts +4 -0
  213. package/dist/core/ingestion/languages/zig/index.js +4 -0
  214. package/dist/core/ingestion/languages/zig/interpret.d.ts +36 -0
  215. package/dist/core/ingestion/languages/zig/interpret.js +176 -0
  216. package/dist/core/ingestion/languages/zig/query.d.ts +3 -0
  217. package/dist/core/ingestion/languages/zig/query.js +426 -0
  218. package/dist/core/ingestion/languages/zig/range-binding.d.ts +37 -0
  219. package/dist/core/ingestion/languages/zig/range-binding.js +373 -0
  220. package/dist/core/ingestion/languages/zig/scope-resolver.d.ts +12 -0
  221. package/dist/core/ingestion/languages/zig/scope-resolver.js +58 -0
  222. package/dist/core/ingestion/languages/zig/simple-hooks.d.ts +25 -0
  223. package/dist/core/ingestion/languages/zig/simple-hooks.js +143 -0
  224. package/dist/core/ingestion/languages/zig.d.ts +32 -0
  225. package/dist/core/ingestion/languages/zig.js +130 -0
  226. package/dist/core/ingestion/method-extractors/configs/zig.d.ts +2 -0
  227. package/dist/core/ingestion/method-extractors/configs/zig.js +120 -0
  228. package/dist/core/ingestion/method-extractors/generic.js +16 -4
  229. package/dist/core/ingestion/method-types.d.ts +10 -4
  230. package/dist/core/ingestion/model/field-registry.d.ts +3 -3
  231. package/dist/core/ingestion/model/field-registry.js +11 -7
  232. package/dist/core/ingestion/model/method-registry.d.ts +3 -3
  233. package/dist/core/ingestion/model/method-registry.js +13 -8
  234. package/dist/core/ingestion/model/registration-table.js +3 -0
  235. package/dist/core/ingestion/model/type-registry.js +8 -4
  236. package/dist/core/ingestion/pipeline-phases/di.js +47 -14
  237. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  238. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  239. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +7 -1
  240. package/dist/core/ingestion/pipeline-phases/parse-impl.js +79 -91
  241. package/dist/core/ingestion/pipeline-phases/parse.d.ts +17 -0
  242. package/dist/core/ingestion/pipeline-phases/processes.d.ts +2 -1
  243. package/dist/core/ingestion/pipeline-phases/processes.js +39 -4
  244. package/dist/core/ingestion/pipeline-phases/routes.js +27 -18
  245. package/dist/core/ingestion/pipeline-phases/runner.d.ts +4 -1
  246. package/dist/core/ingestion/pipeline-phases/runner.js +34 -14
  247. package/dist/core/ingestion/pipeline-phases/scan.js +82 -1
  248. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +2 -0
  249. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +8 -0
  250. package/dist/core/ingestion/pipeline-phases/spring-destinations.d.ts +123 -0
  251. package/dist/core/ingestion/pipeline-phases/spring-destinations.js +688 -0
  252. package/dist/core/ingestion/pipeline.d.ts +30 -1
  253. package/dist/core/ingestion/pipeline.js +52 -14
  254. package/dist/core/ingestion/resolve-references.js +5 -0
  255. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +16 -0
  256. package/dist/core/ingestion/route-extractors/constant-resolver.js +10 -0
  257. package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +27 -1
  258. package/dist/core/ingestion/route-extractors/java-const-resolver.js +161 -13
  259. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +12 -18
  260. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +214 -33
  261. package/dist/core/ingestion/route-extractors/kotlin-spring.d.ts +13 -0
  262. package/dist/core/ingestion/route-extractors/kotlin-spring.js +259 -0
  263. package/dist/core/ingestion/route-extractors/python-decorator-handler.d.ts +6 -0
  264. package/dist/core/ingestion/route-extractors/python-decorator-handler.js +16 -0
  265. package/dist/core/ingestion/route-extractors/spring-shared.d.ts +30 -1
  266. package/dist/core/ingestion/route-extractors/spring-shared.js +77 -9
  267. package/dist/core/ingestion/route-extractors/spring.js +9 -5
  268. package/dist/core/ingestion/scope-extractor.js +8 -0
  269. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +62 -0
  270. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +4 -0
  271. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +2 -0
  272. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +28 -0
  273. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +11 -2
  274. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +23 -2
  275. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +24 -3
  276. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +11 -1
  277. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +26 -6
  278. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +11 -0
  279. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +29 -3
  280. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +8 -1
  281. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +35 -9
  282. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -4
  283. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +277 -9
  284. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
  285. package/dist/core/ingestion/scope-resolution/pipeline/run.js +7 -3
  286. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +43 -9
  287. package/dist/core/ingestion/scope-resolution/scope/walkers.js +71 -10
  288. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -0
  289. package/dist/core/ingestion/tree-sitter-queries.js +161 -0
  290. package/dist/core/ingestion/type-extractors/zig.d.ts +2 -0
  291. package/dist/core/ingestion/type-extractors/zig.js +17 -0
  292. package/dist/core/ingestion/utils/ast-helpers.d.ts +40 -1
  293. package/dist/core/ingestion/utils/ast-helpers.js +124 -6
  294. package/dist/core/ingestion/utils/callable-flow-captures.d.ts +9 -0
  295. package/dist/core/ingestion/utils/callable-flow-captures.js +75 -14
  296. package/dist/core/ingestion/utils/test-file-path.d.ts +28 -0
  297. package/dist/core/ingestion/utils/test-file-path.js +87 -0
  298. package/dist/core/ingestion/variable-extractors/configs/zig.d.ts +2 -0
  299. package/dist/core/ingestion/variable-extractors/configs/zig.js +71 -0
  300. package/dist/core/ingestion/workers/parse-worker.js +85 -14
  301. package/dist/core/install-context.d.ts +4 -0
  302. package/dist/core/install-context.js +152 -0
  303. package/dist/core/lbug/csv-generator.d.ts +10 -1
  304. package/dist/core/lbug/csv-generator.js +92 -22
  305. package/dist/core/lbug/graph-emit-sink.d.ts +3 -2
  306. package/dist/core/lbug/graph-emit-sink.js +4 -2
  307. package/dist/core/lbug/lbug-adapter.d.ts +100 -5
  308. package/dist/core/lbug/lbug-adapter.js +236 -24
  309. package/dist/core/lbug/schema.d.ts +6 -5
  310. package/dist/core/lbug/schema.js +84 -22
  311. package/dist/core/net/url-guard.d.ts +6 -0
  312. package/dist/core/net/url-guard.js +147 -0
  313. package/dist/core/package-version.d.ts +5 -0
  314. package/dist/core/package-version.js +10 -0
  315. package/dist/core/run-analyze.d.ts +21 -4
  316. package/dist/core/run-analyze.js +426 -117
  317. package/dist/core/search/fts-indexes.d.ts +19 -1
  318. package/dist/core/search/fts-indexes.js +28 -1
  319. package/dist/core/tree-sitter/parser-loader.js +16 -0
  320. package/dist/core/update-cache.d.ts +39 -0
  321. package/dist/core/update-cache.js +141 -0
  322. package/dist/core/update-check.d.ts +31 -0
  323. package/dist/core/update-check.js +274 -0
  324. package/dist/mcp/local/local-backend.d.ts +27 -13
  325. package/dist/mcp/local/local-backend.js +148 -60
  326. package/dist/mcp/repository-policy.d.ts +5 -1
  327. package/dist/mcp/repository-policy.js +48 -4
  328. package/dist/mcp/resources.js +10 -1
  329. package/dist/mcp/server.js +8 -9
  330. package/dist/mcp/tools.js +32 -22
  331. package/dist/server/analyze-launch.d.ts +2 -0
  332. package/dist/server/analyze-launch.js +2 -0
  333. package/dist/server/analyze-worker-protocol.d.ts +6 -1
  334. package/dist/server/analyze-worker.d.ts +1 -0
  335. package/dist/server/analyze-worker.js +38 -20
  336. package/dist/server/api.d.ts +5 -1
  337. package/dist/server/api.js +105 -88
  338. package/dist/server/git-clone.d.ts +40 -16
  339. package/dist/server/git-clone.js +253 -199
  340. package/dist/server/grep-params.d.ts +18 -0
  341. package/dist/server/grep-params.js +83 -0
  342. package/dist/server/grep-scan.d.ts +23 -0
  343. package/dist/server/grep-scan.js +107 -0
  344. package/dist/server/grep-worker.d.ts +1 -0
  345. package/dist/server/grep-worker.js +12 -0
  346. package/dist/server/mcp-http.d.ts +8 -0
  347. package/dist/server/mcp-http.js +16 -1
  348. package/dist/server/update-controller.d.ts +29 -0
  349. package/dist/server/update-controller.js +82 -0
  350. package/dist/storage/file-lock.d.ts +15 -0
  351. package/dist/storage/file-lock.js +155 -0
  352. package/dist/storage/fs-atomic.d.ts +24 -0
  353. package/dist/storage/fs-atomic.js +86 -2
  354. package/dist/storage/global-dir.d.ts +2 -0
  355. package/dist/storage/global-dir.js +6 -0
  356. package/dist/storage/parse-cache.d.ts +45 -7
  357. package/dist/storage/parse-cache.js +189 -42
  358. package/dist/storage/parsedfile-store.d.ts +41 -60
  359. package/dist/storage/parsedfile-store.js +247 -171
  360. package/dist/storage/repo-manager.d.ts +10 -4
  361. package/dist/storage/repo-manager.js +35 -25
  362. package/dist/storage/repo-meta.d.ts +34 -0
  363. package/dist/storage/v8-sidecar.d.ts +48 -0
  364. package/dist/storage/v8-sidecar.js +347 -0
  365. package/dist/types/pipeline.d.ts +14 -0
  366. package/dist/utils/process-identity.d.ts +2 -0
  367. package/dist/utils/process-identity.js +35 -0
  368. package/package.json +10 -4
  369. package/scripts/assert-web-assets.mjs +35 -0
  370. package/scripts/build-web.js +72 -0
  371. package/scripts/build.js +31 -28
  372. package/scripts/cross-platform-tests.ts +5 -0
  373. package/skills/gitnexus-cli.md +5 -1
  374. package/web/assets/ProcessFlowModal-DAeX2BHW.js +24 -0
  375. package/web/assets/{abnfDiagram-QNN2D4NM-Cq2djWWe.js → abnfDiagram-PAR5IXJI-J3OdeHLl.js} +1 -1
  376. package/web/assets/{agent-BWAXPjC5.js → agent-BMRqXorA.js} +6 -4
  377. package/web/assets/architecture-7GRP2DOG-M7G3SWCO-G3sWyX6M.js +1 -0
  378. package/web/assets/architectureDiagram-2PNWDENW-ysKcRlGT.js +36 -0
  379. package/web/assets/blockDiagram-PUWGUBOA-oLXTa1lY.js +129 -0
  380. package/web/assets/c4Diagram-3NLNHZP5-D3iu4eC0.js +38 -0
  381. package/web/assets/{chunk-2SREHG4O-Dip42xOq.js → chunk-2NMSUPJH-B24w-wng.js} +1 -1
  382. package/web/assets/{chunk-VJFVEZTB-CX66F2ep.js → chunk-32MCUW2P-ByUyt0Sa.js} +3 -3
  383. package/web/assets/{chunk-4RFN2BYJ-DHHWuC-n.js → chunk-3NPNU5GP-DocZ07Sg.js} +1 -1
  384. package/web/assets/{chunk-XNMVGMAZ-Cg_LnPtj.js → chunk-3SMGFRGC-CAu4JRLv.js} +1 -1
  385. package/web/assets/{chunk-W44A43WB-BN8EQc_u.js → chunk-4CAJECRU-DRYMwG9z.js} +1 -1
  386. package/web/assets/chunk-4OADUZ5Q-CxrSvOwZ.js +10 -0
  387. package/web/assets/{chunk-DMV4VAQV-Bn6WXDSX.js → chunk-5IQCK5RY-CCMhl4so.js} +2 -2
  388. package/web/assets/{chunk-RRFMTAIC-CMN0wcYA.js → chunk-5MVFYWFU-Db9KvrYO.js} +1 -1
  389. package/web/assets/chunk-CLS4B6BI-Uvx5QNsu.js +168 -0
  390. package/web/assets/chunk-DZP67EKU-B3Mt380j.js +70 -0
  391. package/web/assets/{chunk-6L755F7B-CMhLBxi2.js → chunk-EICP7K5X-CqwE9hui.js} +1 -1
  392. package/web/assets/{chunk-BI6VK774-D0oaWk8V.js → chunk-GDY2UAB4-CtQQR0a8.js} +1 -1
  393. package/web/assets/chunk-H7VHZCWX-CE1nAmt6.js +1 -0
  394. package/web/assets/chunk-IJBDOHL6-BUKtY6oF.js +1 -0
  395. package/web/assets/{chunk-OIYT25JQ-CQ6KOZGX.js → chunk-JFFVMJIA-0fJenqia.js} +1 -1
  396. package/web/assets/{chunk-HNC4WDU7-DoU3KnA7.js → chunk-JZGDI5JK-BeTMSSkJ.js} +1 -1
  397. package/web/assets/{chunk-EQFTRU2I-1ix7TzW9.js → chunk-KD6SPIPN-Qp1Pflah.js} +1 -1
  398. package/web/assets/chunk-NF366YI6-CpSpya3n.js +231 -0
  399. package/web/assets/chunk-NUDPKBEF-CU1-BQIW.js +34 -0
  400. package/web/assets/{chunk-SATU7PGQ-B1zhgOvc.js → chunk-OJINMHTS-zOCQe4eI.js} +1 -1
  401. package/web/assets/{chunk-E5QJAATJ-dh-5CtIV.js → chunk-Q6NGPIAH-yyBomb63.js} +1 -1
  402. package/web/assets/chunk-QJSWEUOL-D_rf9gPD.js +128 -0
  403. package/web/assets/chunk-R7JDMUKV-CRoqKpD6.js +1 -0
  404. package/web/assets/{chunk-VE5CLXGZ-C1vB7wpY.js → chunk-RCXAM2GK-CUqrWQDV.js} +1 -1
  405. package/web/assets/{chunk-66DQ2XMT-CM0xjFAN.js → chunk-RT4MAWR3-zXy9-Lvt.js} +1 -1
  406. package/web/assets/{chunk-TZUXEDM2-B7p9AcTw.js → chunk-SFMINX4W-J2UrvMpD.js} +1 -1
  407. package/web/assets/{chunk-LORZLZWG-B57uGw2N.js → chunk-SLDQ463B-CHY6e_bQ.js} +2 -2
  408. package/web/assets/{chunk-FWYVLQTC-BgDItRzJ.js → chunk-TCEHX7R3-CXPDEVbm.js} +1 -1
  409. package/web/assets/{chunk-224SPVON-B8gxtXpy.js → chunk-VQC2EELJ-Dc8fIy4R.js} +1 -1
  410. package/web/assets/chunk-VRZKL3EH-DB3KixTQ.js +1 -0
  411. package/web/assets/{chunk-A7VWPJGB-B4O3oQdQ.js → chunk-VTHDQ7BV-b7FsPQZO.js} +1 -1
  412. package/web/assets/chunk-VY2OSTJR-Dkgc3Brg.js +2 -0
  413. package/web/assets/chunk-WUBWJARI-7FwILJ3k.js +2 -0
  414. package/web/assets/{chunk-D6VWDJW2-BxcBdZ9c.js → chunk-YBMQ5JGJ-BSnyWZmd.js} +1 -1
  415. package/web/assets/chunk-YDMLL4PJ-IHhMngTz.js +2 -0
  416. package/web/assets/chunk-Z6V44ARX-BjCEsF0Q.js +62 -0
  417. package/web/assets/chunk-ZJJ7VQJP-Dz089b-K.js +321 -0
  418. package/web/assets/chunk-ZNLK7HRR-B0iFpmW4.js +1 -0
  419. package/web/assets/chunk-ZQN7UHIL-Cy7KAjQt.js +1 -0
  420. package/web/assets/{chunk-L5GCOVLC-CE2w8Nm_.js → chunk-ZS6VBONO-DBjJO0w9.js} +2 -2
  421. package/web/assets/{chunk-NV3KIAZN-5yvcpMiu.js → chunk-ZUNWM646-DNRJyNPe.js} +1 -1
  422. package/web/assets/classDiagram-FGAMPOII-C5Ibyode.js +1 -0
  423. package/web/assets/classDiagram-v2-AI5RJEK4-C5Ibyode.js +1 -0
  424. package/web/assets/{cose-bilkent-RZA4XIPR-BHpK4Crp.js → cose-bilkent-Q72C2OJ3-DMeFXnK8.js} +1 -1
  425. package/web/assets/cynefin-OW5HDTMX-6OCTWOGG-vlqakYcO.js +1 -0
  426. package/web/assets/{cynefinDiagram-TR7LZUCG-C3Iar9lZ.js → cynefinDiagram-2OOWUY4M-BY6DZkTt.js} +1 -1
  427. package/web/assets/dagre-MPVFI544-DWO70fy_.js +4 -0
  428. package/web/assets/diagram-AE4NWXFW-f7JRVRUL.js +24 -0
  429. package/web/assets/{diagram-L7DVE3PN-GIRyVUtt.js → diagram-BUJID5UG-BXZv1rCS.js} +2 -2
  430. package/web/assets/{diagram-JCD7PQ7C-DC5-9FRr.js → diagram-C44CZ5NI-CRNfvjCq.js} +1 -1
  431. package/web/assets/diagram-EYOLEXXS-DZOjKQVE.js +30 -0
  432. package/web/assets/diagram-P7B6PWOJ-D3SQmw3_.js +3 -0
  433. package/web/assets/{ebnfDiagram-DRHRQJWO-D8_CI4ZF.js → ebnfDiagram-FTPZ3PV6-jKWpIDN2.js} +1 -1
  434. package/web/assets/erDiagram-H3ERR26V-BqJntEuJ.js +99 -0
  435. package/web/assets/eventmodeling-NTZA5JFV-WKSWQHFS-Bq4FqtBL.js +1 -0
  436. package/web/assets/flowDiagram-YHGXBVSY-Dnlk2bEu.js +1 -0
  437. package/web/assets/ganttDiagram-RWFTB7ED-Bl6Y1K5T.js +292 -0
  438. package/web/assets/gitGraph-4MIJSDKK-JH2HKYUO-B3yc4GkH.js +1 -0
  439. package/web/assets/gitGraphDiagram-MAR6GKOP-CkNvsrdw.js +106 -0
  440. package/web/assets/{index-CJDpyH-n.css → index-C2_aej58.css} +1 -1
  441. package/web/assets/{index-DDRie6_8.js → index-Dj3vQOHK.js} +51 -51
  442. package/web/assets/info-A6RAGUB7-3TX3OFWW-BM3N5_Dv.js +1 -0
  443. package/web/assets/infoDiagram-LV547AFH-COkFutAf.js +2 -0
  444. package/web/assets/{ishikawaDiagram-4JDSWWDM-DmqWtjkl.js → ishikawaDiagram-PUJQGNDS-Bb8FylSR.js} +2 -2
  445. package/web/assets/{journeyDiagram-QUS3FAKT-XAzVzrQW.js → journeyDiagram-EW5QJT4W-BzoHUBhM.js} +4 -4
  446. package/web/assets/{kanban-definition-D4L7SQKK-YurRnmYn.js → kanban-definition-JSQERAZB-Uy2Pi0yQ.js} +4 -4
  447. package/web/assets/katex-CZ4GXH2S-C0Fcou7U.js +257 -0
  448. package/web/assets/{mindmap-definition-66QP5TD6-ChrWWnil.js → mindmap-definition-VBJCLQLM-B-CnOnt_.js} +3 -3
  449. package/web/assets/packet-AYTQ26CC-MKII6P3Y-Bd52ZE3V.js +1 -0
  450. package/web/assets/{pegDiagram-YKIO5C6U-QGeQLEq2.js → pegDiagram-7WILOQTJ-D9sneKXg.js} +1 -1
  451. package/web/assets/pie-WAS4IAKB-6B4OPMJ5-DW5Xy69Z.js +1 -0
  452. package/web/assets/pieDiagram-EFA7CBSB-Dx2NQofL.js +39 -0
  453. package/web/assets/{quadrantDiagram-VO5QLCXA-B7098wSc.js → quadrantDiagram-WARVYA7P-DPKL9_0A.js} +3 -3
  454. package/web/assets/radar-RG4KPBEZ-UPTR3XUL-CkzibT2h.js +1 -0
  455. package/web/assets/railroad-74A4TZTK-MEFUPFMS-D9zF-mDN.js +1 -0
  456. package/web/assets/railroad-abnf-HS5TGJTU-R5YG2S5D-ruacjUbX.js +1 -0
  457. package/web/assets/railroad-ebnf-LZEXJU2U-G5QEX2L6-S1zc5OiO.js +1 -0
  458. package/web/assets/railroad-peg-WCYAUIDC-H5I2ZRY2-Cbcr0XzY.js +1 -0
  459. package/web/assets/{railroadDiagram-M77LTMSB-AXu4vxk_.js → railroadDiagram-5NIQVNLQ-DsweTo14.js} +1 -1
  460. package/web/assets/{requirementDiagram-RASO5HTO-B-l8InpK.js → requirementDiagram-SXREGOKZ-CXwdNSVR.js} +4 -4
  461. package/web/assets/{sankeyDiagram-F32LOJ6L-Kd7zjJgX.js → sankeyDiagram-VV74M2VP-CA6jtP9P.js} +3 -3
  462. package/web/assets/{sequenceDiagram-URATNSBD-BlcdY9DS.js → sequenceDiagram-52ZFIFDL-k_5rEbzm.js} +15 -15
  463. package/web/assets/src-Df5C1Nz4.js +1 -0
  464. package/web/assets/stateDiagram-3QAKPIVI-BejHTf31.js +1 -0
  465. package/web/assets/stateDiagram-v2-HN2P4RDZ-BrfoRuOc.js +1 -0
  466. package/web/assets/swimlanes-QLVP42QD-CQSVO5D6.js +1 -0
  467. package/web/assets/swimlanesDiagram-JKPDBFCN-DrWB9kcD.js +8 -0
  468. package/web/assets/{timeline-definition-WJXWRH4I-DUfp1R3E.js → timeline-definition-GS45XAXW-C0Ks8rPP.js} +4 -4
  469. package/web/assets/treeView-Q6P3EWNA-ZRJGANNQ-DmKOCo6L.js +1 -0
  470. package/web/assets/treemap-WGGIJYW6-K64VN5AS-DO3xY92U.js +1 -0
  471. package/web/assets/{vennDiagram-K3VCMQLI-Bj-FN-XS.js → vennDiagram-QIQU2ZRJ-rgPiS837.js} +3 -3
  472. package/web/assets/wardley-WFR3VGLG-D67OWCCH-DiDPBNft.js +1 -0
  473. package/web/assets/wardleyDiagram-U6YNM66N-DRVr7SPi.js +78 -0
  474. package/web/assets/{xychartDiagram-5VRUVLCW-CK_rbSWE.js → xychartDiagram-XJAZEDNM-COtlZzYb.js} +3 -3
  475. package/web/index.html +19 -17
  476. package/web/assets/ProcessFlowModal-Badh2Pbg.js +0 -24
  477. package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +0 -1
  478. package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +0 -36
  479. package/web/assets/blockDiagram-54WLDVWM-Dg_hrRWE.js +0 -132
  480. package/web/assets/c4Diagram-X2LASM7V-CnhoT4aV.js +0 -10
  481. package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +0 -127
  482. package/web/assets/chunk-5VCL7Z4A-CQ-2dYWj.js +0 -1
  483. package/web/assets/chunk-6BELYETK-ChsYtfHW.js +0 -1
  484. package/web/assets/chunk-7CWYLC5S-DRgGkkpF.js +0 -2
  485. package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +0 -32
  486. package/web/assets/chunk-KRXBNO2N-C-UNuKKf.js +0 -1
  487. package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +0 -321
  488. package/web/assets/chunk-LIEV3EAG-pyKGssV3.js +0 -1
  489. package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +0 -62
  490. package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +0 -10
  491. package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +0 -156
  492. package/web/assets/chunk-SZD42YQK-ijyKKVr1.js +0 -70
  493. package/web/assets/chunk-TFPGFQPA-Dj6a-0pC.js +0 -231
  494. package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +0 -2
  495. package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +0 -1
  496. package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +0 -1
  497. package/web/assets/chunk-WJBAP47W-BckNkuEN.js +0 -1
  498. package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +0 -1
  499. package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +0 -1
  500. package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +0 -1
  501. package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +0 -4
  502. package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +0 -30
  503. package/web/assets/diagram-KFBZAVDW-Dfmf_4ti.js +0 -3
  504. package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +0 -24
  505. package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +0 -85
  506. package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +0 -1
  507. package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +0 -1
  508. package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +0 -292
  509. package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +0 -1
  510. package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +0 -106
  511. package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +0 -1
  512. package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +0 -2
  513. package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +0 -257
  514. package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +0 -1
  515. package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +0 -1
  516. package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +0 -39
  517. package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +0 -1
  518. package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +0 -1
  519. package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +0 -1
  520. package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +0 -1
  521. package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +0 -1
  522. package/web/assets/src-C5sx_gMp.js +0 -1
  523. package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +0 -1
  524. package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +0 -1
  525. package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +0 -2
  526. package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +0 -8
  527. package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +0 -1
  528. package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +0 -1
  529. package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +0 -1
  530. package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +0 -78
  531. /package/web/assets/{sizeCapture-5GORAGP4-BEqQzsxs.js → sizeCapture-FGA5AGYP-BEqQzsxs.js} +0 -0
package/dist/cli/watch.js CHANGED
@@ -1,372 +1,6 @@
1
- import path from 'node:path';
2
- import fs from 'node:fs/promises';
3
- import { watch } from 'chokidar';
4
- import { createWatchIgnorePredicate } from '../config/ignore-service.js';
5
- import { analyzeFailureMayHaveMutatedLiveIndex, runFullAnalysis, } from '../core/run-analyze.js';
6
- import { getGitRoot, hasGitDir } from '../storage/git.js';
7
- import { GITNEXUS_DIR } from '../storage/repo-meta.js';
8
- import { loadAnalyzeConfigStrict, mergeAnalyzeOptions, validateBranchName, } from './analyze-config.js';
9
- import { ensureHeap } from './analyze.js';
10
- import { cliError, cliInfo, cliWarn } from './cli-message.js';
11
- import { WATCH_FULL_REFRESH_PATH, WatchRefreshQueue, } from './watch-queue.js';
12
- const DEFAULT_DEBOUNCE_MS = 300;
13
- const MAX_TIMER_DELAY_MS = 2_147_483_647;
14
- const MAX_FILE_SIZE_KB = 32 * 1024;
15
- const TRANSIENT_WATCH_ERROR_CODES = new Set(['EACCES', 'ENOENT', 'ENOTDIR', 'EPERM']);
16
- function posixWatchPath(filePath) {
17
- return filePath.replace(/\\/g, '/').replace(/^\.\/+/, '');
18
- }
19
- export function isRelevantWatchPath(filePath) {
20
- const normalized = posixWatchPath(filePath);
21
- return (normalized.length > 0 &&
22
- normalized !== '.' &&
23
- !normalized.startsWith('../') &&
24
- !path.posix.isAbsolute(normalized) &&
25
- !path.win32.isAbsolute(filePath));
26
- }
27
- function isIgnoreControlPath(filePath) {
28
- const normalized = posixWatchPath(filePath);
29
- return normalized === '.gitignore' || normalized === '.gitnexusignore';
30
- }
31
- function isConfigControlPath(filePath) {
32
- return posixWatchPath(filePath) === '.gitnexusrc';
33
- }
34
- function isAnalyzerOwnedWatchPath(filePath) {
35
- const normalized = posixWatchPath(filePath).replace(/\/+$/, '');
36
- return normalized === GITNEXUS_DIR || normalized.startsWith(`${GITNEXUS_DIR}/`);
37
- }
38
- function repoRelativeWatchPath(repoPath, candidate) {
39
- const relative = path.relative(repoPath, candidate).replace(/\\/g, '/');
40
- if (!relative || relative.startsWith('../') || path.isAbsolute(relative))
41
- return null;
42
- return relative;
43
- }
44
- function setEnvironment(name, value) {
45
- if (value === undefined)
46
- delete process.env[name];
47
- else
48
- process.env[name] = value;
49
- }
50
- function positiveInteger(value, flag, maximum) {
51
- if (value === undefined)
52
- return undefined;
53
- const parsed = Number(value);
54
- if (!Number.isInteger(parsed) || parsed < 1)
55
- throw new Error(`${flag} must be a positive integer`);
56
- if (maximum !== undefined && parsed > maximum) {
57
- throw new Error(`${flag} must not exceed ${maximum}`);
58
- }
59
- return parsed;
60
- }
61
- export async function resolveWatchOptions(repoPath, cli, baseline, reportIgnoredConfig = () => { }) {
62
- const config = (await loadAnalyzeConfigStrict(repoPath)) ?? {};
63
- const merged = mergeAnalyzeOptions(cli, config);
64
- const unsupported = [
65
- ['--force', cli.force],
66
- ['--repair-fts', cli.repairFts],
67
- ['--embeddings', cli.embeddings],
68
- ['--drop-embeddings', cli.dropEmbeddings],
69
- ['--skills', cli.skills],
70
- ['--default-branch', cli.defaultBranch],
71
- ['--skip-agents-md', cli.skipAgentsMd],
72
- ['--skip-skills', cli.skipSkills],
73
- ['--no-stats', cli.stats === false],
74
- ['--self-commit', cli.selfCommit],
75
- ['--index-only', cli.indexOnly],
76
- ['--skip-git', cli.skipGit],
77
- ['walCheckpointThreshold', cli.walCheckpointThreshold],
78
- ['embeddingThreads', cli.embeddingThreads],
79
- ['embeddingBatchSize', cli.embeddingBatchSize],
80
- ['embeddingSubBatchSize', cli.embeddingSubBatchSize],
81
- ['embeddingDevice', cli.embeddingDevice],
82
- ['embeddingBaseUrl', cli.embeddingBaseUrl],
83
- ['embeddingModel', cli.embeddingModel],
84
- ['--embedding-auth-token', cli.embeddingAuthToken],
85
- ['--embedding-dims', cli.embeddingDims],
86
- ].filter(([, value]) => value !== undefined && value !== false);
87
- if (unsupported.length > 0) {
88
- throw new Error(`analyze --watch does not support ${unsupported.map(([name]) => name).join(', ')}`);
89
- }
90
- reportIgnoredConfig([
91
- ['embeddings', config.embeddings],
92
- ['dropEmbeddings', config.dropEmbeddings],
93
- ['defaultBranch', config.defaultBranch],
94
- ['skipAgentsMd', config.skipAgentsMd !== undefined],
95
- ['skipSkills', config.skipSkills !== undefined],
96
- ['stats', config.stats !== undefined],
97
- ['walCheckpointThreshold', config.walCheckpointThreshold],
98
- ['embeddingThreads', config.embeddingThreads],
99
- ['embeddingBatchSize', config.embeddingBatchSize],
100
- ['embeddingSubBatchSize', config.embeddingSubBatchSize],
101
- ['embeddingDevice', config.embeddingDevice],
102
- ['embeddingBaseUrl', config.embeddingBaseUrl],
103
- ['embeddingModel', config.embeddingModel],
104
- ]
105
- .filter(([, value]) => value !== undefined && value !== false)
106
- .map(([name]) => String(name)));
107
- const branch = merged.branch === undefined ? undefined : validateBranchName(merged.branch, '--branch');
108
- const workerPoolSize = positiveInteger(merged.workers, '--workers');
109
- const workerTimeoutSeconds = positiveInteger(merged.workerTimeout, 'workerTimeout');
110
- const maxFileSize = positiveInteger(merged.maxFileSize, 'maxFileSize', MAX_FILE_SIZE_KB);
111
- setEnvironment('GITNEXUS_MAX_FILE_SIZE', maxFileSize === undefined ? baseline.maxFileSize : String(maxFileSize));
112
- if (workerTimeoutSeconds !== undefined) {
113
- process.env.GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS = String(workerTimeoutSeconds * 1000);
114
- }
115
- else {
116
- setEnvironment('GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS', baseline.workerTimeout);
117
- }
118
- setEnvironment('GITNEXUS_VERBOSE', merged.verbose ? '1' : baseline.verbose);
119
- return {
120
- pdg: merged.pdg,
121
- branch,
122
- registryName: merged.name,
123
- allowDuplicateName: merged.allowDuplicateName,
124
- workerPoolSize,
125
- fetchWrappers: merged.fetchWrappers,
126
- skipAgentsMd: true,
127
- skipSkills: true,
128
- noStats: true,
129
- atomicIncremental: process.platform !== 'win32',
130
- };
131
- }
132
- function refreshSummary(result, observedPaths, durationMs, lastSuccessfulRefreshAt) {
133
- const measured = result.incrementalStats;
134
- const changed = measured?.changedFiles ?? (result.alreadyUpToDate ? 0 : observedPaths.length);
135
- const reparsed = measured?.reparsedFiles ??
136
- (typeof result.pipelineResult?.reparsedFileCount === 'number'
137
- ? result.pipelineResult.reparsedFileCount
138
- : 0);
139
- const dependents = measured?.affectedDependents ?? 0;
140
- const mode = measured?.writeMode ?? (result.alreadyUpToDate ? 'no-op' : 'full');
141
- return (`Refresh complete: ${changed} changed, ${reparsed} re-parsed, ` +
142
- `${dependents} affected dependent(s), ${durationMs}ms, ${mode}; ` +
143
- `last success ${lastSuccessfulRefreshAt}`);
144
- }
145
- async function waitUntilReady(watcher) {
146
- await new Promise((resolve, reject) => {
147
- const ready = () => {
148
- watcher.off('error', failed);
149
- resolve();
150
- };
151
- const failed = (error) => {
152
- watcher.off('ready', ready);
153
- reject(error);
154
- };
155
- watcher.once('ready', ready);
156
- watcher.once('error', failed);
157
- });
158
- }
159
- class WatchControlReloadError extends Error {
160
- constructor(cause) {
161
- super(cause instanceof Error ? cause.message : String(cause), { cause });
162
- this.name = 'WatchControlReloadError';
163
- }
164
- }
165
- export function shouldStopAfterWatchRefreshFailure(error, paths) {
166
- return (paths.length > 0 &&
167
- !(error instanceof WatchControlReloadError) &&
168
- analyzeFailureMayHaveMutatedLiveIndex(error));
169
- }
170
- /** Start the real filesystem watcher with bounded, serialized refreshes. */
171
- export async function startWatchFileLoop(repoPath, debounceMs, refresh, onError, onWatcherError = (error) => onError(error, [])) {
172
- let ignorePath = await createWatchIgnorePredicate(repoPath);
173
- let ignoreControlValid = true;
174
- const queue = new WatchRefreshQueue(async (paths) => {
175
- if (paths.some(isIgnoreControlPath) || !ignoreControlValid) {
176
- const retryingInvalidControls = !ignoreControlValid;
177
- try {
178
- ignorePath = await createWatchIgnorePredicate(repoPath);
179
- ignoreControlValid = true;
180
- watcher.add(repoPath);
181
- }
182
- catch (error) {
183
- ignoreControlValid = false;
184
- throw new WatchControlReloadError(retryingInvalidControls
185
- ? new Error('Ignore controls remain invalid; fix them before indexing more changes.', {
186
- cause: error,
187
- })
188
- : error);
189
- }
190
- }
191
- await refresh(paths);
192
- }, onError, debounceMs, {
193
- maxWaitMs: Math.max(2_000, debounceMs * 10),
194
- maxPendingPaths: 1_000,
195
- holdEventsUntilInitialRefresh: true,
196
- isPriorityPath: (filePath) => isIgnoreControlPath(filePath) || isConfigControlPath(filePath),
197
- });
198
- const watcher = watch(repoPath, {
199
- ignoreInitial: true,
200
- atomic: true,
201
- followSymlinks: false,
202
- awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 20 },
203
- ignored: (candidate, stats) => {
204
- const relative = repoRelativeWatchPath(repoPath, candidate);
205
- if (relative !== null && isAnalyzerOwnedWatchPath(relative))
206
- return true;
207
- if (relative !== null && (isIgnoreControlPath(relative) || isConfigControlPath(relative))) {
208
- return false;
209
- }
210
- return ignorePath(candidate, stats?.isDirectory() ?? false);
211
- },
212
- });
213
- watcher.on('all', (event, changedPath) => {
214
- if (event !== 'add' && event !== 'change' && event !== 'unlink')
215
- return;
216
- const relative = repoRelativeWatchPath(repoPath, changedPath);
217
- if (relative && isRelevantWatchPath(relative) && !isAnalyzerOwnedWatchPath(relative)) {
218
- queue.enqueue(relative);
219
- }
220
- });
221
- watcher.on('error', (error) => {
222
- // Chokidar can surface a transient EPERM on Windows while an ignored
223
- // analyzer-owned path is replaced. Re-arm the root and force one bounded
224
- // catch-up refresh so a missed event cannot leave the graph stale. Other
225
- // watcher errors may mean coverage was lost and remain fatal.
226
- if (TRANSIENT_WATCH_ERROR_CODES.has(error.code ?? '')) {
227
- watcher.add(repoPath);
228
- queue.enqueue(WATCH_FULL_REFRESH_PATH);
229
- return;
230
- }
231
- onWatcherError(error);
232
- });
233
- try {
234
- await waitUntilReady(watcher);
235
- await queue.runInitial();
236
- }
237
- catch (error) {
238
- await watcher.close();
239
- await queue.close();
240
- throw error;
241
- }
242
- return {
243
- waitForIdle: () => queue.waitForIdle(),
244
- close: async () => {
245
- await watcher.close();
246
- await queue.close();
247
- },
248
- };
249
- }
250
- export async function watchCommandWithRunnerIdentity(runnerIdentityAtBootstrap, inputPath, cliOptions = {}) {
251
- if (await ensureHeap({ cleanForwardedTermination: true }))
252
- return;
253
- const requestedRepoPath = inputPath ? path.resolve(inputPath) : getGitRoot(process.cwd());
254
- if (requestedRepoPath === null || !hasGitDir(requestedRepoPath)) {
255
- cliError(' gitnexus analyze --watch requires a Git repository.');
256
- process.exitCode = 1;
257
- return;
258
- }
259
- const repoPath = await fs.realpath(requestedRepoPath);
260
- const baselineEnvironment = {
261
- maxFileSize: process.env.GITNEXUS_MAX_FILE_SIZE,
262
- workerTimeout: process.env.GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS,
263
- verbose: process.env.GITNEXUS_VERBOSE,
264
- };
265
- try {
266
- let ignoredConfigSignature;
267
- const reportIgnoredConfig = (names) => {
268
- const signature = [...names].sort().join(',');
269
- if (signature === ignoredConfigSignature)
270
- return;
271
- ignoredConfigSignature = signature;
272
- if (names.length > 0) {
273
- cliWarn(`Watch mode ignores unsupported .gitnexusrc settings: ${names.join(', ')}.`);
274
- }
275
- };
276
- let debounceMs;
277
- let analyzeOptions;
278
- try {
279
- debounceMs =
280
- positiveInteger(cliOptions.debounce ?? String(DEFAULT_DEBOUNCE_MS), '--debounce', MAX_TIMER_DELAY_MS) ?? DEFAULT_DEBOUNCE_MS;
281
- analyzeOptions = await resolveWatchOptions(repoPath, cliOptions, baselineEnvironment, reportIgnoredConfig);
282
- }
283
- catch (error) {
284
- cliError(` ${error instanceof Error ? error.message : String(error)}`);
285
- process.exitCode = 1;
286
- return;
287
- }
288
- let stopWatching;
289
- const stopped = new Promise((resolve) => {
290
- stopWatching = resolve;
291
- });
292
- const stop = () => stopWatching();
293
- process.once('SIGINT', stop);
294
- process.once('SIGTERM', stop);
295
- try {
296
- let loop;
297
- let fatalRefreshError;
298
- let configControlValid = true;
299
- let lastSuccessfulRefreshAt;
300
- try {
301
- loop = await startWatchFileLoop(repoPath, debounceMs, async (paths) => {
302
- if (paths.some(isConfigControlPath) || !configControlValid) {
303
- const retryingInvalidConfig = !configControlValid;
304
- try {
305
- analyzeOptions = await resolveWatchOptions(repoPath, cliOptions, baselineEnvironment, reportIgnoredConfig);
306
- configControlValid = true;
307
- }
308
- catch (error) {
309
- configControlValid = false;
310
- throw new WatchControlReloadError(retryingInvalidConfig
311
- ? new Error('Configuration remains invalid; fix it before indexing more changes.', {
312
- cause: error,
313
- })
314
- : error);
315
- }
316
- }
317
- const startedAt = Date.now();
318
- const result = await runFullAnalysis(repoPath, analyzeOptions, {
319
- onProgress: () => { },
320
- onLog: process.env.GITNEXUS_VERBOSE === '1'
321
- ? (message) => cliInfo(` ${message}`)
322
- : undefined,
323
- }, runnerIdentityAtBootstrap);
324
- lastSuccessfulRefreshAt = new Date().toISOString();
325
- if (paths.length === 0) {
326
- cliInfo(result.alreadyUpToDate
327
- ? `Watching ${repoPath}; index is up to date.`
328
- : `Watching ${repoPath}; initial index ready in ${Date.now() - startedAt}ms.`);
329
- }
330
- else {
331
- cliInfo(refreshSummary(result, paths, Date.now() - startedAt, lastSuccessfulRefreshAt));
332
- }
333
- }, (error, paths) => {
334
- const detail = paths.length > 0 ? ` (${paths.length} queued path(s))` : '';
335
- if (shouldStopAfterWatchRefreshFailure(error, paths)) {
336
- fatalRefreshError = error;
337
- cliError(`Refresh failed${detail}: ${error instanceof Error ? error.message : String(error)}. ` +
338
- 'Watch mode is stopping because the live index may have been updated in place.');
339
- stopWatching();
340
- return;
341
- }
342
- const lastSuccess = lastSuccessfulRefreshAt ?? 'none yet';
343
- cliWarn(`Refresh failed${detail}: ${error instanceof Error ? error.message : String(error)}. ` +
344
- `Retry scheduled; last success ${lastSuccess}.`);
345
- }, (error) => {
346
- fatalRefreshError = error;
347
- cliError(`Watcher failed: ${error instanceof Error ? error.message : String(error)}. ` +
348
- 'Watch mode is stopping.');
349
- stopWatching();
350
- });
351
- }
352
- catch (error) {
353
- cliError(` Unable to start watcher: ${error instanceof Error ? error.message : String(error)}`);
354
- process.exitCode = 1;
355
- return;
356
- }
357
- await stopped;
358
- await loop.close();
359
- if (fatalRefreshError !== undefined)
360
- process.exitCode = 1;
361
- }
362
- finally {
363
- process.removeListener('SIGINT', stop);
364
- process.removeListener('SIGTERM', stop);
365
- }
366
- }
367
- finally {
368
- setEnvironment('GITNEXUS_MAX_FILE_SIZE', baselineEnvironment.maxFileSize);
369
- setEnvironment('GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS', baselineEnvironment.workerTimeout);
370
- setEnvironment('GITNEXUS_VERBOSE', baselineEnvironment.verbose);
371
- }
1
+ /** Reserved CLI verb: never starts either watch product. */
2
+ import { t } from './i18n/index.js';
3
+ export async function watchAmbiguousCommand(_action) {
4
+ process.stderr.write(t('error.watch.ambiguous'));
5
+ process.exitCode = 1;
372
6
  }
@@ -0,0 +1,2 @@
1
+ /** Production registry of independently versioned analysis capabilities. */
2
+ export declare const ANALYSIS_FEATURES: readonly [import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor, import("./analysis-features.js").AnalysisFeatureDescriptor];
@@ -0,0 +1,15 @@
1
+ import { CLASS_FRAMEWORK_ANNOTATIONS_FEATURE } from './analysis-features.js';
2
+ import { SPRING_AOP_FEATURE, SPRING_BEAN_INVENTORY_FEATURE, SPRING_CONDITIONALS_FEATURE, SPRING_NON_HTTP_HANDLERS_FEATURE, SPRING_ROUTE_BINDINGS_FEATURE, } from './ingestion/frameworks/spring/analysis-features.js';
3
+ import { JAVA_ENUM_INTERFACE_HERITAGE_FEATURE, JAVA_RECORD_COMPONENT_ACCESSORS_FEATURE, SPRING_CONFIG_BINDINGS_FEATURE, } from './ingestion/languages/java/analysis-features.js';
4
+ /** Production registry of independently versioned analysis capabilities. */
5
+ export const ANALYSIS_FEATURES = [
6
+ CLASS_FRAMEWORK_ANNOTATIONS_FEATURE,
7
+ SPRING_AOP_FEATURE,
8
+ SPRING_BEAN_INVENTORY_FEATURE,
9
+ SPRING_CONDITIONALS_FEATURE,
10
+ SPRING_NON_HTTP_HANDLERS_FEATURE,
11
+ SPRING_ROUTE_BINDINGS_FEATURE,
12
+ SPRING_CONFIG_BINDINGS_FEATURE,
13
+ JAVA_ENUM_INTERFACE_HERITAGE_FEATURE,
14
+ JAVA_RECORD_COMPONENT_ACCESSORS_FEATURE,
15
+ ];
@@ -13,12 +13,13 @@
13
13
  * different entry files inside the same build tree; alternating between them
14
14
  * must not make an otherwise identical index stale.
15
15
  */
16
- import { closeSync, constants as fsConstants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
16
+ import { accessSync, closeSync, constants as fsConstants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
17
17
  import { createHash, randomBytes } from 'node:crypto';
18
18
  import { spawnSync } from 'node:child_process';
19
19
  import { isDeepStrictEqual } from 'node:util';
20
20
  import os from 'node:os';
21
21
  import path from 'node:path';
22
+ import { parseTruthyEnv } from './ingestion/utils/env.js';
22
23
  import { fileURLToPath } from 'node:url';
23
24
  export const ANALYZER_RUNNER_IDENTITY_SCHEMA_VERSION = 4;
24
25
  const BUILD_CANONICALIZATION = 'gitnexus-analyzer-build-v2';
@@ -1754,9 +1755,26 @@ function snapshotCacheGuardDirect(request) {
1754
1755
  return null;
1755
1756
  }
1756
1757
  }
1757
- function snapshotCacheGuards(requests) {
1758
+ function installTreeUnwritable(packageRoot, buildRoot) {
1759
+ for (const dir of [packageRoot, buildRoot]) {
1760
+ try {
1761
+ accessSync(dir, fsConstants.W_OK);
1762
+ }
1763
+ catch (err) {
1764
+ const code = err.code;
1765
+ if (code === 'EACCES' || code === 'EROFS')
1766
+ return true;
1767
+ }
1768
+ }
1769
+ return false;
1770
+ }
1771
+ function snapshotCacheGuards(requests, packageRoot, buildRoot) {
1758
1772
  if (requests.length < 128)
1759
1773
  return requests.map(snapshotCacheGuardDirect);
1774
+ if (parseTruthyEnv(process.env.GITNEXUS_ANALYZER_IDENTITY_IN_PROCESS_GUARDS) ||
1775
+ installTreeUnwritable(packageRoot, buildRoot)) {
1776
+ return requests.map(snapshotCacheGuardDirect);
1777
+ }
1760
1778
  try {
1761
1779
  const probe = spawnSync(process.execPath, ['--input-type=commonjs', '-e', CACHE_GUARD_PROBE_SCRIPT], {
1762
1780
  input: JSON.stringify(requests),
@@ -1857,7 +1875,7 @@ function validateIdentityCache(cache, options) {
1857
1875
  return { mode, absolutePath };
1858
1876
  });
1859
1877
  options.onCacheValidationPass?.({ guardCount: requests.length });
1860
- const actual = snapshotCacheGuards(requests);
1878
+ const actual = snapshotCacheGuards(requests, cache.packageRoot, cache.buildRoot);
1861
1879
  const mismatch = actual.findIndex((result, index) => !isDeepStrictEqual(result, entries[index][1]));
1862
1880
  if (mismatch !== -1) {
1863
1881
  const [mode, absolutePath] = JSON.parse(entries[mismatch][0]);
@@ -0,0 +1,30 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import type { AnalyzeOptions, AnalyzeResult } from '../run-analyze.js';
3
+ export type AutoSyncAnalysisRunner = (repoPath: string, options: AnalyzeOptions, timeoutMs: number, signal?: AbortSignal, onCancellationRequested?: () => void, concurrency?: number) => Promise<Pick<AnalyzeResult, 'stats'>>;
4
+ interface AnalysisWorker extends Pick<ChildProcess, 'send' | 'on'> {
5
+ stdout?: Pick<NodeJS.ReadableStream, 'resume'> | null;
6
+ stderr?: Pick<NodeJS.ReadableStream, 'resume'> | null;
7
+ unref?: () => void;
8
+ channel?: {
9
+ unref(): void;
10
+ } | null;
11
+ }
12
+ export interface AutoSyncAnalysisLaunchDeps {
13
+ forkWorker: (workerPath: string, execArgv: string[]) => AnalysisWorker;
14
+ setTimeoutFn: typeof setTimeout;
15
+ clearTimeoutFn: typeof clearTimeout;
16
+ cancelGraceMs: number;
17
+ }
18
+ /**
19
+ * Per-worker V8 heap cap for one tick.
20
+ *
21
+ * `autoHeapCapMb()` is a whole-machine figure, so handing it to every fork
22
+ * over-commits memory by the parallelism factor. Admission already bounds
23
+ * parallelism to `floor(availableMemoryGB / 2)`, so dividing here keeps the sum
24
+ * of worker heaps inside the machine budget while leaving `max_concurrency`
25
+ * free to mean what it says. The two rules compose to a ~1.5GB per-worker floor.
26
+ */
27
+ export declare function resolveWorkerHeapMb(concurrency?: number): number;
28
+ export declare function createAutoSyncAnalysisRunner(overrides?: Partial<AutoSyncAnalysisLaunchDeps>): AutoSyncAnalysisRunner;
29
+ export declare const runAutoSyncAnalysis: AutoSyncAnalysisRunner;
30
+ export {};
@@ -0,0 +1,166 @@
1
+ import { fork } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { createRequire } from 'node:module';
4
+ import path from 'node:path';
5
+ import { fileURLToPath, pathToFileURL } from 'node:url';
6
+ import { autoHeapCapMb } from '../ingestion/utils/effective-ram.js';
7
+ const _require = createRequire(import.meta.url);
8
+ /**
9
+ * How long the parent keeps waiting after asking a worker to cancel.
10
+ *
11
+ * Must stay below `stopAutoSyncWatch`'s process-exit budget, or a worker wedged
12
+ * past its safe point still turns `watch stop` into a timeout.
13
+ */
14
+ const AUTO_SYNC_CANCEL_GRACE_MS = 5_000;
15
+ const DEFAULT_DEPS = {
16
+ forkWorker: (workerPath, execArgv) => fork(workerPath, [], {
17
+ execArgv,
18
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
19
+ }),
20
+ setTimeoutFn: setTimeout,
21
+ clearTimeoutFn: clearTimeout,
22
+ cancelGraceMs: AUTO_SYNC_CANCEL_GRACE_MS,
23
+ };
24
+ /**
25
+ * Per-worker V8 heap cap for one tick.
26
+ *
27
+ * `autoHeapCapMb()` is a whole-machine figure, so handing it to every fork
28
+ * over-commits memory by the parallelism factor. Admission already bounds
29
+ * parallelism to `floor(availableMemoryGB / 2)`, so dividing here keeps the sum
30
+ * of worker heaps inside the machine budget while leaving `max_concurrency`
31
+ * free to mean what it says. The two rules compose to a ~1.5GB per-worker floor.
32
+ */
33
+ export function resolveWorkerHeapMb(concurrency = 1) {
34
+ const slots = Number.isFinite(concurrency) && concurrency >= 1 ? Math.floor(concurrency) : 1;
35
+ return Math.max(1, Math.min(8192, Math.floor(autoHeapCapMb() / slots)));
36
+ }
37
+ export function createAutoSyncAnalysisRunner(overrides = {}) {
38
+ const deps = { ...DEFAULT_DEPS, ...overrides };
39
+ return (repoPath, options, timeoutMs, signal, onCancellationRequested, concurrency) => new Promise((resolve, reject) => {
40
+ if (signal?.aborted) {
41
+ reject(new Error('Analysis cancelled.'));
42
+ return;
43
+ }
44
+ const callerPath = fileURLToPath(import.meta.url);
45
+ const isDev = callerPath.endsWith('.ts');
46
+ const workerPath = path.join(path.dirname(callerPath), '../../server', isDev ? 'analyze-worker.ts' : 'analyze-worker.js');
47
+ if (!existsSync(workerPath)) {
48
+ reject(new Error(`Auto-sync analyze worker is missing: ${workerPath}`));
49
+ return;
50
+ }
51
+ const workerHeapMb = resolveWorkerHeapMb(concurrency);
52
+ const execArgv = isDev
53
+ ? [
54
+ '--import',
55
+ pathToFileURL(_require.resolve('tsx/esm')).href,
56
+ `--max-old-space-size=${workerHeapMb}`,
57
+ ]
58
+ : [`--max-old-space-size=${workerHeapMb}`];
59
+ const child = deps.forkWorker(workerPath, execArgv);
60
+ child.stdout?.resume();
61
+ child.stderr?.resume();
62
+ let terminalOutcome;
63
+ let terminationError;
64
+ let settled = false;
65
+ let graceTimer;
66
+ const cleanup = () => {
67
+ deps.clearTimeoutFn(timeout);
68
+ deps.clearTimeoutFn(graceTimer);
69
+ signal?.removeEventListener('abort', onAbort);
70
+ };
71
+ // Stop the parent owning a worker it has given up waiting for. An
72
+ // established IPC channel keeps this event loop alive even after unref,
73
+ // so both handles have to go. Never a kill: the child may be inside
74
+ // native work and is left to reach its own safe point.
75
+ const releaseChild = () => {
76
+ child.channel?.unref?.();
77
+ child.unref?.();
78
+ };
79
+ const settle = (error, result) => {
80
+ if (settled)
81
+ return;
82
+ settled = true;
83
+ cleanup();
84
+ if (error)
85
+ reject(error);
86
+ else
87
+ resolve(result);
88
+ };
89
+ const requestCancellation = (error) => {
90
+ if (settled || terminationError)
91
+ return;
92
+ terminationError = error;
93
+ deps.clearTimeoutFn(timeout);
94
+ onCancellationRequested?.();
95
+ // IPC has the same semantics on macOS and Windows. The worker exits only
96
+ // after reaching a JS-visible safe point; this parent keeps ownership until then.
97
+ try {
98
+ child.send({ type: 'cancel' });
99
+ }
100
+ catch {
101
+ // A closed IPC channel still has an exit/error path. Do not force-kill a
102
+ // worker that may be inside native code.
103
+ }
104
+ // Bounded wait. A worker stuck past its safe point would otherwise leave
105
+ // this promise pending forever, wedging `activeRun` so `stop()` — and the
106
+ // `watch stop` waiting on this process to exit — can never finish. Settle
107
+ // the parent's wait and drop the IPC channel's hold on this event loop;
108
+ // an established channel keeps the parent alive even after unref. The
109
+ // child is deliberately left running rather than killed mid-write.
110
+ graceTimer = deps.setTimeoutFn(() => {
111
+ if (settled)
112
+ return;
113
+ releaseChild();
114
+ settle(new Error(`${error.message} The analyze worker did not exit within ${deps.cancelGraceMs}ms; ` +
115
+ 'it was left running so its native work is not interrupted.'));
116
+ }, deps.cancelGraceMs);
117
+ };
118
+ const timeout = deps.setTimeoutFn(() => requestCancellation(new Error(`Analysis timed out after ${timeoutMs}ms.`)), timeoutMs);
119
+ const onAbort = () => requestCancellation(new Error('Analysis cancelled.'));
120
+ signal?.addEventListener('abort', onAbort, { once: true });
121
+ child.on('message', (message) => {
122
+ // Once timeout/cancellation requested shutdown, its reason owns the
123
+ // result. A terminal IPC can already be queued behind cancellation.
124
+ if (message.type === 'progress' || terminalOutcome || terminationError)
125
+ return;
126
+ terminalOutcome = message;
127
+ deps.clearTimeoutFn(timeout);
128
+ });
129
+ child.on('error', (error) => {
130
+ const workerError = new Error(`Auto-sync analyze worker error: ${error.message}`);
131
+ requestCancellation(workerError);
132
+ // This settles immediately rather than waiting out the grace, so the
133
+ // grace timer that would otherwise have released the child is cleared
134
+ // by cleanup(). Release it here instead — an errored channel does not
135
+ // mean the worker stopped.
136
+ releaseChild();
137
+ settle(workerError);
138
+ });
139
+ child.on('exit', (code, childSignal) => {
140
+ if (settled)
141
+ return;
142
+ if (terminationError) {
143
+ settle(terminationError);
144
+ return;
145
+ }
146
+ if (terminalOutcome?.type === 'complete') {
147
+ settle(undefined, { stats: terminalOutcome.result.stats });
148
+ return;
149
+ }
150
+ if (terminalOutcome?.type === 'error') {
151
+ settle(new Error(terminalOutcome.message));
152
+ return;
153
+ }
154
+ settle(new Error(`Auto-sync analyze worker exited before completion (${childSignal ?? code ?? 'unknown'}).`));
155
+ });
156
+ try {
157
+ child.send({ type: 'start', repoPath, options });
158
+ }
159
+ catch (error) {
160
+ const startError = new Error(`Failed to start auto-sync analyze worker: ${error.message}`);
161
+ requestCancellation(startError);
162
+ settle(startError);
163
+ }
164
+ });
165
+ }
166
+ export const runAutoSyncAnalysis = createAutoSyncAnalysisRunner();