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
@@ -1,7 +1,20 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
+ import { XMLParser } from 'fast-xml-parser';
3
4
  import { shouldIgnorePath, loadIgnoreRules } from '../../../config/ignore-service.js';
4
5
  import { logger } from '../../logger.js';
6
+ // POMs are static metadata. Parse hierarchy with a real XML parser, but do not
7
+ // invoke Maven or resolve the effective model. Properties, profiles, and remote
8
+ // parent resolution remain outside this extractor's deterministic boundary.
9
+ const pomParser = new XMLParser({
10
+ ignoreAttributes: true,
11
+ removeNSPrefix: true,
12
+ trimValues: true,
13
+ parseTagValue: false,
14
+ processEntities: false,
15
+ ignoreDeclaration: true,
16
+ ignorePiTags: true,
17
+ });
5
18
  async function parseJavaManifest(repoPath) {
6
19
  const pomPath = path.join(repoPath, 'pom.xml');
7
20
  try {
@@ -9,13 +22,14 @@ async function parseJavaManifest(repoPath) {
9
22
  return parsePom(content);
10
23
  }
11
24
  catch {
12
- // fall through to Gradle
25
+ // Missing pom.xml — fall through to Gradle.
13
26
  }
27
+ const gradleSidecars = await readGradleSidecars(repoPath);
14
28
  for (const name of ['build.gradle.kts', 'build.gradle']) {
15
29
  const gradlePath = path.join(repoPath, name);
16
30
  try {
17
31
  const content = await fs.readFile(gradlePath, 'utf-8');
18
- return parseGradle(content, repoPath);
32
+ return parseGradle(content, repoPath, gradleSidecars);
19
33
  }
20
34
  catch {
21
35
  continue;
@@ -23,45 +37,244 @@ async function parseJavaManifest(repoPath) {
23
37
  }
24
38
  return null;
25
39
  }
40
+ async function readIfPresent(filePath) {
41
+ try {
42
+ return await fs.readFile(filePath, 'utf-8');
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
48
+ async function readGradleSidecars(repoPath) {
49
+ const [properties, settingsKts, settingsGroovy, catalog] = await Promise.all([
50
+ readIfPresent(path.join(repoPath, 'gradle.properties')),
51
+ readIfPresent(path.join(repoPath, 'settings.gradle.kts')),
52
+ readIfPresent(path.join(repoPath, 'settings.gradle')),
53
+ readIfPresent(path.join(repoPath, 'gradle', 'libs.versions.toml')),
54
+ ]);
55
+ const sidecars = {
56
+ catalogLibraries: new Map(),
57
+ catalogBundles: new Map(),
58
+ };
59
+ const groupMatch = properties?.match(/(?:^|\n)\s*group\s*=\s*([^\s#]+)/);
60
+ if (groupMatch)
61
+ sidecars.propertiesGroup = groupMatch[1];
62
+ const settings = settingsKts ?? settingsGroovy;
63
+ const nameMatch = settings?.match(/rootProject\.name\s*=\s*['"]([^'"]+)['"]/);
64
+ if (nameMatch)
65
+ sidecars.rootProjectName = nameMatch[1];
66
+ if (catalog) {
67
+ const parsed = parseGradleVersionCatalog(catalog);
68
+ sidecars.catalogLibraries = parsed.libraries;
69
+ sidecars.catalogBundles = parsed.bundles;
70
+ }
71
+ return sidecars;
72
+ }
73
+ function catalogAccessors(alias) {
74
+ const dotted = alias.replace(/[-_]/g, '.');
75
+ const camel = alias.replace(/[-_]+([A-Za-z0-9])/g, (_, char) => char.toUpperCase());
76
+ return [...new Set([alias, dotted, camel])];
77
+ }
78
+ function projectAccessorToArtifactId(accessor) {
79
+ const last = accessor.split('.').pop();
80
+ return last.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`).replace(/^-/, '');
81
+ }
82
+ function moduleToGa(module) {
83
+ const parts = module.split(':');
84
+ return parts.length >= 2 ? `${parts[0]}:${parts[1]}` : undefined;
85
+ }
86
+ function parseInlineTomlTable(rhs) {
87
+ const fields = {};
88
+ for (const match of rhs.matchAll(/([A-Za-z0-9_-]+)\s*=\s*['"]([^'"]+)['"]/g)) {
89
+ fields[match[1]] = match[2];
90
+ }
91
+ return fields;
92
+ }
93
+ /** Default Gradle catalog (`gradle/libs.versions.toml`) — aliases only, no version resolution. */
94
+ function parseGradleVersionCatalog(toml) {
95
+ const libraries = new Map();
96
+ const bundles = new Map();
97
+ let section = 'other';
98
+ const addLibrary = (alias, ga) => {
99
+ for (const accessor of catalogAccessors(alias))
100
+ libraries.set(accessor, ga);
101
+ };
102
+ for (const raw of toml.split(/\r?\n/)) {
103
+ const line = raw.replace(/#.*$/, '').trim();
104
+ if (!line)
105
+ continue;
106
+ const header = line.match(/^\[([^\]]+)\]$/);
107
+ if (header) {
108
+ const name = header[1];
109
+ section =
110
+ name === 'libraries' || name.endsWith('.libraries')
111
+ ? 'libraries'
112
+ : name === 'bundles' || name.endsWith('.bundles')
113
+ ? 'bundles'
114
+ : 'other';
115
+ continue;
116
+ }
117
+ if (section === 'libraries') {
118
+ const dottedModule = line.match(/^([A-Za-z0-9._-]+)\.module\s*=\s*['"]([^'"]+)['"]$/);
119
+ if (dottedModule) {
120
+ const ga = moduleToGa(dottedModule[2]);
121
+ if (ga)
122
+ addLibrary(dottedModule[1], ga);
123
+ continue;
124
+ }
125
+ const assignment = line.match(/^([A-Za-z0-9._-]+)\s*=\s*(.+)$/);
126
+ if (!assignment)
127
+ continue;
128
+ const alias = assignment[1];
129
+ const rhs = assignment[2].trim();
130
+ const quoted = rhs.match(/^['"]([^'"]+)['"]$/);
131
+ if (quoted) {
132
+ const ga = moduleToGa(quoted[1]);
133
+ if (ga)
134
+ addLibrary(alias, ga);
135
+ continue;
136
+ }
137
+ const table = parseInlineTomlTable(rhs);
138
+ const ga = table.module
139
+ ? moduleToGa(table.module)
140
+ : table.group && table.name
141
+ ? `${table.group}:${table.name}`
142
+ : undefined;
143
+ if (ga)
144
+ addLibrary(alias, ga);
145
+ continue;
146
+ }
147
+ if (section === 'bundles') {
148
+ const assignment = line.match(/^([A-Za-z0-9._-]+)\s*=\s*\[([^\]]*)\]$/);
149
+ if (!assignment)
150
+ continue;
151
+ const members = [...assignment[2].matchAll(/['"]([^'"]+)['"]/g)].map((match) => match[1]);
152
+ for (const accessor of catalogAccessors(assignment[1]))
153
+ bundles.set(accessor, members);
154
+ }
155
+ }
156
+ return { libraries, bundles };
157
+ }
158
+ const GRADLE_GROUP_PATTERNS = [
159
+ /(?:^|[\n{;])\s*(?:rootProject\.)?group\s*=\s*['"]([^'"]+)['"]/,
160
+ /(?:^|[\n{;])\s*group\s+['"]([^'"]+)['"]/,
161
+ ];
162
+ const GRADLE_COORD_CONFIGS = 'implementation|api|compileOnly|runtimeOnly|testImplementation|testApi|testCompileOnly|compile|kapt|ksp|commonMainImplementation|commonMainApi';
163
+ const CATALOG_ALIAS = '([A-Za-z0-9_]+(?:\\.[A-Za-z0-9_]+)*)(?:\\.get\\(\\)|\\.asProvider\\(\\))?';
164
+ function gradleDepRe(suffix) {
165
+ return new RegExp(`(?:${GRADLE_COORD_CONFIGS})\\s*${suffix}`, 'g');
166
+ }
167
+ function parseGradleGroup(content) {
168
+ for (const pattern of GRADLE_GROUP_PATTERNS) {
169
+ const match = content.match(pattern);
170
+ if (match?.[1])
171
+ return match[1];
172
+ }
173
+ return undefined;
174
+ }
175
+ function asXmlNode(value) {
176
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
177
+ ? value
178
+ : undefined;
179
+ }
180
+ function xmlText(value) {
181
+ if (typeof value === 'string' || typeof value === 'number') {
182
+ const text = String(value).trim();
183
+ return text || undefined;
184
+ }
185
+ const nested = asXmlNode(value)?.['#text'];
186
+ if (nested === undefined)
187
+ return undefined;
188
+ return xmlText(nested);
189
+ }
190
+ function xmlChildText(node, name) {
191
+ return node ? xmlText(node[name]) : undefined;
192
+ }
193
+ function asList(value) {
194
+ if (value === undefined || value === null)
195
+ return [];
196
+ return Array.isArray(value) ? value : [value];
197
+ }
198
+ /** Direct project dependencies only — not BOM, profiles, or plugin classpath. */
199
+ function collectProjectDependencies(project, deps) {
200
+ const dependencies = asXmlNode(project.dependencies);
201
+ if (!dependencies)
202
+ return;
203
+ for (const dep of asList(dependencies.dependency)) {
204
+ const depNode = asXmlNode(dep);
205
+ const groupId = xmlChildText(depNode, 'groupId');
206
+ const artifactId = xmlChildText(depNode, 'artifactId');
207
+ if (groupId && artifactId)
208
+ deps.push(`${groupId}:${artifactId}`);
209
+ }
210
+ }
26
211
  function parsePom(content) {
27
- const projectGroupMatch = content.match(/<project[^>]*>[\s\S]*?<groupId>([^<]+)<\/groupId>/);
28
- const projectArtifactMatch = content.match(/<project[^>]*>[\s\S]*?<artifactId>([^<]+)<\/artifactId>/);
29
- if (!projectGroupMatch || !projectArtifactMatch)
212
+ let parsed;
213
+ try {
214
+ // parseSourceSafe guards tree-sitter's Windows SIGSEGV by switching to a
215
+ // chunked input callback above 16 KB; XMLParser only accepts XML text, so
216
+ // routing POMs through it silently yields an empty document.
217
+ // eslint-disable-next-line gitnexus/require-safe-parse
218
+ parsed = pomParser.parse(content);
219
+ }
220
+ catch {
30
221
  return null;
31
- const groupId = projectGroupMatch[1].trim();
32
- const artifactId = projectArtifactMatch[1].trim();
33
- const deps = [];
34
- const depBlocks = content.matchAll(/<dependency>\s*([\s\S]*?)<\/dependency>/g);
35
- for (const block of depBlocks) {
36
- const gMatch = block[1].match(/<groupId>([^<]+)<\/groupId>/);
37
- const aMatch = block[1].match(/<artifactId>([^<]+)<\/artifactId>/);
38
- if (gMatch && aMatch) {
39
- deps.push(`${gMatch[1].trim()}:${aMatch[1].trim()}`);
40
- }
41
222
  }
223
+ const project = asXmlNode(asXmlNode(parsed)?.project);
224
+ if (!project)
225
+ return null;
226
+ // Maven inherits groupId from <parent>, but artifactId is always the
227
+ // project's own direct child and must never fall back to parent.artifactId.
228
+ const groupId = xmlChildText(project, 'groupId') ?? xmlChildText(asXmlNode(project.parent), 'groupId');
229
+ const artifactId = xmlChildText(project, 'artifactId');
230
+ if (!groupId || !artifactId)
231
+ return null;
232
+ const deps = [];
233
+ collectProjectDependencies(project, deps);
42
234
  return { groupId, artifactId, deps: [...new Set(deps)] };
43
235
  }
44
- function parseGradle(content, repoPath) {
45
- const groupMatch = content.match(/group\s*=\s*['"]([^'"]+)['"]/);
46
- const dirName = path.basename(repoPath);
47
- const groupId = groupMatch ? groupMatch[1] : '';
236
+ function parseGradle(content, repoPath, sidecars = { catalogLibraries: new Map(), catalogBundles: new Map() }) {
237
+ // Static text + default catalog file. Do not execute Gradle.
238
+ const groupId = parseGradleGroup(content) ?? sidecars.propertiesGroup ?? '';
48
239
  if (!groupId)
49
240
  return null;
50
- const artifactId = dirName;
241
+ const artifactId = sidecars.rootProjectName ?? path.basename(repoPath);
242
+ const { catalogLibraries, catalogBundles } = sidecars;
51
243
  const deps = [];
52
- // implementation("group:artifact:version") or api("group:artifact:version")
53
- const depMatches = content.matchAll(/(?:implementation|api|compileOnly|runtimeOnly)\s*\(\s*['"]([^'"]+)['"]\s*\)/g);
54
- for (const m of depMatches) {
55
- const parts = m[1].split(':');
56
- if (parts.length >= 2) {
57
- deps.push(`${parts[0]}:${parts[1]}`);
244
+ const pushCatalogAlias = (alias) => {
245
+ const ga = catalogLibraries.get(alias);
246
+ if (ga)
247
+ deps.push(ga);
248
+ };
249
+ const namedPattern = gradleDepRe(`(?:\\(\\s*)?(?:group\\s*=\\s*['"](?<group1>[^'"]+)['"]\\s*,\\s*name\\s*=\\s*['"](?<name1>[^'"]+)['"]|name\\s*=\\s*['"](?<name2>[^'"]+)['"]\\s*,\\s*group\\s*=\\s*['"](?<group2>[^'"]+)['"]|group:\\s*['"](?<group3>[^'"]+)['"]\\s*,\\s*name:\\s*['"](?<name3>[^'"]+)['"]|name:\\s*['"](?<name4>[^'"]+)['"]\\s*,\\s*group:\\s*['"](?<group4>[^'"]+)['"])`);
250
+ for (const match of content.matchAll(namedPattern)) {
251
+ const group = match.groups?.group1 ?? match.groups?.group2 ?? match.groups?.group3 ?? match.groups?.group4;
252
+ const name = match.groups?.name1 ?? match.groups?.name2 ?? match.groups?.name3 ?? match.groups?.name4;
253
+ if (group && name)
254
+ deps.push(`${group}:${name}`);
255
+ }
256
+ for (const match of content.matchAll(gradleDepRe(`(?:\\(\\s*)?libs(?:\\.libraries)?\\.(?!bundles\\.|plugins\\.)${CATALOG_ALIAS}`))) {
257
+ pushCatalogAlias(match[1]);
258
+ }
259
+ for (const match of content.matchAll(gradleDepRe(`(?:\\(\\s*)?libs\\.bundles\\.${CATALOG_ALIAS}`))) {
260
+ for (const member of catalogBundles.get(match[1]) ?? []) {
261
+ for (const accessor of catalogAccessors(member))
262
+ pushCatalogAlias(accessor);
58
263
  }
59
264
  }
60
- // implementation(project(":subproject"))
61
- const projDeps = content.matchAll(/(?:implementation|api)\s*\(\s*project\s*\(\s*['"]([^'"]+)['"]\s*\)\s*\)/g);
62
- for (const m of projDeps) {
63
- const subName = m[1].replace(/^:/, '');
64
- deps.push(`${groupId}:${subName}`);
265
+ for (const match of content.matchAll(gradleDepRe(`\\(\\s*projects\\.([A-Za-z][A-Za-z0-9.]*)`))) {
266
+ deps.push(`${groupId}:${projectAccessorToArtifactId(match[1])}`);
267
+ }
268
+ for (const match of content.matchAll(gradleDepRe(`(?:\\(\\s*['"]([^'"]+)['"]\\s*\\)|['"]([^'"]+)['"])`))) {
269
+ const coord = match[1] ?? match[2];
270
+ if (!coord)
271
+ continue;
272
+ const parts = coord.split(':');
273
+ if (parts.length >= 2)
274
+ deps.push(`${parts[0]}:${parts[1]}`);
275
+ }
276
+ for (const match of content.matchAll(gradleDepRe(`(?:\\(\\s*)?project\\s*\\(\\s*['"]([^'"]+)['"]\\s*\\)`))) {
277
+ deps.push(`${groupId}:${match[1].replace(/^:/, '')}`);
65
278
  }
66
279
  return { groupId, artifactId, deps: [...new Set(deps)] };
67
280
  }
@@ -21,12 +21,11 @@
21
21
  * else claims: group directories live under `~/.gitnexus/groups/<name>` (or
22
22
  * `$GITNEXUS_HOME`), never under a repo's `.gitnexus[/branches/<slug>]`.
23
23
  *
24
- * WHY IT FAILS CLOSED, unlike the registry lock. `withRegistryLock` degrades to
25
- * running UNLOCKED on timeout, and that is right for it: it guards a sub-second
26
- * JSON read/merge/write on a latency-critical path (`augment` runs on every
27
- * editor tool call), and running unlocked is merely the pre-lock status quo. A
28
- * group sync is the opposite on every axis — it is long, expensive, operator-
29
- * initiated, and its lost update destroys contracts rather than a registry field.
24
+ * WHY IT FAILS CLOSED, like the registry lock. `withRegistryLock` also
25
+ * refuses to continue unlocked on timeout: a lost registry update can drop a
26
+ * concurrent registration. A group sync still fails closed for additional
27
+ * reasons — it is long, expensive, operator-initiated, and a lost update
28
+ * destroys contracts rather than a registry field.
30
29
  * A sync that cannot be protected must not run at all, and there are three
31
30
  * distinct ways it can fail to be protected; all three throw
32
31
  * {@link GroupSyncLockError}:
@@ -1,3 +1,40 @@
1
- import type { CrossLink, StoredContract } from './types.js';
1
+ import type { CrossLink, CrossLinkEndpoint, StoredContract } from './types.js';
2
+ /**
3
+ * True when a link endpoint carries no resolved graph symbol — empty
4
+ * `symbolUid` or a missing/empty `symbolRef`.
5
+ *
6
+ * Sync marks a cross-link `degraded: true` when this holds for the PROVIDER
7
+ * endpoint (`to`): the contract boundary is proven, but the empty uid can
8
+ * never match a Phase-1 impact symbol id, so cross-repo fan-out across the
9
+ * link silently yields nothing (the classic case is a provider whose handler
10
+ * failed to resolve, leaving `symbolName` degraded to the file name with one
11
+ * pseudo-symbol carrying every route in that file). Consumer-side (`from`)
12
+ * emptiness is deliberately NOT degraded — several extractors (topics, grpc)
13
+ * legitimately emit consumer contracts without a per-call symbol, and the
14
+ * anchor that matters for far-side fan-out is the provider's.
15
+ *
16
+ * Kept next to the endpoint merge logic because `dedupeCrossLinks` must
17
+ * re-derive the flag after a merge: `mergeEndpoints` backfills `symbolUid`
18
+ * from the losing twin, which can invalidate a flag carried in from the winner.
19
+ *
20
+ * NOT unresolved: a deterministic `manifest::<repo>::<contractId>` synthetic
21
+ * uid (see `manifestSymbolUid`). Manifest endpoints fall back to it precisely
22
+ * when the graph has no symbol for them — its empty `symbolRef.filePath` would
23
+ * otherwise trip the check below — yet cross-impact anchors those links by
24
+ * design (#2722: the crossing is preserved with `fanout_status:
25
+ * 'not_attempted'` instead of silently yielding cross=0). The prefix is the
26
+ * canonical discriminator — real indexer uids never start with `manifest::`
27
+ * — and `cross-impact.ts` branches on the same test. Encoding the exemption
28
+ * HERE (not at the sync marking call site) keeps marking and the post-merge
29
+ * re-derivation from drifting apart, and keeps the flag's meaning exactly what
30
+ * `types.ts` documents: "distinct from manifest::… synthetic UIDs".
31
+ */
32
+ export declare function isUnresolvedEndpoint(endpoint: CrossLinkEndpoint): boolean;
33
+ /**
34
+ * Derive `degraded` from the provider endpoint. Present (`true`) only when
35
+ * unresolved; deleted otherwise so contracts.json stays "carried only when
36
+ * meaningful" (`'degraded' in link === false` for anchored links).
37
+ */
38
+ export declare function applyDegradedFlag(link: CrossLink): CrossLink;
2
39
  export declare function dedupeContracts(items: StoredContract[]): StoredContract[];
3
40
  export declare function dedupeCrossLinks(items: CrossLink[]): CrossLink[];
@@ -83,6 +83,59 @@ function crossLinkKey(link) {
83
83
  endpointKey(link.to),
84
84
  ].join('\0');
85
85
  }
86
+ /**
87
+ * True when a link endpoint carries no resolved graph symbol — empty
88
+ * `symbolUid` or a missing/empty `symbolRef`.
89
+ *
90
+ * Sync marks a cross-link `degraded: true` when this holds for the PROVIDER
91
+ * endpoint (`to`): the contract boundary is proven, but the empty uid can
92
+ * never match a Phase-1 impact symbol id, so cross-repo fan-out across the
93
+ * link silently yields nothing (the classic case is a provider whose handler
94
+ * failed to resolve, leaving `symbolName` degraded to the file name with one
95
+ * pseudo-symbol carrying every route in that file). Consumer-side (`from`)
96
+ * emptiness is deliberately NOT degraded — several extractors (topics, grpc)
97
+ * legitimately emit consumer contracts without a per-call symbol, and the
98
+ * anchor that matters for far-side fan-out is the provider's.
99
+ *
100
+ * Kept next to the endpoint merge logic because `dedupeCrossLinks` must
101
+ * re-derive the flag after a merge: `mergeEndpoints` backfills `symbolUid`
102
+ * from the losing twin, which can invalidate a flag carried in from the winner.
103
+ *
104
+ * NOT unresolved: a deterministic `manifest::<repo>::<contractId>` synthetic
105
+ * uid (see `manifestSymbolUid`). Manifest endpoints fall back to it precisely
106
+ * when the graph has no symbol for them — its empty `symbolRef.filePath` would
107
+ * otherwise trip the check below — yet cross-impact anchors those links by
108
+ * design (#2722: the crossing is preserved with `fanout_status:
109
+ * 'not_attempted'` instead of silently yielding cross=0). The prefix is the
110
+ * canonical discriminator — real indexer uids never start with `manifest::`
111
+ * — and `cross-impact.ts` branches on the same test. Encoding the exemption
112
+ * HERE (not at the sync marking call site) keeps marking and the post-merge
113
+ * re-derivation from drifting apart, and keeps the flag's meaning exactly what
114
+ * `types.ts` documents: "distinct from manifest::… synthetic UIDs".
115
+ */
116
+ export function isUnresolvedEndpoint(endpoint) {
117
+ if (endpoint.symbolUid.startsWith('manifest::'))
118
+ return false;
119
+ return (!endpoint.symbolUid ||
120
+ !endpoint.symbolRef ||
121
+ !endpoint.symbolRef.filePath ||
122
+ !endpoint.symbolRef.name);
123
+ }
124
+ /**
125
+ * Derive `degraded` from the provider endpoint. Present (`true`) only when
126
+ * unresolved; deleted otherwise so contracts.json stays "carried only when
127
+ * meaningful" (`'degraded' in link === false` for anchored links).
128
+ */
129
+ export function applyDegradedFlag(link) {
130
+ const next = { ...link };
131
+ if (isUnresolvedEndpoint(next.to)) {
132
+ next.degraded = true;
133
+ }
134
+ else {
135
+ delete next.degraded;
136
+ }
137
+ return next;
138
+ }
86
139
  export function dedupeContracts(items) {
87
140
  const deduped = new Map();
88
141
  for (const contract of items) {
@@ -104,12 +157,15 @@ export function dedupeCrossLinks(items) {
104
157
  const keepIncoming = link.confidence > existing.confidence;
105
158
  const primary = keepIncoming ? link : existing;
106
159
  const secondary = keepIncoming ? existing : link;
107
- deduped.set(key, {
160
+ const merged = {
108
161
  ...primary,
109
162
  confidence: Math.max(existing.confidence, link.confidence),
110
163
  from: mergeEndpoints(primary.from, secondary.from),
111
164
  to: mergeEndpoints(primary.to, secondary.to),
112
- });
165
+ };
166
+ // Re-derive after mergeEndpoints: a richer twin can backfill `to.symbolUid`
167
+ // and must not leave a stale `degraded` flag on an now-anchored link.
168
+ deduped.set(key, applyDegradedFlag(merged));
113
169
  }
114
- return [...deduped.values()];
170
+ return [...deduped.values()].map(applyDegradedFlag);
115
171
  }
@@ -15,6 +15,17 @@ export interface GroupToolPort {
15
15
  resolveRepo(repoParam?: string): Promise<GroupRepoHandle>;
16
16
  impact(repo: GroupRepoHandle, params: {
17
17
  target: string;
18
+ /**
19
+ * Target-selector params, same semantics as the single-repo `impact`
20
+ * tool: `target_uid` is the zero-ambiguity lookup (it wins over the
21
+ * name), `file_path`/`kind` narrow a name shared by several symbols
22
+ * (e.g. same-named Api/Impl/Controller layers). The port implementation
23
+ * consumes them directly; the Phase-1 caller in cross-impact.ts is
24
+ * responsible for threading them from the MCP `impact` args.
25
+ */
26
+ target_uid?: string;
27
+ file_path?: string;
28
+ kind?: string;
18
29
  direction: 'upstream' | 'downstream';
19
30
  maxDepth?: number;
20
31
  relationTypes?: string[];
@@ -301,8 +301,9 @@ export class GroupService {
301
301
  // group tools never need it — so deferring it here keeps that closure off
302
302
  // MCP server startup entirely and off every non-sync group call. The CLI
303
303
  // already does exactly this at `cli/group.ts`'s sync command.
304
- const { syncGroup } = await import('./sync.js');
304
+ const { syncGroup, formatGroupSyncAmbiguousError } = await import('./sync.js');
305
305
  const { GroupSyncLockError } = await import('./group-lock.js');
306
+ const { RegistryAmbiguousTargetError } = await import('../../storage/repo-manager.js');
306
307
  let result;
307
308
  try {
308
309
  result = await syncGroup(config, {
@@ -315,6 +316,9 @@ export class GroupService {
315
316
  });
316
317
  }
317
318
  catch (err) {
319
+ if (err instanceof RegistryAmbiguousTargetError) {
320
+ return { error: formatGroupSyncAmbiguousError(err) };
321
+ }
318
322
  // Fails closed (R9): this sync could not be protected against a concurrent
319
323
  // one, so it did not run and wrote nothing. Return it through the same
320
324
  // error channel a missing group uses — NEVER as a success payload of zeroes,
@@ -337,6 +341,14 @@ export class GroupService {
337
341
  // can otherwise see contract counts that disagree with this payload, with
338
342
  // nothing here explaining why the write was skipped.
339
343
  registryOutcome: result.registryOutcome,
344
+ // Data-quality signals surfaced from the sync run: links whose provider
345
+ // endpoint never resolved to a graph symbol, per-repo extraction
346
+ // failures with reasons, and operator warnings (e.g. bridge.lbug write
347
+ // failed after contracts.json was written). Always present so MCP
348
+ // consumers can branch on them without existence checks.
349
+ degradedLinks: result.degradedLinks,
350
+ failedRepos: result.failedRepos,
351
+ warnings: result.warnings,
340
352
  };
341
353
  }
342
354
  async groupContracts(params) {
@@ -1,11 +1,11 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as fsp from 'node:fs/promises';
3
3
  import * as path from 'node:path';
4
- import * as os from 'node:os';
5
4
  import { writeFileAtomic } from '../../storage/fs-atomic.js';
5
+ import { getGlobalDir } from '../../storage/global-dir.js';
6
6
  export const CONTRACTS_FILE = 'contracts.json';
7
7
  export function getDefaultGitnexusDir() {
8
- return process.env.GITNEXUS_HOME || path.join(os.homedir(), '.gitnexus');
8
+ return getGlobalDir();
9
9
  }
10
10
  export function getGroupsBaseDir(gitnexusDir) {
11
11
  return path.join(gitnexusDir || getDefaultGitnexusDir(), 'groups');
@@ -1,4 +1,4 @@
1
- import { type RegistryEntry } from '../../storage/repo-manager.js';
1
+ import { RegistryAmbiguousTargetError, type RegistryEntry } from '../../storage/repo-manager.js';
2
2
  import type { GroupConfig, RepoHandle, RepoSnapshot, StoredContract, CrossLink, GroupManifestLink, MatchType } from './types.js';
3
3
  export interface SyncOptions {
4
4
  extractorOverride?: ((repo: RepoHandle) => Promise<StoredContract[]>) | (() => Promise<StoredContract[]>);
@@ -47,6 +47,27 @@ export interface SyncResult {
47
47
  * none of that repo's contracts are in `contracts`.
48
48
  */
49
49
  unreadableRepos: string[];
50
+ /**
51
+ * Cross-links whose provider endpoint has no resolved graph symbol
52
+ * (`degraded: true` on the link — see `isUnresolvedEndpoint`). The boundary
53
+ * is proven but cross-impact fan-out cannot anchor it; the usual remedy is
54
+ * re-analyzing the provider repo so its handlers resolve.
55
+ */
56
+ degradedLinks: number;
57
+ /**
58
+ * Repos whose per-repo extraction threw (init, an extractor, or the
59
+ * snapshot read). Each still lands in `unreadableRepos` (group path) —
60
+ * unchanged downstream semantics — but carries its failure reason here: the
61
+ * catch used to swallow the exception, leaving contracts already pushed by
62
+ * earlier extractors in this iteration as silent half-repo data. `repo` is
63
+ * that same group path (e.g. `app/backend`), not the registry display name.
64
+ */
65
+ failedRepos: Array<{
66
+ repo: string;
67
+ reason: string;
68
+ }>;
69
+ /** Operator-facing run warnings (e.g. bridge.lbug write failed after contracts.json was written). */
70
+ warnings: string[];
50
71
  repoSnapshots: Record<string, RepoSnapshot>;
51
72
  /**
52
73
  * Matching stages this run was asked to skip. Populated on EVERY outcome,
@@ -64,6 +85,8 @@ export interface SyncResult {
64
85
  registryOutcome: RegistryWriteOutcome;
65
86
  }
66
87
  export declare function stableRepoPoolId(entry: RegistryEntry, allEntries: RegistryEntry[]): string;
88
+ /** Operator copy for group sync — unique `--name`, not a path in yaml. */
89
+ export declare function formatGroupSyncAmbiguousError(err: RegistryAmbiguousTargetError): string;
67
90
  /** A batch of manifest links whose referenced in-group repos fit one resident window. */
68
91
  export interface ManifestWindow {
69
92
  links: GroupManifestLink[];