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
@@ -440,6 +440,724 @@ export async function loadSwiftPackageConfig(repoRoot) {
440
440
  }
441
441
  return null;
442
442
  }
443
+ /**
444
+ * Load the Zig build configuration a repo's `build.zig.zon` + root `build.zig`
445
+ * declare: `.path` deps (and the roots their own build.zig names) from the
446
+ * zon, and the repo's own named modules from the root build.zig. Either file
447
+ * may be missing — a repo with a `build.zig` but no `build.zig.zon` still
448
+ * resolves `@import("<own module>")`. Null only when neither contributes.
449
+ *
450
+ * `build.zig.zon` is Zig source (an anonymous-struct literal), not JSON.
451
+ * Rather than pull in a tree-sitter parse for one file, we use a small
452
+ * regex-based extractor that handles the common shapes:
453
+ *
454
+ * .dependencies = .{
455
+ * .ziggit_pkg = .{
456
+ * .url = "https://...",
457
+ * .hash = "1220...",
458
+ * },
459
+ * .local_dep = .{
460
+ * .path = "../local_dep",
461
+ * },
462
+ * },
463
+ *
464
+ * Limitations (intentional — bail to null on anything weirder):
465
+ * - Only the top-level `.dependencies = .{ ... }` block is parsed (brace
466
+ * depth 1); a same-named field nested in another struct is ignored.
467
+ * - Each dep entry is matched by a single shape: `.<name> = .{ ... }`
468
+ * where `<name>` is a bare identifier (no `@"…"` quoted form).
469
+ * - Only `.path = "..."` is captured. `.url` deps are left unresolved
470
+ * because their unpacked location lives outside the repo
471
+ * (.zig-cache/p/<hash>/ or ~/.cache/zig/p/<hash>/) and is therefore
472
+ * not in our `allFilePaths` set.
473
+ * - `//` line comments are stripped before scanning (string-aware, so a
474
+ * `//` inside `.url = "https://…"` survives), and brace matching skips
475
+ * string literals — a commented-out `.path` or a `}` inside a comment
476
+ * or string cannot declare a dep or truncate the block.
477
+ */
478
+ export async function loadZigBuildConfig(repoRoot) {
479
+ let config = null;
480
+ try {
481
+ const raw = await fs.readFile(path.join(repoRoot, 'build.zig.zon'), 'utf-8');
482
+ config = parseZigBuildZon(raw);
483
+ }
484
+ catch {
485
+ // No zon (or unreadable): the root build.zig may still declare modules.
486
+ }
487
+ // The repo's own importable modules, from its root build.zig. Independent
488
+ // of the zon: `@import("<own module>")` is how single-package repos refer
489
+ // to their root file from every other file.
490
+ let rootModules;
491
+ let rootBuildZig = null;
492
+ try {
493
+ rootBuildZig = await fs.readFile(path.join(repoRoot, 'build.zig'), 'utf-8');
494
+ const parsed = parseZigRootModules(rootBuildZig);
495
+ if (parsed.size > 0)
496
+ rootModules = parsed;
497
+ }
498
+ catch {
499
+ // No root build.zig — nothing to declare.
500
+ }
501
+ if (config === null) {
502
+ if (rootBuildZig === null)
503
+ return null;
504
+ // No zon: no path deps, so `dep.module(…)` operands resolve to nothing.
505
+ const buildModules = parseZigBuildModules(rootBuildZig);
506
+ if (!rootModules && buildModules.length === 0)
507
+ return null;
508
+ return {
509
+ pathDeps: new Map(),
510
+ ...(rootModules ? { rootModules } : {}),
511
+ ...(buildModules.length > 0 ? { buildModules } : {}),
512
+ };
513
+ }
514
+ // A path dep's importable root is whatever ITS build.zig declares, not a
515
+ // fixed layout: read `root_source_file` per `addModule` and remember it
516
+ // repo-relative. Best effort — an unreadable build.zig just leaves the
517
+ // conventional-layout fallback in place.
518
+ const moduleRoots = new Map();
519
+ // Per path dep: the modules its build.zig NAMES (`addModule("core", …)`),
520
+ // repo-relative — what a root-build.zig `dep.module("core")` operand means.
521
+ const depModules = new Map();
522
+ for (const [depName, depPath] of config.pathDeps) {
523
+ const rel = normalizeZigDepPath(depPath);
524
+ if (rel === null)
525
+ continue;
526
+ let buildZig;
527
+ try {
528
+ buildZig = await fs.readFile(path.join(repoRoot, rel, 'build.zig'), 'utf-8');
529
+ }
530
+ catch {
531
+ continue;
532
+ }
533
+ const prefixed = (r) => (rel === '' ? r : `${rel}/${r}`);
534
+ const roots = parseZigBuildModuleRoots(buildZig, depName).map(prefixed);
535
+ if (roots.length > 0)
536
+ moduleRoots.set(depName, roots);
537
+ const named = new Map();
538
+ for (const mod of parseZigBuildModules(buildZig)) {
539
+ if (mod.name !== undefined && !named.has(mod.name))
540
+ named.set(mod.name, prefixed(mod.root));
541
+ }
542
+ if (named.size > 0)
543
+ depModules.set(depName, named);
544
+ }
545
+ const buildModules = rootBuildZig === null ? [] : parseZigBuildModules(rootBuildZig, depModules);
546
+ return {
547
+ ...config,
548
+ ...(moduleRoots.size > 0 ? { moduleRoots } : {}),
549
+ ...(rootModules ? { rootModules } : {}),
550
+ ...(buildModules.length > 0 ? { buildModules } : {}),
551
+ };
552
+ }
553
+ /**
554
+ * Normalize a `.path` value from build.zig.zon into a repo-relative form.
555
+ * Returns null for paths that escape the repo root (start with `..`) or
556
+ * are absolute — those point to files we don't index. `.` / `./` normalize
557
+ * to the empty string (the repo root itself). Shared with the import
558
+ * resolver so both sides agree on which deps are in-repo.
559
+ */
560
+ export function normalizeZigDepPath(depPath) {
561
+ // Normalize separators BEFORE the absolute check so every Windows spelling
562
+ // is visible to it: POSIX (`/x`), drive (`C:\x`, `C:/x`), root-relative
563
+ // (`\x` → `/x`) and UNC (`\\server\share` → `//server/share`) paths all
564
+ // point outside the repository.
565
+ const normalized = depPath.replace(/\\/g, '/');
566
+ if (normalized.startsWith('/') || /^[A-Za-z]:\//.test(normalized))
567
+ return null;
568
+ const parts = [];
569
+ for (const part of normalized.split('/')) {
570
+ if (part === '' || part === '.')
571
+ continue;
572
+ if (part === '..') {
573
+ if (parts.length === 0)
574
+ return null;
575
+ parts.pop();
576
+ }
577
+ else {
578
+ parts.push(part);
579
+ }
580
+ }
581
+ return parts.join('/');
582
+ }
583
+ /**
584
+ * The `root_source_file` paths a `build.zig` declares, dep-relative, with the
585
+ * module whose `addModule("<name>", …)` name equals `preferredName` first.
586
+ *
587
+ * Reads two shapes, which between them cover `zig init` output and the
588
+ * common hand-written build scripts:
589
+ * - `b.addModule("name", .{ .root_source_file = b.path("src/root.zig") })`
590
+ * - any other `.root_source_file = b.path("…")` (exe/lib/test artifacts),
591
+ * kept as unnamed fallbacks in file order.
592
+ * A `.zig` under `b.path` is required — `.{ .cwd_relative = … }` and
593
+ * `LazyPath` values computed at build time are not resolvable statically and
594
+ * are skipped. Duplicates collapse to the first occurrence.
595
+ */
596
+ export function parseZigBuildModuleRoots(buildZig, preferredName) {
597
+ const named = [];
598
+ const unnamed = [];
599
+ const seen = new Set();
600
+ const add = (into, p) => {
601
+ const norm = normalizeZigDepPath(p);
602
+ if (norm === null || norm === '' || !norm.endsWith('.zig') || seen.has(norm))
603
+ return;
604
+ seen.add(norm);
605
+ into.push(norm);
606
+ };
607
+ const rootRe = /\.root_source_file\s*=\s*b\.path\(\s*"([^"\n]+)"\s*\)/;
608
+ // The named module: scan the whole `addModule(…)` argument list, balanced
609
+ // on parentheses, so a nested field before `.root_source_file` (`.imports =
610
+ // &.{ .{ … } }`) does not end the match early — a `[^}]*` regex stopped at
611
+ // that inner `}` and silently demoted the module to an unnamed fallback.
612
+ const text = stripZonComments(buildZig);
613
+ const mask = zonStringMask(text);
614
+ const callRe = /\baddModule\s*\(/g;
615
+ let m;
616
+ while ((m = callRe.exec(text)) !== null) {
617
+ if (mask[m.index] !== 0)
618
+ continue;
619
+ const argsStart = m.index + m[0].length;
620
+ const argsEnd = findZigParenEnd(text, argsStart);
621
+ if (argsEnd < 0)
622
+ break;
623
+ const args = text.slice(argsStart, argsEnd);
624
+ const nameMatch = /^\s*"([^"\n]+)"\s*,/.exec(args);
625
+ if (nameMatch?.[1] !== preferredName)
626
+ continue;
627
+ const root = zigTopLevelStaticRoot(args);
628
+ if (root !== null)
629
+ add(named, root);
630
+ }
631
+ const anyRe = new RegExp(rootRe.source, 'g');
632
+ while ((m = anyRe.exec(text)) !== null)
633
+ add(unnamed, m[1]);
634
+ return [...named, ...unnamed];
635
+ }
636
+ /**
637
+ * The importable modules a repo's ROOT `build.zig` declares, module name →
638
+ * repo-relative root source file. Static scan (no execution) of two shapes:
639
+ *
640
+ * - `b.addModule("<name>", .{ .root_source_file = b.path("<p>.zig"), … })`
641
+ * names the module directly;
642
+ * - `const m = b.createModule(.{ .root_source_file = b.path("<p>.zig"), … })`
643
+ * (or `const m = b.addModule(…)`) bound to an identifier and later named
644
+ * by `x.addImport("<name>", m)` or `.imports = &.{ .{ .name = "<name>",
645
+ * .module = m } }`.
646
+ *
647
+ * Deliberately NOT resolved — they are not in-repo source files: modules whose
648
+ * root is not a static `b.path("….zig")` (generated `opts.createModule()` from
649
+ * `addOptions`, `translate_c.createModule()`, `.cwd_relative` / computed
650
+ * LazyPaths), `addImport("<name>", dep.module("…"))` (a `.url` / path dep,
651
+ * handled through the zon), and aliases whose module operand is anything but a
652
+ * bare identifier bound above (`config.lp_module`). Comments are stripped and
653
+ * string literals skipped; the first declaration of a name wins.
654
+ */
655
+ export function parseZigRootModules(buildZig) {
656
+ const text = stripZonComments(buildZig);
657
+ const mask = zonStringMask(text);
658
+ const modules = new Map();
659
+ // identifier → repo-relative root, for `const m = b.createModule(…)` /
660
+ // `const m = b.addModule(…)` bindings later named via addImport.
661
+ const bindings = new Map();
662
+ const callRe = /\b(addModule|createModule)\s*\(/g;
663
+ let m;
664
+ while ((m = callRe.exec(text)) !== null) {
665
+ if (mask[m.index] !== 0)
666
+ continue;
667
+ const argsStart = m.index + m[0].length;
668
+ const argsEnd = findZigParenEnd(text, argsStart);
669
+ if (argsEnd < 0)
670
+ break;
671
+ const args = text.slice(argsStart, argsEnd);
672
+ const root = zigTopLevelStaticRoot(args);
673
+ if (root === null)
674
+ continue;
675
+ if (m[1] === 'addModule') {
676
+ const nameMatch = /^\s*"([^"\n]+)"\s*,/.exec(args);
677
+ if (nameMatch && !modules.has(nameMatch[1]))
678
+ modules.set(nameMatch[1], root);
679
+ }
680
+ const binding = ZIG_MODULE_BINDING_RE.exec(text.slice(0, m.index));
681
+ if (binding && !bindings.has(binding[1]))
682
+ bindings.set(binding[1], root);
683
+ }
684
+ if (bindings.size === 0)
685
+ return modules;
686
+ const aliasRes = [
687
+ /\.addImport\(\s*"([^"\n]+)"\s*,\s*([A-Za-z_]\w*)\s*\)/g,
688
+ /\.name\s*=\s*"([^"\n]+)"\s*,\s*\.module\s*=\s*([A-Za-z_]\w*)\s*[,}]/g,
689
+ ];
690
+ for (const re of aliasRes) {
691
+ while ((m = re.exec(text)) !== null) {
692
+ if (mask[m.index] !== 0)
693
+ continue;
694
+ const root = bindings.get(m[2]);
695
+ if (root !== undefined && !modules.has(m[1]))
696
+ modules.set(m[1], root);
697
+ }
698
+ }
699
+ return modules;
700
+ }
701
+ /**
702
+ * Every build module the ROOT `build.zig` declares, each with its OWN import
703
+ * table (`ZigBuildModule`). Static scan (no execution) of:
704
+ *
705
+ * - `b.addModule("<name>", .{ .root_source_file = b.path("<p>.zig"), … })`
706
+ * and `const m = b.createModule(.{ .root_source_file = … })` — a module,
707
+ * bound to the identifier a preceding `const m =` names;
708
+ * - `b.addExecutable` / `addLibrary` / `addStaticLibrary` /
709
+ * `addSharedLibrary` / `addTest` / `addObject(.{ .root_source_file =
710
+ * b.path("<p>.zig"), … })` — an artifact whose ROOT MODULE is a module of
711
+ * its own (reached as `exe.root_module.addImport(…)`), or `.root_module =
712
+ * m` / `.root_module = b.createModule(…)` naming one declared inline;
713
+ * - `<m>.addImport("<alias>", <operand>)`, `<exe>.root_module.addImport(…)`
714
+ * and the `.imports = &.{ .{ .name = "<alias>", .module = <operand> } }`
715
+ * field of a module's own arguments — an entry in THAT module's table.
716
+ * The operand is a module binding (`m`) or a path dep's named module,
717
+ * `dep.module("<name>")` with `const dep = b.dependency("<zon name>", …)`,
718
+ * looked up in `depModules` (zon dep name → module name → repo-relative
719
+ * root, from the dep's own build.zig).
720
+ *
721
+ * Why per module rather than one map (`parseZigRootModules`): an alias is
722
+ * scoped to the module that declares it. Two executables that each
723
+ * `addImport("config", …)` their own `config.zig` are the ordinary
724
+ * multi-target layout, and a single first-wins map sent the second module's
725
+ * `@import("config")` to the first module's file — a confident wrong
726
+ * `IMPORTS` edge and every `config.*` call behind it. Deliberately NOT
727
+ * resolved, as in `parseZigRootModules`: generated roots
728
+ * (`addOptions().createModule()`, `translate_c.createModule()`, computed
729
+ * LazyPaths), `.url` deps, and operands that are not a bare identifier or a
730
+ * `dep.module("…")` on a `b.dependency` binding. Comments stripped, string
731
+ * literals masked; the first binding of an identifier wins.
732
+ */
733
+ export function parseZigBuildModules(buildZig, depModules) {
734
+ const text = stripZonComments(buildZig);
735
+ const mask = zonStringMask(text);
736
+ const drafts = [];
737
+ const bindings = new Map(); // identifier → drafts index
738
+ const bind = (prefixEnd, idx) => {
739
+ const binding = ZIG_MODULE_BINDING_RE.exec(text.slice(0, prefixEnd));
740
+ if (binding && !bindings.has(binding[1]))
741
+ bindings.set(binding[1], idx);
742
+ };
743
+ // Artifact bindings whose `.root_module = <ident>` names a module declared
744
+ // by another call; resolved once every binding is known.
745
+ const pendingArtifactAliases = [];
746
+ const callRe = /\b(addModule|createModule|addExecutable|addLibrary|addStaticLibrary|addSharedLibrary|addTest|addObject)\s*\(/g;
747
+ let m;
748
+ while ((m = callRe.exec(text)) !== null) {
749
+ if (mask[m.index] !== 0)
750
+ continue;
751
+ const argsStart = m.index + m[0].length;
752
+ const argsEnd = findZigParenEnd(text, argsStart);
753
+ if (argsEnd < 0)
754
+ break;
755
+ const args = text.slice(argsStart, argsEnd);
756
+ const kind = m[1];
757
+ if (kind === 'addModule' || kind === 'createModule') {
758
+ const root = zigTopLevelStaticRoot(args);
759
+ if (root === null)
760
+ continue;
761
+ const nameMatch = kind === 'addModule' ? /^\s*"([^"\n]+)"\s*,/.exec(args) : null;
762
+ drafts.push({
763
+ ...(nameMatch ? { name: nameMatch[1] } : {}),
764
+ root,
765
+ at: m.index,
766
+ argsStart,
767
+ argsEnd,
768
+ imports: new Map(),
769
+ });
770
+ bind(m.index, drafts.length - 1);
771
+ continue;
772
+ }
773
+ // An artifact. Its root module is either declared inline by
774
+ // `.root_source_file`, or handed over through `.root_module = …`.
775
+ const rootModule = /\.root_module\s*=\s*((?:[A-Za-z_]\w*\.)*)([A-Za-z_]\w*)\s*(\()?/.exec(args);
776
+ if (rootModule) {
777
+ if (rootModule[3] === '(' && rootModule[2] === 'createModule') {
778
+ // Inline `.root_module = b.createModule(.{ … })`: the module is minted
779
+ // by the createModule call inside these args (a later iteration of
780
+ // this loop); remember the artifact's binding for it.
781
+ const nameOffset = rootModule.index + rootModule[0].lastIndexOf('createModule');
782
+ const binding = ZIG_MODULE_BINDING_RE.exec(text.slice(0, m.index));
783
+ if (binding) {
784
+ pendingArtifactAliases.push({
785
+ ident: binding[1],
786
+ module: `@${argsStart + nameOffset}`,
787
+ });
788
+ }
789
+ }
790
+ else if (rootModule[1] === '' && rootModule[3] === undefined) {
791
+ const binding = ZIG_MODULE_BINDING_RE.exec(text.slice(0, m.index));
792
+ if (binding)
793
+ pendingArtifactAliases.push({ ident: binding[1], module: rootModule[2] });
794
+ }
795
+ continue;
796
+ }
797
+ const root = zigTopLevelStaticRoot(args);
798
+ if (root === null)
799
+ continue;
800
+ drafts.push({ root, at: m.index, argsStart, argsEnd, imports: new Map() });
801
+ bind(m.index, drafts.length - 1);
802
+ }
803
+ for (const alias of pendingArtifactAliases) {
804
+ if (bindings.has(alias.ident))
805
+ continue;
806
+ const idx = alias.module.startsWith('@')
807
+ ? drafts.findIndex((d) => d.at === Number(alias.module.slice(1)))
808
+ : (bindings.get(alias.module) ?? -1);
809
+ if (idx >= 0)
810
+ bindings.set(alias.ident, idx);
811
+ }
812
+ if (drafts.length === 0)
813
+ return [];
814
+ // `const dep = b.dependency("<zon name>", …)` bindings, for `dep.module("…")`.
815
+ const dependencyBindings = new Map();
816
+ const depRe = /(?:const|var)\s+([A-Za-z_]\w*)\s*=\s*(?:[A-Za-z_]\w*\.)*dependency\(\s*"([^"\n]+)"/g;
817
+ while ((m = depRe.exec(text)) !== null) {
818
+ if (mask[m.index] !== 0)
819
+ continue;
820
+ if (!dependencyBindings.has(m[1]))
821
+ dependencyBindings.set(m[1], m[2]);
822
+ }
823
+ // An import operand → the repo-relative root it names, or null.
824
+ const operandRoot = (operand) => {
825
+ const bare = /^([A-Za-z_]\w*)$/.exec(operand);
826
+ if (bare) {
827
+ const idx = bindings.get(bare[1]);
828
+ return idx === undefined ? null : drafts[idx].root;
829
+ }
830
+ const viaDep = /^([A-Za-z_]\w*)\.module\(\s*"([^"\n]+)"\s*\)$/.exec(operand);
831
+ if (viaDep) {
832
+ const zonName = dependencyBindings.get(viaDep[1]);
833
+ return zonName === undefined ? null : (depModules?.get(zonName)?.get(viaDep[2]) ?? null);
834
+ }
835
+ return null;
836
+ };
837
+ const addImport = (idx, alias, operand) => {
838
+ const root = operandRoot(operand.trim());
839
+ const table = drafts[idx].imports;
840
+ if (root !== null && !table.has(alias))
841
+ table.set(alias, root);
842
+ };
843
+ // Pass 2a — `<m>.addImport("<alias>", <operand>)` / `<exe>.root_module.addImport(…)`.
844
+ const addImportRe = /\b([A-Za-z_]\w*)(?:\.root_module)?\.addImport\s*\(/g;
845
+ while ((m = addImportRe.exec(text)) !== null) {
846
+ if (mask[m.index] !== 0)
847
+ continue;
848
+ const idx = bindings.get(m[1]);
849
+ if (idx === undefined)
850
+ continue;
851
+ const argsStart = m.index + m[0].length;
852
+ const argsEnd = findZigParenEnd(text, argsStart);
853
+ if (argsEnd < 0)
854
+ break;
855
+ const args = text.slice(argsStart, argsEnd);
856
+ const aliasMatch = /^\s*"([^"\n]+)"\s*,/.exec(args);
857
+ if (!aliasMatch)
858
+ continue;
859
+ addImport(idx, aliasMatch[1], args.slice(aliasMatch[0].length));
860
+ }
861
+ // Pass 2b — `.imports = &.{ .{ .name = "<alias>", .module = <operand> }, … }`
862
+ // inside a module's own argument list. The operand runs to the next `,` or
863
+ // `}` at paren depth 0 (`dep.module("core")` carries parentheses).
864
+ const entryRe = /\.name\s*=\s*"([^"\n]+)"\s*,\s*\.module\s*=\s*/g;
865
+ drafts.forEach((draft, idx) => {
866
+ const args = text.slice(draft.argsStart, draft.argsEnd);
867
+ let e;
868
+ while ((e = entryRe.exec(args)) !== null) {
869
+ if (mask[draft.argsStart + e.index] !== 0)
870
+ continue;
871
+ let depth = 0;
872
+ let end = e.index + e[0].length;
873
+ for (; end < args.length; end++) {
874
+ const ch = args[end];
875
+ if (ch === '(')
876
+ depth++;
877
+ else if (ch === ')') {
878
+ if (depth === 0)
879
+ break;
880
+ depth--;
881
+ }
882
+ else if (depth === 0 && (ch === ',' || ch === '}'))
883
+ break;
884
+ }
885
+ addImport(idx, e[1], args.slice(e.index + e[0].length, end));
886
+ }
887
+ });
888
+ return drafts.map(({ name, root, imports }) => ({
889
+ ...(name !== undefined ? { name } : {}),
890
+ root,
891
+ imports,
892
+ }));
893
+ }
894
+ /** First `.root_source_file = b.path("….zig")` at the TOP level of a
895
+ * module-options `.{ … }` — not a nested `.imports = &.{ .{ … } }` entry. */
896
+ function zigTopLevelStaticRoot(args) {
897
+ const mask = zonStringMask(args);
898
+ let structAt = -1;
899
+ for (let i = 0; i < args.length - 1; i++) {
900
+ if (mask[i] !== 0)
901
+ continue;
902
+ if (args[i] === '.' && args[i + 1] === '{') {
903
+ structAt = i;
904
+ break;
905
+ }
906
+ }
907
+ if (structAt < 0)
908
+ return null;
909
+ const bodyStart = structAt + 2;
910
+ const bodyEnd = findZonBlockEnd(args, bodyStart);
911
+ if (bodyEnd < 0)
912
+ return null;
913
+ const match = /\.root_source_file\s*=\s*b\.path\(\s*"([^"\n]+)"\s*\)/.exec(zonBlankNestedBlocks(args.slice(bodyStart, bodyEnd)));
914
+ if (match === null)
915
+ return null;
916
+ const root = normalizeZigDepPath(match[1]);
917
+ return root === null || root === '' || !root.endsWith('.zig') ? null : root;
918
+ }
919
+ /** `const m = b.createModule` / `const m = b.addModule` — not `config.createModule`. */
920
+ const ZIG_MODULE_BINDING_RE = /(?:const|var)\s+([A-Za-z_]\w*)\s*=\s*b\.$/;
921
+ /**
922
+ * Index of the `)` matching the `(` that precedes `start`, skipping parens
923
+ * inside `"…"` literals. -1 when unbalanced. Call on comment-stripped text.
924
+ */
925
+ function findZigParenEnd(text, start) {
926
+ let depth = 1;
927
+ let inString = false;
928
+ for (let i = start; i < text.length; i++) {
929
+ const ch = text[i];
930
+ if (inString) {
931
+ if (ch === '\\')
932
+ i++;
933
+ else if (ch === '"')
934
+ inString = false;
935
+ continue;
936
+ }
937
+ if (ch === '"')
938
+ inString = true;
939
+ else if (ch === '(')
940
+ depth++;
941
+ else if (ch === ')' && --depth === 0)
942
+ return i;
943
+ }
944
+ return -1;
945
+ }
946
+ /**
947
+ * Blank out `//` line comments (and `\\` multiline-string-literal lines) in
948
+ * ZON source, string-aware: a `//` inside a `"…"` literal (`.url =
949
+ * "https://…"`) is content, not a comment. Comment bytes are replaced with
950
+ * spaces so every surviving character keeps its offset.
951
+ */
952
+ function stripZonComments(raw) {
953
+ const out = raw.split('');
954
+ let inString = false;
955
+ for (let i = 0; i < raw.length; i++) {
956
+ const ch = raw[i];
957
+ if (inString) {
958
+ if (ch === '\\')
959
+ i++; // skip the escaped char
960
+ else if (ch === '"')
961
+ inString = false;
962
+ continue;
963
+ }
964
+ if (ch === '"') {
965
+ inString = true;
966
+ continue;
967
+ }
968
+ const isLineComment = ch === '/' && raw[i + 1] === '/';
969
+ const isMultilineLiteral = ch === '\\' &&
970
+ raw[i + 1] === '\\' &&
971
+ /^[ \t]*$/.test(raw.slice(raw.lastIndexOf('\n', i) + 1, i));
972
+ if (isLineComment || isMultilineLiteral) {
973
+ while (i < raw.length && raw[i] !== '\n')
974
+ out[i++] = ' ';
975
+ }
976
+ }
977
+ return out.join('');
978
+ }
979
+ /**
980
+ * Index of the `}` matching the `{` that precedes `start`, skipping braces
981
+ * inside `"…"` literals. -1 when unbalanced. Call on comment-stripped text.
982
+ */
983
+ function findZonBlockEnd(text, start) {
984
+ let depth = 1;
985
+ let inString = false;
986
+ for (let i = start; i < text.length; i++) {
987
+ const ch = text[i];
988
+ if (inString) {
989
+ if (ch === '\\')
990
+ i++;
991
+ else if (ch === '"')
992
+ inString = false;
993
+ continue;
994
+ }
995
+ if (ch === '"')
996
+ inString = true;
997
+ else if (ch === '{')
998
+ depth++;
999
+ else if (ch === '}' && --depth === 0)
1000
+ return i;
1001
+ }
1002
+ return -1;
1003
+ }
1004
+ /**
1005
+ * `body` with every nested `{ … }` block (string-aware) replaced by spaces of
1006
+ * equal length, so a regex over the result only sees the block's DIRECT
1007
+ * fields and offsets still line up with the original text.
1008
+ */
1009
+ function zonBlankNestedBlocks(body) {
1010
+ const out = body.split('');
1011
+ let depth = 0;
1012
+ let inString = false;
1013
+ for (let i = 0; i < body.length; i++) {
1014
+ const ch = body[i];
1015
+ if (inString) {
1016
+ if (ch === '\\') {
1017
+ if (depth > 0 && i + 1 < body.length)
1018
+ out[i + 1] = ' ';
1019
+ i++;
1020
+ }
1021
+ else if (ch === '"')
1022
+ inString = false;
1023
+ if (depth > 0)
1024
+ out[i] = ' ';
1025
+ continue;
1026
+ }
1027
+ if (ch === '"')
1028
+ inString = true;
1029
+ else if (ch === '{')
1030
+ depth++;
1031
+ else if (ch === '}' && depth > 0) {
1032
+ depth--;
1033
+ out[i] = ' ';
1034
+ continue;
1035
+ }
1036
+ if (depth > 0)
1037
+ out[i] = ' ';
1038
+ }
1039
+ return out.join('');
1040
+ }
1041
+ /**
1042
+ * Per-offset "is inside a `"…"` literal" mask for comment-stripped ZON text,
1043
+ * so header regexes can reject a match that merely LOOKS like a field
1044
+ * (`.name = ".dependencies = .{ … }"` is a string, not the dependencies
1045
+ * block). Escaped quotes (`\"`) do not end the literal.
1046
+ */
1047
+ function zonStringMask(text) {
1048
+ const mask = new Uint8Array(text.length);
1049
+ let inString = false;
1050
+ for (let i = 0; i < text.length; i++) {
1051
+ const ch = text[i];
1052
+ if (inString) {
1053
+ mask[i] = 1;
1054
+ if (ch === '\\' && i + 1 < text.length)
1055
+ mask[++i] = 1;
1056
+ else if (ch === '"')
1057
+ inString = false;
1058
+ continue;
1059
+ }
1060
+ if (ch === '"') {
1061
+ inString = true;
1062
+ mask[i] = 1;
1063
+ }
1064
+ }
1065
+ return mask;
1066
+ }
1067
+ /**
1068
+ * Per-offset brace depth for comment-stripped ZON text, string-aware: the
1069
+ * depth AT an offset is the number of unclosed `{` before it. The file's
1070
+ * top-level `.{` puts every direct field at depth 1.
1071
+ */
1072
+ function zonDepthMask(text) {
1073
+ const depth = new Uint8Array(text.length);
1074
+ let d = 0;
1075
+ let inString = false;
1076
+ for (let i = 0; i < text.length; i++) {
1077
+ const ch = text[i];
1078
+ depth[i] = d;
1079
+ if (inString) {
1080
+ if (ch === '\\' && i + 1 < text.length)
1081
+ depth[++i] = d;
1082
+ else if (ch === '"')
1083
+ inString = false;
1084
+ continue;
1085
+ }
1086
+ if (ch === '"')
1087
+ inString = true;
1088
+ else if (ch === '{')
1089
+ d++;
1090
+ else if (ch === '}' && d > 0)
1091
+ d--;
1092
+ }
1093
+ return depth;
1094
+ }
1095
+ /**
1096
+ * First match of a sticky-free global `re` in `text[from, to)` whose start
1097
+ * lies outside a string literal (per `mask`) and, when `depthAt` is given, at
1098
+ * exactly that brace depth (per `depth`). Null when none.
1099
+ */
1100
+ function matchZonHeader(text, re, mask, from, to, depth, depthAt) {
1101
+ re.lastIndex = from;
1102
+ let m;
1103
+ while ((m = re.exec(text)) !== null && m.index < to) {
1104
+ if (mask[m.index] !== 0)
1105
+ continue;
1106
+ if (depth !== undefined && depthAt !== undefined && depth[m.index] !== depthAt)
1107
+ continue;
1108
+ return m;
1109
+ }
1110
+ return null;
1111
+ }
1112
+ /** Pure parser split out for testability. Returns null when no path-deps found. */
1113
+ export function parseZigBuildZon(raw) {
1114
+ const text = stripZonComments(raw);
1115
+ const mask = zonStringMask(text);
1116
+ const depth = zonDepthMask(text);
1117
+ // Locate the `.dependencies = .{ ... }` block. Use brace counting because
1118
+ // dep entries are nested anonymous structs and a naive `}` match would stop
1119
+ // early — and only accept a header outside string literals AND at brace
1120
+ // depth 1 (a direct field of the file's top-level `.{`), so neither a
1121
+ // `.name` value spelling `.dependencies = .{` nor a `.dependencies` field
1122
+ // nested in some earlier anonymous struct can hijack it.
1123
+ const depsHeader = matchZonHeader(text, /\.dependencies\s*=\s*\.\{/g, mask, 0, text.length, depth, 1);
1124
+ if (!depsHeader)
1125
+ return null;
1126
+ const start = depsHeader.index + depsHeader[0].length;
1127
+ const end = findZonBlockEnd(text, start);
1128
+ if (end < 0)
1129
+ return null;
1130
+ const pathDeps = new Map();
1131
+ // Walk each `.<name> = .{ ... }` entry inside [start, end); the body ends
1132
+ // at the matching brace (string-aware), not at the first `}` in the text,
1133
+ // and an entry header inside a string (`.url = "…/.x = .{"`) is not an entry.
1134
+ const entryHeaderRe = /\.([A-Za-z_][A-Za-z0-9_]*)\s*=\s*\.\{/g;
1135
+ let cursor = start;
1136
+ let m;
1137
+ while ((m = matchZonHeader(text, entryHeaderRe, mask, cursor, end)) !== null) {
1138
+ const depName = m[1];
1139
+ const bodyStart = m.index + m[0].length;
1140
+ const bodyEnd = findZonBlockEnd(text, bodyStart);
1141
+ if (bodyEnd < 0 || bodyEnd > end)
1142
+ break;
1143
+ cursor = bodyEnd + 1;
1144
+ // Only a `.path` that is a DIRECT field of the entry counts: a nested
1145
+ // object inside the entry (`.foo = .{ .url = "…", .x = .{ .path = "…" } }`)
1146
+ // must not turn a URL dep into a path dep. Blank nested blocks first and
1147
+ // reject a match that starts inside a string literal.
1148
+ const body = zonBlankNestedBlocks(text.slice(bodyStart, bodyEnd));
1149
+ const pathMatch = matchZonHeader(body, /\.path\s*=\s*"([^"\n]+)"/g, mask.subarray(bodyStart, bodyEnd), 0, body.length);
1150
+ if (pathMatch) {
1151
+ pathDeps.set(depName, pathMatch[1]);
1152
+ }
1153
+ }
1154
+ if (pathDeps.size === 0)
1155
+ return null;
1156
+ if (isDev) {
1157
+ logger.info(`📦 Loaded ${pathDeps.size} Zig path-dep(s) from build.zig.zon`);
1158
+ }
1159
+ return { pathDeps };
1160
+ }
443
1161
  /** Load all language-specific configs once for an ingestion run. */
444
1162
  export async function loadImportConfigs(repoRoot) {
445
1163
  const csharpScan = await scanCSharpProject(repoRoot);
@@ -450,5 +1168,6 @@ export async function loadImportConfigs(repoRoot) {
450
1168
  swiftPackageConfig: await loadSwiftPackageConfig(repoRoot),
451
1169
  csharpConfigs: csharpScan.configs,
452
1170
  csharpNamespaces: csharpScanToEvidence(csharpScan),
1171
+ zigBuildZon: await loadZigBuildConfig(repoRoot),
453
1172
  };
454
1173
  }