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
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Query-parameter parsing for GET /api/grep.
3
+ *
4
+ * Extracted from api.ts so the contract is unit-testable without pulling
5
+ * Express + the LadybugDB native adapter into the test run (same rationale
6
+ * as the #2790 helper extraction).
7
+ *
8
+ * Contract fix (Patch 12): the grep tool schema in gitnexus-web has always
9
+ * promised regex search with an optional path-substring filter and
10
+ * case-sensitivity control, but the handler used to escapeRegExp() every
11
+ * pattern into a literal substring — an agent asking for "sign|Sign" got
12
+ * zero hits and concluded the code didn't exist, and the schema's own
13
+ * example ("console\.log") could never match. This restores the promised
14
+ * semantics. Matching runs in a worker_threads worker (`grep-worker.ts`) so
15
+ * `terminate()` can interrupt a catastrophic `regex.test()` when the
16
+ * wall-clock budget expires; the parent event loop stays responsive.
17
+ * Bounded mitigations:
18
+ * - pattern length cap (200 chars, unchanged from the literal-only era)
19
+ * - line-by-line matching (each regex.test call sees one source line)
20
+ * - a wall-clock budget the parent enforces via worker terminate()
21
+ * - result cap unchanged (limit, max 200)
22
+ * - literal=1 opt-out restores the old escaped-substring immunity
23
+ */
24
+ import { assertString, escapeRegExp, BadRequestError } from './validation.js';
25
+ /** Hard cap on pattern length — unchanged from the literal-only era. */
26
+ export const GREP_PATTERN_MAX_LENGTH = 200;
27
+ /** Wall-clock budget for one /api/grep call; parent terminate()s the scan worker. */
28
+ export const GREP_TIME_BUDGET_MS = 5_000;
29
+ export const GREP_DEFAULT_LIMIT = 50;
30
+ export const GREP_MAX_LIMIT = 200;
31
+ const isFlagTrue = (value, name) => {
32
+ const s = assertString(value ?? '', name).toLowerCase();
33
+ return s === '1' || s === 'true';
34
+ };
35
+ /**
36
+ * Parse /api/grep query parameters into a ready-to-use regex + filters.
37
+ * Throws BadRequestError (mapped to HTTP 400 by statusFromError) on
38
+ * missing/over-long patterns or invalid regex syntax.
39
+ */
40
+ export function parseGrepQuery(query) {
41
+ if (query.pattern === undefined) {
42
+ throw new BadRequestError('Missing "pattern" query parameter');
43
+ }
44
+ const pattern = assertString(query.pattern, 'pattern');
45
+ if (pattern.length === 0) {
46
+ throw new BadRequestError('Missing "pattern" query parameter');
47
+ }
48
+ if (pattern.length > GREP_PATTERN_MAX_LENGTH) {
49
+ throw new BadRequestError(`Pattern too long (max ${GREP_PATTERN_MAX_LENGTH} characters)`);
50
+ }
51
+ // Regex semantics by default — what the tool schema always promised.
52
+ // literal=1 opts back into the escaped-substring behaviour of the
53
+ // literal-only era for callers that want it verbatim.
54
+ const caseSensitive = isFlagTrue(query.caseSensitive, 'caseSensitive');
55
+ const flags = caseSensitive ? '' : 'i';
56
+ let regex;
57
+ try {
58
+ // Deliberately no 'g' flag: the handler tests line-by-line and a
59
+ // stateful lastIndex across lines would skip matches (the old handler
60
+ // had to reset it manually). No 'm' either: each test receives a
61
+ // single line, so ^/$ already anchor at string boundaries — 'm'
62
+ // would be a no-op.
63
+ if (isFlagTrue(query.literal, 'literal')) {
64
+ regex = new RegExp(escapeRegExp(pattern), flags);
65
+ }
66
+ else {
67
+ // Intentional: /api/grep advertises real regex (see file header + SECURITY.md).
68
+ // ReDoS is mitigated by running the scan in a worker and terminate()-ing it.
69
+ // codeql[js/regex-injection]
70
+ regex = new RegExp(pattern, flags);
71
+ }
72
+ }
73
+ catch {
74
+ throw new BadRequestError('Invalid regex pattern');
75
+ }
76
+ // Path-substring filter, case-insensitive ("Controller.java", "src/api").
77
+ const fileFilter = assertString(query.fileFilter ?? '', 'fileFilter').toLowerCase();
78
+ const parsedLimit = Number(query.limit ?? GREP_DEFAULT_LIMIT);
79
+ const limit = Number.isFinite(parsedLimit)
80
+ ? Math.max(1, Math.min(GREP_MAX_LIMIT, Math.trunc(parsedLimit)))
81
+ : GREP_DEFAULT_LIMIT;
82
+ return { regex, fileFilter, limit };
83
+ }
@@ -0,0 +1,23 @@
1
+ export interface GrepHit {
2
+ filePath: string;
3
+ line: number;
4
+ text: string;
5
+ }
6
+ export interface GrepScanInput {
7
+ repoRoot: string;
8
+ /** Repo-relative paths already filtered by fileFilter. */
9
+ filePaths: string[];
10
+ pattern: string;
11
+ flags: string;
12
+ limit: number;
13
+ /** Absolute Date.now() deadline. */
14
+ deadlineMs: number;
15
+ }
16
+ export interface GrepScanResult {
17
+ results: GrepHit[];
18
+ timedOut: boolean;
19
+ }
20
+ export type GrepProgress = (partial: GrepScanResult) => void;
21
+ export declare function scanGrepFiles(input: GrepScanInput, onProgress?: GrepProgress): Promise<GrepScanResult>;
22
+ export declare function grepWorkerPath(): string;
23
+ export declare function runGrepScanInWorker(input: GrepScanInput): Promise<GrepScanResult>;
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Filesystem grep scan used by GET /api/grep.
3
+ *
4
+ * Matching runs in a worker_threads worker (see grep-worker.ts) so a
5
+ * catastrophic `regex.test()` can be killed with terminate() when the
6
+ * wall-clock budget expires. The parent event loop stays responsive.
7
+ */
8
+ import fs from 'node:fs/promises';
9
+ import path from 'node:path';
10
+ import { createRequire } from 'node:module';
11
+ import { fileURLToPath, pathToFileURL } from 'node:url';
12
+ import { Worker } from 'node:worker_threads';
13
+ export async function scanGrepFiles(input, onProgress) {
14
+ const regex = new RegExp(input.pattern, input.flags);
15
+ const results = [];
16
+ const repoRoot = path.resolve(input.repoRoot);
17
+ const safeRepoRoot = repoRoot.endsWith(path.sep) ? repoRoot : repoRoot + path.sep;
18
+ let timedOut = false;
19
+ files: for (const filePath of input.filePaths) {
20
+ if (results.length >= input.limit)
21
+ break;
22
+ if (Date.now() > input.deadlineMs) {
23
+ timedOut = true;
24
+ break;
25
+ }
26
+ const fullPath = path.resolve(repoRoot, filePath);
27
+ if (!fullPath.startsWith(safeRepoRoot) && fullPath !== repoRoot)
28
+ continue;
29
+ let content;
30
+ try {
31
+ content = await fs.readFile(fullPath, 'utf-8');
32
+ }
33
+ catch {
34
+ continue;
35
+ }
36
+ const lines = content.split('\n');
37
+ for (let i = 0; i < lines.length; i++) {
38
+ if (results.length >= input.limit)
39
+ break files;
40
+ if ((i & 255) === 0 && Date.now() > input.deadlineMs) {
41
+ timedOut = true;
42
+ break files;
43
+ }
44
+ regex.lastIndex = 0;
45
+ if (regex.test(lines[i])) {
46
+ results.push({ filePath, line: i + 1, text: lines[i].trim().slice(0, 200) });
47
+ }
48
+ }
49
+ onProgress?.({ results: results.slice(), timedOut });
50
+ }
51
+ return { results, timedOut };
52
+ }
53
+ const _require = createRequire(import.meta.url);
54
+ export function grepWorkerPath() {
55
+ const callerPath = fileURLToPath(import.meta.url);
56
+ const isDev = callerPath.endsWith('.ts');
57
+ return path.join(path.dirname(callerPath), isDev ? 'grep-worker.ts' : 'grep-worker.js');
58
+ }
59
+ export function runGrepScanInWorker(input) {
60
+ const callerPath = fileURLToPath(import.meta.url);
61
+ const isDev = callerPath.endsWith('.ts');
62
+ const tsxHookArgs = isDev
63
+ ? ['--import', pathToFileURL(_require.resolve('tsx/esm')).href]
64
+ : [];
65
+ return new Promise((resolve, reject) => {
66
+ let settled = false;
67
+ let latest = { results: [], timedOut: false };
68
+ const worker = new Worker(grepWorkerPath(), {
69
+ workerData: input,
70
+ execArgv: tsxHookArgs,
71
+ });
72
+ const finish = (result) => {
73
+ if (settled)
74
+ return;
75
+ settled = true;
76
+ clearTimeout(timer);
77
+ void worker.terminate();
78
+ resolve(result);
79
+ };
80
+ const remain = Math.max(1, input.deadlineMs - Date.now());
81
+ const timer = setTimeout(() => {
82
+ finish({ results: latest.results, timedOut: true });
83
+ }, remain);
84
+ worker.on('message', (msg) => {
85
+ if (msg.type === 'progress') {
86
+ latest = { results: msg.results, timedOut: msg.timedOut };
87
+ return;
88
+ }
89
+ if (msg.type === 'done') {
90
+ finish({ results: msg.results, timedOut: msg.timedOut });
91
+ }
92
+ });
93
+ worker.on('error', (err) => {
94
+ if (settled)
95
+ return;
96
+ settled = true;
97
+ clearTimeout(timer);
98
+ void worker.terminate();
99
+ reject(err);
100
+ });
101
+ worker.on('exit', () => {
102
+ if (settled)
103
+ return;
104
+ finish({ results: latest.results, timedOut: true });
105
+ });
106
+ });
107
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { parentPort, workerData } from 'node:worker_threads';
2
+ if (!parentPort) {
3
+ throw new Error('grep-worker must run as a worker_threads worker');
4
+ }
5
+ const ext = import.meta.url.endsWith('.ts') ? '.ts' : '.js';
6
+ const { scanGrepFiles } = await import(new URL(`./grep-scan${ext}`, import.meta.url).href);
7
+ const port = parentPort;
8
+ const input = workerData;
9
+ const out = await scanGrepFiles(input, (partial) => {
10
+ port.postMessage({ type: 'progress', ...partial });
11
+ });
12
+ port.postMessage({ type: 'done', ...out });
@@ -9,4 +9,12 @@
9
9
  */
10
10
  import type { Express } from 'express';
11
11
  import type { LocalBackend } from '../mcp/local/local-backend.js';
12
+ /**
13
+ * Protect serve's /api/mcp route when the shared MCP bearer token is configured.
14
+ *
15
+ * This middleware must be installed before Express's global JSON parser so an
16
+ * unauthenticated request body is rejected before it is parsed. The standalone
17
+ * `gitnexus mcp --http` server resolves the same environment variable.
18
+ */
19
+ export declare function installServeMcpAuth(app: Express, env?: NodeJS.ProcessEnv): boolean;
12
20
  export declare function mountMCPEndpoints(app: Express, backend: LocalBackend): Promise<() => Promise<void>>;
@@ -7,9 +7,24 @@
7
7
  *
8
8
  * Used by server/api.ts to wire up the full web server.
9
9
  */
10
- import { createStreamableHttpHandler } from '../mcp/http-transport.js';
10
+ import { createAuthMiddleware, createStreamableHttpHandler, resolveAuthToken, } from '../mcp/http-transport.js';
11
11
  import { createMcpRepositoryPolicy } from '../mcp/repository-policy.js';
12
12
  import { logger } from '../core/logger.js';
13
+ /**
14
+ * Protect serve's /api/mcp route when the shared MCP bearer token is configured.
15
+ *
16
+ * This middleware must be installed before Express's global JSON parser so an
17
+ * unauthenticated request body is rejected before it is parsed. The standalone
18
+ * `gitnexus mcp --http` server resolves the same environment variable.
19
+ */
20
+ export function installServeMcpAuth(app, env = process.env) {
21
+ const authToken = resolveAuthToken(undefined, env);
22
+ if (!authToken)
23
+ return false;
24
+ app.use('/api/mcp', createAuthMiddleware(authToken));
25
+ logger.info('Bearer authentication enabled for serve /api/mcp');
26
+ return true;
27
+ }
13
28
  export async function mountMCPEndpoints(app, backend) {
14
29
  const repositoryPolicy = await createMcpRepositoryPolicy(backend);
15
30
  const { handler, cleanup } = createStreamableHttpHandler(backend, { repositoryPolicy });
@@ -0,0 +1,29 @@
1
+ import { type UpdateState } from '../core/update-check.js';
2
+ export interface ServerInfoResponse {
3
+ version: string;
4
+ launchContext: 'npx' | 'global' | 'local';
5
+ nodeVersion: string;
6
+ latestVersion?: string;
7
+ updateAvailable?: boolean;
8
+ }
9
+ interface ServeUpdateControllerDependencies {
10
+ evaluate: (options?: {
11
+ refreshIfStale?: boolean;
12
+ }) => Promise<UpdateState | null>;
13
+ armScheduler: (onState: (state: UpdateState | null) => void) => () => void;
14
+ }
15
+ export interface ServeUpdateController {
16
+ start: () => Promise<void>;
17
+ stop: () => void;
18
+ snapshot: () => UpdateState | null;
19
+ }
20
+ /**
21
+ * Own the update state for one `serve` process. The route reads snapshot()
22
+ * synchronously; all cache and network work stays on the startup/scheduler path.
23
+ */
24
+ export declare const createServeUpdateController: (dependencies?: ServeUpdateControllerDependencies) => ServeUpdateController;
25
+ export declare const buildServerInfo: (updateState: UpdateState | null) => ServerInfoResponse;
26
+ export declare const bindServeUpdateControllerLifecycle: (server: {
27
+ once(event: "listening" | "close", listener: () => void): unknown;
28
+ }, controller: ServeUpdateController) => void;
29
+ export {};
@@ -0,0 +1,82 @@
1
+ import { packageVersion } from '../core/package-version.js';
2
+ import { armUpdateRefreshScheduler, evaluate } from '../core/update-check.js';
3
+ /**
4
+ * Own the update state for one `serve` process. The route reads snapshot()
5
+ * synchronously; all cache and network work stays on the startup/scheduler path.
6
+ */
7
+ export const createServeUpdateController = (dependencies = {
8
+ evaluate,
9
+ armScheduler: armUpdateRefreshScheduler,
10
+ }) => {
11
+ let updateState = null;
12
+ let stopScheduler;
13
+ let started = false;
14
+ let stopped = false;
15
+ return {
16
+ start: async () => {
17
+ if (started || stopped)
18
+ return;
19
+ started = true;
20
+ try {
21
+ // Cache-only: the scheduler's first cycle owns any stale refresh.
22
+ updateState = await dependencies.evaluate({ refreshIfStale: false });
23
+ }
24
+ catch {
25
+ updateState = null;
26
+ }
27
+ if (stopped)
28
+ return;
29
+ try {
30
+ stopScheduler = dependencies.armScheduler((state) => {
31
+ if (state?.updateAvailable !== updateState?.updateAvailable ||
32
+ state?.latestVersion !== updateState?.latestVersion) {
33
+ updateState = state;
34
+ }
35
+ });
36
+ }
37
+ catch {
38
+ // Update checks are best-effort and never affect HTTP availability.
39
+ }
40
+ },
41
+ stop: () => {
42
+ if (stopped)
43
+ return;
44
+ stopped = true;
45
+ try {
46
+ stopScheduler?.();
47
+ }
48
+ catch {
49
+ // Shutdown must continue even if notifier cleanup unexpectedly fails.
50
+ }
51
+ },
52
+ snapshot: () => updateState,
53
+ };
54
+ };
55
+ export const buildServerInfo = (updateState) => {
56
+ const execPath = process.env.npm_execpath ?? '';
57
+ const argv0 = process.argv[1] ?? '';
58
+ let launchContext;
59
+ if (execPath.includes('npx') ||
60
+ argv0.includes('_npx') ||
61
+ process.env.npm_config_prefix?.includes('_npx')) {
62
+ launchContext = 'npx';
63
+ }
64
+ else if (argv0.includes('node_modules')) {
65
+ launchContext = 'local';
66
+ }
67
+ else {
68
+ launchContext = 'global';
69
+ }
70
+ return {
71
+ version: packageVersion(),
72
+ launchContext,
73
+ nodeVersion: process.version,
74
+ ...(updateState?.updateAvailable && updateState.latestVersion
75
+ ? { latestVersion: updateState.latestVersion, updateAvailable: true }
76
+ : {}),
77
+ };
78
+ };
79
+ export const bindServeUpdateControllerLifecycle = (server, controller) => {
80
+ server.once('listening', () => void controller.start());
81
+ server.once('close', controller.stop);
82
+ };
@@ -0,0 +1,15 @@
1
+ export interface FileLockOptions {
2
+ retries?: number;
3
+ retryDelayMs?: number;
4
+ pid?: number;
5
+ processStartTime?: string;
6
+ hostname?: string;
7
+ isProcessAlive?: (pid: number) => boolean;
8
+ readProcessStartTime?: (pid: number) => string | undefined;
9
+ }
10
+ export declare class FileLockBusyError extends Error {
11
+ readonly lockPath: string;
12
+ constructor(lockPath: string);
13
+ }
14
+ /** Acquire a recoverable cross-process mutex using an atomically published owner file. */
15
+ export declare function acquireFileLock(lockPath: string, options?: FileLockOptions): Promise<() => Promise<void>>;
@@ -0,0 +1,155 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { setTimeout as sleep } from 'node:timers/promises';
6
+ import { isProcessAlive, readProcessStartTime } from '../utils/process-identity.js';
7
+ const HOSTNAME = os.hostname();
8
+ export class FileLockBusyError extends Error {
9
+ lockPath;
10
+ constructor(lockPath) {
11
+ super(`Lock is already held: ${lockPath}. Confirm no owner process is active, then remove it manually.`);
12
+ this.lockPath = lockPath;
13
+ this.name = 'FileLockBusyError';
14
+ }
15
+ }
16
+ /** Acquire a recoverable cross-process mutex using an atomically published owner file. */
17
+ export async function acquireFileLock(lockPath, options = {}) {
18
+ const resolvedPath = path.resolve(lockPath);
19
+ const retries = options.retries ?? 0;
20
+ const retryDelayMs = options.retryDelayMs ?? 50;
21
+ const pid = options.pid ?? process.pid;
22
+ const owner = {
23
+ pid,
24
+ ownerId: crypto.randomUUID(),
25
+ processStartTime: options.processStartTime ?? (options.readProcessStartTime ?? readProcessStartTime)(pid) ?? '',
26
+ hostname: options.hostname ?? HOSTNAME,
27
+ };
28
+ if (!owner.processStartTime) {
29
+ throw new Error(`Unable to determine process start time for file lock owner pid ${owner.pid}.`);
30
+ }
31
+ await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
32
+ const pendingPath = `${resolvedPath}.pending-${owner.ownerId}`;
33
+ await fs.writeFile(pendingPath, `${JSON.stringify(owner)}\n`, { encoding: 'utf-8', flag: 'wx' });
34
+ try {
35
+ for (let attempt = 0;; attempt += 1) {
36
+ try {
37
+ await fs.link(pendingPath, resolvedPath);
38
+ break;
39
+ }
40
+ catch (error) {
41
+ if (!(await isLockConflict(error, resolvedPath)))
42
+ throw error;
43
+ if (await reclaimStaleLock(resolvedPath, owner, options.isProcessAlive ?? isProcessAlive, options.readProcessStartTime ?? readProcessStartTime)) {
44
+ continue;
45
+ }
46
+ if (attempt >= retries)
47
+ throw new FileLockBusyError(lockPath);
48
+ await sleep(retryDelayMs);
49
+ }
50
+ }
51
+ }
52
+ finally {
53
+ // The lock is already published by now, but the release closure below is
54
+ // not yet in the caller's hands. Letting a staging-file cleanup error
55
+ // escape would strand a lock nobody can release, so prefer leaking the
56
+ // pending file — its name is per-acquisition, so it can never block anyone.
57
+ await fs.rm(pendingPath, { force: true }).catch(() => { });
58
+ }
59
+ let releasePromise;
60
+ return () => (releasePromise ??= releaseOwnedLock(resolvedPath, owner.ownerId));
61
+ }
62
+ async function reclaimStaleLock(lockPath, guardOwner, ownerIsAlive, getProcessStartTime) {
63
+ const reclaimGuardPath = `${lockPath}.reclaim`;
64
+ let releaseReclaimGuard;
65
+ try {
66
+ releaseReclaimGuard = await acquireFileLock(reclaimGuardPath, {
67
+ pid: guardOwner.pid,
68
+ processStartTime: guardOwner.processStartTime,
69
+ hostname: guardOwner.hostname,
70
+ isProcessAlive: ownerIsAlive,
71
+ readProcessStartTime: getProcessStartTime,
72
+ });
73
+ }
74
+ catch (error) {
75
+ if (error instanceof FileLockBusyError)
76
+ return false;
77
+ throw error;
78
+ }
79
+ try {
80
+ const owner = await readOwner(lockPath);
81
+ if (!owner)
82
+ return false;
83
+ // A pid only means something on the machine that issued it. Asking this
84
+ // kernel about a holder on another host answers about an unrelated process
85
+ // — or nothing — and either way the answer is "stale", which would steal a
86
+ // live lock whenever GITNEXUS_HOME is a shared volume.
87
+ if (owner.hostname !== guardOwner.hostname)
88
+ return false;
89
+ if (ownerIsAlive(owner.pid)) {
90
+ const currentStartTime = getProcessStartTime(owner.pid);
91
+ if (!currentStartTime || currentStartTime === owner.processStartTime)
92
+ return false;
93
+ }
94
+ await fs.rm(lockPath, { force: true });
95
+ return true;
96
+ }
97
+ finally {
98
+ await releaseReclaimGuard();
99
+ }
100
+ }
101
+ async function releaseOwnedLock(lockPath, ownerId) {
102
+ const releasePath = `${lockPath}.release-${ownerId}-${crypto.randomUUID()}`;
103
+ if (!(await moveOwnedLock(lockPath, releasePath, ownerId)))
104
+ return;
105
+ await fs.rm(releasePath, { force: true });
106
+ }
107
+ async function moveOwnedLock(lockPath, destinationPath, ownerId) {
108
+ if ((await readOwner(lockPath))?.ownerId !== ownerId)
109
+ return false;
110
+ try {
111
+ await fs.rename(lockPath, destinationPath);
112
+ }
113
+ catch (error) {
114
+ if (error.code === 'ENOENT')
115
+ return false;
116
+ throw error;
117
+ }
118
+ if ((await readOwner(destinationPath))?.ownerId === ownerId)
119
+ return true;
120
+ await fs.rename(destinationPath, lockPath).catch(() => { });
121
+ return false;
122
+ }
123
+ async function readOwner(lockPath) {
124
+ try {
125
+ const parsed = JSON.parse(await fs.readFile(lockPath, 'utf-8'));
126
+ if (Number.isInteger(parsed.pid) &&
127
+ Number(parsed.pid) > 0 &&
128
+ typeof parsed.ownerId === 'string' &&
129
+ parsed.ownerId &&
130
+ typeof parsed.processStartTime === 'string' &&
131
+ parsed.processStartTime &&
132
+ typeof parsed.hostname === 'string' &&
133
+ parsed.hostname) {
134
+ return parsed;
135
+ }
136
+ }
137
+ catch {
138
+ // Invalid or legacy locks fail closed; only verified dead owners are reclaimed.
139
+ }
140
+ return undefined;
141
+ }
142
+ async function isLockConflict(error, lockPath) {
143
+ const code = error.code;
144
+ if (code === 'EEXIST')
145
+ return true;
146
+ if (code !== 'EPERM')
147
+ return false;
148
+ try {
149
+ await fs.access(lockPath);
150
+ return true;
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ }
@@ -28,3 +28,27 @@ export declare function retryRename(src: string, dst: string, attempts?: number)
28
28
  * retry backoff (and, under a lock, make everyone else wait for it).
29
29
  */
30
30
  export declare function writeFileAtomic(targetPath: string, data: string, attempts?: number): Promise<void>;
31
+ /**
32
+ * Publish `src` at `dst` without ever writing through the inode currently
33
+ * named by `dst` (#3090). Fast path is `fs.link`. Any failure (EEXIST, EXDEV,
34
+ * EPERM, unsupported hardlinks) copies into a unique sibling and
35
+ * {@link retryRename}s over `dst`. POSIX rename of a file over an existing
36
+ * file unlinks the old name; it does not open or truncate that inode.
37
+ *
38
+ * Invariant: may replace the destination directory entry; must never modify
39
+ * the inode that entry currently references. There is no dest unlink and no
40
+ * in-place `copyFile(src, dst)`.
41
+ */
42
+ export declare function linkOrCopyFile(src: string, dst: string): Promise<void>;
43
+ /**
44
+ * Binary sibling of {@link writeFileAtomic}. Same random tmp + `'wx'` + `0o600`
45
+ * + rename contract; used for optional V8 cache sidecars that cannot go through
46
+ * a UTF-8 `writeFile`.
47
+ */
48
+ export declare function writeFileAtomicBytes(targetPath: string, data: Uint8Array, attempts?: number): Promise<void>;
49
+ /**
50
+ * Sync binary publish for parse workers. Same exclusive-tmp + mode contract as
51
+ * {@link writeFileAtomicBytes}; rename is not retried (the worker is not the
52
+ * Windows multi-reader case `retryRename` exists for).
53
+ */
54
+ export declare function writeFileAtomicBytesSync(targetPath: string, data: Uint8Array): void;