@intentius/chant 0.124.46 → 0.124.48

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 (633) hide show
  1. package/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  2. package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  3. package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  4. package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  5. package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  6. package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  7. package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
  8. package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
  9. package/dist/__golden__/wave-loop/op-denied.json +16 -0
  10. package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  11. package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  12. package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
  13. package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
  14. package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
  15. package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  16. package/dist/__golden__/wave-loop/op-held-on.json +16 -0
  17. package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  18. package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  19. package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  20. package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  21. package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
  22. package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  23. package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
  24. package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  25. package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
  26. package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
  27. package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  28. package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  29. package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
  30. package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  31. package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  32. package/dist/__golden__/wave-loop/op-overridden.json +16 -0
  33. package/dist/__golden__/wave-loop/op-per-run.json +20 -0
  34. package/dist/__golden__/wave-loop/op-point.json +13 -0
  35. package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
  36. package/dist/__golden__/wave-loop/op-sealed.json +10 -0
  37. package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
  38. package/dist/__golden__/wave-loop/op-spend.json +10 -0
  39. package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
  40. package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
  41. package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
  42. package/dist/__golden__/wave-loop/op-wide.json +39 -0
  43. package/dist/action-pins.d.ts +61 -0
  44. package/dist/action-pins.d.ts.map +1 -0
  45. package/dist/action-pins.js +77 -0
  46. package/dist/cli/commands/carve.d.ts +3 -0
  47. package/dist/cli/commands/carve.d.ts.map +1 -1
  48. package/dist/cli/commands/carve.js +36 -7
  49. package/dist/cli/commands/import-report.d.ts +26 -0
  50. package/dist/cli/commands/import-report.d.ts.map +1 -0
  51. package/dist/cli/commands/import-report.js +65 -0
  52. package/dist/cli/commands/import.d.ts +11 -1
  53. package/dist/cli/commands/import.d.ts.map +1 -1
  54. package/dist/cli/commands/import.js +22 -3
  55. package/dist/cli/commands/migrate.d.ts +13 -1
  56. package/dist/cli/commands/migrate.d.ts.map +1 -1
  57. package/dist/cli/commands/migrate.js +134 -10
  58. package/dist/cli/handlers/approve.d.ts.map +1 -1
  59. package/dist/cli/handlers/approve.js +21 -2
  60. package/dist/cli/handlers/build.d.ts.map +1 -1
  61. package/dist/cli/handlers/build.js +6 -1
  62. package/dist/cli/handlers/ledger.d.ts +3 -0
  63. package/dist/cli/handlers/ledger.d.ts.map +1 -0
  64. package/dist/cli/handlers/ledger.js +55 -0
  65. package/dist/cli/handlers/migrate.d.ts.map +1 -1
  66. package/dist/cli/handlers/migrate.js +18 -11
  67. package/dist/cli/handlers/misc.d.ts.map +1 -1
  68. package/dist/cli/handlers/misc.js +12 -1
  69. package/dist/cli/handlers/pr-env.js +2 -2
  70. package/dist/cli/handlers/pr.d.ts +15 -1
  71. package/dist/cli/handlers/pr.d.ts.map +1 -1
  72. package/dist/cli/handlers/pr.js +143 -39
  73. package/dist/cli/handlers/query.d.ts +7 -2
  74. package/dist/cli/handlers/query.d.ts.map +1 -1
  75. package/dist/cli/handlers/query.js +16 -4
  76. package/dist/cli/handlers/release.d.ts.map +1 -1
  77. package/dist/cli/handlers/release.js +6 -3
  78. package/dist/cli/handlers/search.d.ts +2 -4
  79. package/dist/cli/handlers/search.d.ts.map +1 -1
  80. package/dist/cli/handlers/search.js +13 -39
  81. package/dist/cli/main.d.ts.map +1 -1
  82. package/dist/cli/main.js +65 -14
  83. package/dist/cli/parse-args.d.ts.map +1 -1
  84. package/dist/cli/parse-args.js +36 -2
  85. package/dist/cli/registry.d.ts +14 -4
  86. package/dist/cli/registry.d.ts.map +1 -1
  87. package/dist/components/builders.d.ts +5 -1
  88. package/dist/components/builders.d.ts.map +1 -1
  89. package/dist/components/builders.js +5 -0
  90. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  91. package/dist/components/capability-plugin-loader.js +16 -1
  92. package/dist/components/capability-plugin.d.ts +14 -0
  93. package/dist/components/capability-plugin.d.ts.map +1 -1
  94. package/dist/components/pr-hooks.d.ts +21 -1
  95. package/dist/components/pr-hooks.d.ts.map +1 -1
  96. package/dist/components/pr-hooks.js +72 -4
  97. package/dist/components/pr-pipeline.d.ts +45 -10
  98. package/dist/components/pr-pipeline.d.ts.map +1 -1
  99. package/dist/components/pr-pipeline.js +47 -14
  100. package/dist/components/pr-policy.d.ts +36 -0
  101. package/dist/components/pr-policy.d.ts.map +1 -1
  102. package/dist/components/pr-policy.js +36 -0
  103. package/dist/components/starter-plugin.d.ts +1 -0
  104. package/dist/components/starter-plugin.d.ts.map +1 -1
  105. package/dist/components/starter-plugin.js +5 -1
  106. package/dist/components/verbs/index.d.ts +2 -0
  107. package/dist/components/verbs/index.d.ts.map +1 -1
  108. package/dist/components/verbs/index.js +2 -0
  109. package/dist/components/verbs/publish-artifact.d.ts +65 -0
  110. package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
  111. package/dist/components/verbs/publish-artifact.js +74 -0
  112. package/dist/components/verbs/publish-image.d.ts +129 -0
  113. package/dist/components/verbs/publish-image.d.ts.map +1 -0
  114. package/dist/components/verbs/publish-image.js +145 -0
  115. package/dist/config-environments.d.ts +20 -0
  116. package/dist/config-environments.d.ts.map +1 -1
  117. package/dist/config-environments.js +12 -0
  118. package/dist/config.d.ts +9 -1
  119. package/dist/config.d.ts.map +1 -1
  120. package/dist/config.js +6 -2
  121. package/dist/gate-decision.d.ts +11 -2
  122. package/dist/gate-decision.d.ts.map +1 -1
  123. package/dist/gate-decision.js +15 -3
  124. package/dist/graph-ir.d.ts +25 -0
  125. package/dist/graph-ir.d.ts.map +1 -1
  126. package/dist/graph-walk.d.ts +66 -0
  127. package/dist/graph-walk.d.ts.map +1 -0
  128. package/dist/graph-walk.js +70 -0
  129. package/dist/import/parser.d.ts +19 -0
  130. package/dist/import/parser.d.ts.map +1 -1
  131. package/dist/lexicon.d.ts +71 -6
  132. package/dist/lexicon.d.ts.map +1 -1
  133. package/dist/lifecycle/gate-ledger.d.ts +11 -0
  134. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  135. package/dist/lifecycle/git.d.ts +2 -5
  136. package/dist/lifecycle/git.d.ts.map +1 -1
  137. package/dist/lifecycle/ledger-read.d.ts +65 -0
  138. package/dist/lifecycle/ledger-read.d.ts.map +1 -0
  139. package/dist/lifecycle/ledger-read.js +160 -0
  140. package/dist/lifecycle/release-workstation.d.ts +7 -0
  141. package/dist/lifecycle/release-workstation.d.ts.map +1 -1
  142. package/dist/lifecycle/release-workstation.js +25 -0
  143. package/dist/lifecycle/run-ledger.d.ts +4 -3
  144. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  145. package/dist/lifecycle/run-ledger.js +1 -0
  146. package/dist/lint/discover.js +3 -1
  147. package/dist/lint/post-synth.d.ts +127 -1
  148. package/dist/lint/post-synth.d.ts.map +1 -1
  149. package/dist/lint/post-synth.js +84 -2
  150. package/dist/lint/rules/op/index.d.ts +1 -0
  151. package/dist/lint/rules/op/index.d.ts.map +1 -1
  152. package/dist/lint/rules/op/index.js +2 -0
  153. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
  154. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
  155. package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
  156. package/dist/op/activities/activity-contracts.d.ts +5 -2
  157. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  158. package/dist/op/activities/activity-contracts.js +5 -2
  159. package/dist/op/activities/index.d.ts +2 -2
  160. package/dist/op/activities/index.d.ts.map +1 -1
  161. package/dist/op/activities/index.js +1 -1
  162. package/dist/op/activities/review-agent.d.ts +90 -4
  163. package/dist/op/activities/review-agent.d.ts.map +1 -1
  164. package/dist/op/activities/review-agent.js +217 -19
  165. package/dist/op/activities/work-evidence.d.ts +8 -1
  166. package/dist/op/activities/work-evidence.d.ts.map +1 -1
  167. package/dist/op/activities/work-evidence.js +1 -0
  168. package/dist/op/builders.d.ts +9 -5
  169. package/dist/op/builders.d.ts.map +1 -1
  170. package/dist/op/builders.js +9 -5
  171. package/dist/op/composites/apply-op.d.ts +29 -2
  172. package/dist/op/composites/apply-op.d.ts.map +1 -1
  173. package/dist/op/composites/apply-op.js +20 -1
  174. package/dist/op/gate-approval.d.ts +11 -5
  175. package/dist/op/gate-approval.d.ts.map +1 -1
  176. package/dist/op/gate-approval.js +11 -6
  177. package/dist/op/gate-quorum.d.ts +100 -3
  178. package/dist/op/gate-quorum.d.ts.map +1 -1
  179. package/dist/op/gate-quorum.js +108 -6
  180. package/dist/op/gate-review.d.ts +9 -0
  181. package/dist/op/gate-review.d.ts.map +1 -1
  182. package/dist/op/gate-review.js +13 -0
  183. package/dist/op/gate.d.ts +44 -3
  184. package/dist/op/gate.d.ts.map +1 -1
  185. package/dist/op/gate.js +25 -4
  186. package/dist/op/index.d.ts +3 -3
  187. package/dist/op/index.d.ts.map +1 -1
  188. package/dist/op/index.js +1 -1
  189. package/dist/op/local-executor.d.ts +38 -3
  190. package/dist/op/local-executor.d.ts.map +1 -1
  191. package/dist/op/local-executor.js +48 -6
  192. package/dist/op/op-waves-run.d.ts +26 -1
  193. package/dist/op/op-waves-run.d.ts.map +1 -1
  194. package/dist/op/op-waves-run.js +259 -13
  195. package/dist/op/op-waves.d.ts +72 -5
  196. package/dist/op/op-waves.d.ts.map +1 -1
  197. package/dist/op/op-waves.js +110 -15
  198. package/dist/op/runtime.d.ts +11 -0
  199. package/dist/op/runtime.d.ts.map +1 -1
  200. package/dist/op/schedule-overdue.d.ts +16 -0
  201. package/dist/op/schedule-overdue.d.ts.map +1 -1
  202. package/dist/op/schedule-overdue.js +36 -0
  203. package/dist/op/stage-hooks.d.ts +9 -2
  204. package/dist/op/stage-hooks.d.ts.map +1 -1
  205. package/dist/op/stage-hooks.js +7 -5
  206. package/dist/op/workspace-run-env.d.ts +22 -0
  207. package/dist/op/workspace-run-env.d.ts.map +1 -0
  208. package/dist/op/workspace-run-env.js +21 -0
  209. package/dist/pr-forge.d.ts +24 -0
  210. package/dist/pr-forge.d.ts.map +1 -1
  211. package/dist/pr-forge.js +47 -0
  212. package/dist/pr-post.d.ts +42 -0
  213. package/dist/pr-post.d.ts.map +1 -1
  214. package/dist/pr-post.js +67 -1
  215. package/dist/read-filter.d.ts +65 -0
  216. package/dist/read-filter.d.ts.map +1 -0
  217. package/dist/read-filter.js +179 -0
  218. package/dist/run-event.d.ts +1 -1
  219. package/dist/run-event.d.ts.map +1 -1
  220. package/dist/terraform/carve.d.ts +24 -3
  221. package/dist/terraform/carve.d.ts.map +1 -1
  222. package/dist/terraform/carve.js +32 -14
  223. package/dist/terraform/cuts.d.ts +97 -0
  224. package/dist/terraform/cuts.d.ts.map +1 -0
  225. package/dist/terraform/cuts.js +138 -0
  226. package/dist/terraform/folds.d.ts +26 -0
  227. package/dist/terraform/folds.d.ts.map +1 -0
  228. package/dist/terraform/folds.js +38 -0
  229. package/dist/terraform/graph.d.ts.map +1 -1
  230. package/dist/terraform/graph.js +10 -0
  231. package/dist/terraform/reach.d.ts +140 -0
  232. package/dist/terraform/reach.d.ts.map +1 -0
  233. package/dist/terraform/reach.js +170 -0
  234. package/dist/terraform/score.d.ts +14 -0
  235. package/dist/terraform/score.d.ts.map +1 -1
  236. package/dist/terraform/score.js +14 -31
  237. package/dist/terraform/state.d.ts.map +1 -1
  238. package/dist/terraform/state.js +4 -2
  239. package/dist/terraform/types.d.ts +8 -0
  240. package/dist/terraform/types.d.ts.map +1 -1
  241. package/dist/wave-blocked.d.ts +10 -1
  242. package/dist/wave-blocked.d.ts.map +1 -1
  243. package/dist/wave-blocked.js +31 -3
  244. package/dist/wave-runtime.mjs +263 -254
  245. package/dist/workspace/check.schema.json +11 -2
  246. package/dist/workspace/checks/ci-branch.d.ts +44 -0
  247. package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
  248. package/dist/workspace/checks/ci-branch.js +133 -0
  249. package/dist/workspace/checks/links.d.ts +3 -0
  250. package/dist/workspace/checks/links.d.ts.map +1 -1
  251. package/dist/workspace/checks/links.js +12 -1
  252. package/dist/workspace/checks/org.d.ts +48 -0
  253. package/dist/workspace/checks/org.d.ts.map +1 -0
  254. package/dist/workspace/checks/org.js +156 -0
  255. package/dist/workspace/checks.d.ts +11 -1
  256. package/dist/workspace/checks.d.ts.map +1 -1
  257. package/dist/workspace/checks.js +59 -7
  258. package/dist/workspace/ci-branches.d.ts +16 -0
  259. package/dist/workspace/ci-branches.d.ts.map +1 -1
  260. package/dist/workspace/ci-branches.js +27 -0
  261. package/dist/workspace/ci-green-cli.js +7 -7
  262. package/dist/workspace/ci-green-workflow.d.ts +1 -1
  263. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  264. package/dist/workspace/ci-green-workflow.js +13 -8
  265. package/dist/workspace/ci-green.d.ts +14 -0
  266. package/dist/workspace/ci-green.d.ts.map +1 -1
  267. package/dist/workspace/ci-green.js +44 -11
  268. package/dist/workspace/ci-run.d.ts +9 -1
  269. package/dist/workspace/ci-run.d.ts.map +1 -1
  270. package/dist/workspace/ci-run.js +67 -6
  271. package/dist/workspace/ci-serve.d.ts +9 -0
  272. package/dist/workspace/ci-serve.d.ts.map +1 -1
  273. package/dist/workspace/ci-serve.js +114 -76
  274. package/dist/workspace/compose-graph.d.ts +14 -0
  275. package/dist/workspace/compose-graph.d.ts.map +1 -1
  276. package/dist/workspace/composites.d.ts +4 -1
  277. package/dist/workspace/composites.d.ts.map +1 -1
  278. package/dist/workspace/composites.js +5 -2
  279. package/dist/workspace/composites.schema.json +22 -0
  280. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  281. package/dist/workspace/cross-root-lint.d.ts +56 -0
  282. package/dist/workspace/cross-root-lint.d.ts.map +1 -0
  283. package/dist/workspace/cross-root-lint.js +111 -0
  284. package/dist/workspace/dbt-models-reader.d.ts +44 -0
  285. package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
  286. package/dist/workspace/dbt-models-reader.js +356 -0
  287. package/dist/workspace/dbt-project-common.d.ts +40 -0
  288. package/dist/workspace/dbt-project-common.d.ts.map +1 -0
  289. package/dist/workspace/dbt-project-common.js +106 -0
  290. package/dist/workspace/dbt-project-reader.d.ts +4 -3
  291. package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
  292. package/dist/workspace/dbt-project-reader.js +14 -108
  293. package/dist/workspace/decision-rank.d.ts +26 -0
  294. package/dist/workspace/decision-rank.d.ts.map +1 -0
  295. package/dist/workspace/decision-rank.js +16 -0
  296. package/dist/workspace/declaration.d.ts +43 -2
  297. package/dist/workspace/declaration.d.ts.map +1 -1
  298. package/dist/workspace/declaration.js +45 -11
  299. package/dist/workspace/declaration.schema.json +133 -24
  300. package/dist/workspace/environments.d.ts +26 -2
  301. package/dist/workspace/environments.d.ts.map +1 -1
  302. package/dist/workspace/environments.js +26 -2
  303. package/dist/workspace/flyway-dir.d.ts +39 -0
  304. package/dist/workspace/flyway-dir.d.ts.map +1 -0
  305. package/dist/workspace/flyway-dir.js +104 -0
  306. package/dist/workspace/flyway-layout.d.ts +96 -0
  307. package/dist/workspace/flyway-layout.d.ts.map +1 -0
  308. package/dist/workspace/flyway-layout.js +308 -0
  309. package/dist/workspace/graph-cli.d.ts.map +1 -1
  310. package/dist/workspace/graph-cli.js +26 -8
  311. package/dist/workspace/graph.schema.json +34 -0
  312. package/dist/workspace/intent.d.ts +2 -3
  313. package/dist/workspace/intent.d.ts.map +1 -1
  314. package/dist/workspace/intent.js +5 -9
  315. package/dist/workspace/kind-link-readers.d.ts +59 -2
  316. package/dist/workspace/kind-link-readers.d.ts.map +1 -1
  317. package/dist/workspace/kind-link-readers.js +17 -1
  318. package/dist/workspace/kinds.d.ts +66 -2
  319. package/dist/workspace/kinds.d.ts.map +1 -1
  320. package/dist/workspace/kinds.js +98 -4
  321. package/dist/workspace/ledger.schema.json +158 -0
  322. package/dist/workspace/lexicon-outputs.d.ts +20 -1
  323. package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
  324. package/dist/workspace/lexicon-outputs.js +102 -10
  325. package/dist/workspace/lineage-check.d.ts +3 -0
  326. package/dist/workspace/lineage-check.d.ts.map +1 -1
  327. package/dist/workspace/lineage-check.js +23 -4
  328. package/dist/workspace/links.d.ts +8 -1
  329. package/dist/workspace/links.d.ts.map +1 -1
  330. package/dist/workspace/links.js +25 -1
  331. package/dist/workspace/ls.d.ts +8 -0
  332. package/dist/workspace/ls.d.ts.map +1 -1
  333. package/dist/workspace/ls.js +7 -1
  334. package/dist/workspace/ls.schema.json +7 -0
  335. package/dist/workspace/member-commands.d.ts.map +1 -1
  336. package/dist/workspace/member-commands.js +54 -5
  337. package/dist/workspace/migrate-links.d.ts +45 -0
  338. package/dist/workspace/migrate-links.d.ts.map +1 -0
  339. package/dist/workspace/migrate-links.js +100 -0
  340. package/dist/workspace/migration-dirs.d.ts +74 -0
  341. package/dist/workspace/migration-dirs.d.ts.map +1 -0
  342. package/dist/workspace/migration-dirs.js +254 -0
  343. package/dist/workspace/reason-codes.d.ts +8 -0
  344. package/dist/workspace/reason-codes.d.ts.map +1 -1
  345. package/dist/workspace/reason-codes.js +11 -0
  346. package/dist/workspace/records-cli.d.ts +11 -0
  347. package/dist/workspace/records-cli.d.ts.map +1 -1
  348. package/dist/workspace/records-cli.js +57 -5
  349. package/dist/workspace/records.schema.json +5 -0
  350. package/dist/workspace/release-candidates.d.ts +2 -0
  351. package/dist/workspace/release-candidates.d.ts.map +1 -1
  352. package/dist/workspace/release-candidates.js +5 -2
  353. package/dist/workspace/release-train.d.ts +53 -0
  354. package/dist/workspace/release-train.d.ts.map +1 -0
  355. package/dist/workspace/release-train.js +134 -0
  356. package/dist/workspace/release-workflow.d.ts.map +1 -1
  357. package/dist/workspace/release-workflow.js +4 -3
  358. package/dist/workspace/repo-ref.d.ts +45 -0
  359. package/dist/workspace/repo-ref.d.ts.map +1 -0
  360. package/dist/workspace/repo-ref.js +114 -0
  361. package/dist/workspace/run-event.schema.json +2 -2
  362. package/dist/workspace/runs-cli.d.ts +9 -0
  363. package/dist/workspace/runs-cli.d.ts.map +1 -1
  364. package/dist/workspace/runs-cli.js +48 -3
  365. package/dist/workspace/runs.schema.json +7 -0
  366. package/dist/workspace/search-contract.d.ts +1 -1
  367. package/dist/workspace/search-contract.d.ts.map +1 -1
  368. package/dist/workspace/status-decisions.d.ts +37 -0
  369. package/dist/workspace/status-decisions.d.ts.map +1 -0
  370. package/dist/workspace/status-decisions.js +147 -0
  371. package/dist/workspace/status-gates.d.ts +9 -0
  372. package/dist/workspace/status-gates.d.ts.map +1 -1
  373. package/dist/workspace/status.d.ts +4 -0
  374. package/dist/workspace/status.d.ts.map +1 -1
  375. package/dist/workspace/status.js +14 -2
  376. package/dist/workspace/status.schema.json +6 -0
  377. package/dist/workspace/work-cli.d.ts.map +1 -1
  378. package/dist/workspace/work-cli.js +5 -3
  379. package/dist/workspace/work-evidence-ops.d.ts +83 -0
  380. package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
  381. package/dist/workspace/work-evidence-ops.js +169 -0
  382. package/dist/workspace/work-evidence.d.ts +12 -2
  383. package/dist/workspace/work-evidence.d.ts.map +1 -1
  384. package/dist/workspace/work-evidence.js +21 -3
  385. package/dist/workspace/work-evidence.schema.json +49 -2
  386. package/dist/workspace/workspace-gates.d.ts +110 -0
  387. package/dist/workspace/workspace-gates.d.ts.map +1 -0
  388. package/dist/workspace/workspace-gates.js +140 -0
  389. package/dist/workspace/workspace-kinds.schema.json +58 -3
  390. package/dist/workspace/workspace-ledger.d.ts +76 -0
  391. package/dist/workspace/workspace-ledger.d.ts.map +1 -0
  392. package/dist/workspace/workspace-ledger.js +91 -0
  393. package/dist/workspace/workspace-run.d.ts +112 -0
  394. package/dist/workspace/workspace-run.d.ts.map +1 -0
  395. package/dist/workspace/workspace-run.js +432 -0
  396. package/package.json +1 -1
  397. package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  398. package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  399. package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  400. package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  401. package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  402. package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  403. package/src/__golden__/wave-loop/op-cost-member.json +13 -0
  404. package/src/__golden__/wave-loop/op-denied-source.json +16 -0
  405. package/src/__golden__/wave-loop/op-denied.json +16 -0
  406. package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  407. package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  408. package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
  409. package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
  410. package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
  411. package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  412. package/src/__golden__/wave-loop/op-held-on.json +16 -0
  413. package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  414. package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  415. package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  416. package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  417. package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
  418. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  419. package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
  420. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  421. package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
  422. package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
  423. package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  424. package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  425. package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
  426. package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  427. package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  428. package/src/__golden__/wave-loop/op-overridden.json +16 -0
  429. package/src/__golden__/wave-loop/op-per-run.json +20 -0
  430. package/src/__golden__/wave-loop/op-point.json +13 -0
  431. package/src/__golden__/wave-loop/op-pr-review.json +10 -0
  432. package/src/__golden__/wave-loop/op-sealed.json +10 -0
  433. package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
  434. package/src/__golden__/wave-loop/op-spend.json +10 -0
  435. package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
  436. package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
  437. package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
  438. package/src/__golden__/wave-loop/op-wide.json +39 -0
  439. package/src/action-pins.test.ts +78 -0
  440. package/src/action-pins.ts +92 -0
  441. package/src/cli/commands/carve-score-once.test.ts +99 -0
  442. package/src/cli/commands/carve.ts +37 -6
  443. package/src/cli/commands/check-lexicon.test.ts +2 -2
  444. package/src/cli/commands/import-report.ts +71 -0
  445. package/src/cli/commands/import.ts +33 -3
  446. package/src/cli/commands/migrate-dialect.test.ts +145 -0
  447. package/src/cli/commands/migrate.ts +132 -11
  448. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
  449. package/src/cli/handlers/approve.ts +23 -2
  450. package/src/cli/handlers/build.ts +7 -1
  451. package/src/cli/handlers/ledger.ts +54 -0
  452. package/src/cli/handlers/migrate.ts +21 -12
  453. package/src/cli/handlers/misc.ts +10 -1
  454. package/src/cli/handlers/pr-env.ts +2 -2
  455. package/src/cli/handlers/pr.ts +138 -36
  456. package/src/cli/handlers/query.ts +16 -4
  457. package/src/cli/handlers/release.ts +6 -3
  458. package/src/cli/handlers/search.ts +13 -34
  459. package/src/cli/main.test.ts +15 -0
  460. package/src/cli/main.ts +65 -14
  461. package/src/cli/parse-args.ts +27 -2
  462. package/src/cli/registry.ts +14 -4
  463. package/src/components/builders.ts +8 -0
  464. package/src/components/capability-plugin-loader.ts +13 -1
  465. package/src/components/capability-plugin.ts +16 -0
  466. package/src/components/pr-hooks.test.ts +73 -5
  467. package/src/components/pr-hooks.ts +95 -5
  468. package/src/components/pr-pipeline.ts +64 -16
  469. package/src/components/pr-policy.test.ts +64 -1
  470. package/src/components/pr-policy.ts +53 -0
  471. package/src/components/registry.test.ts +1 -1
  472. package/src/components/starter-plugin.ts +6 -0
  473. package/src/components/verbs/index.ts +2 -0
  474. package/src/components/verbs/publish-artifact.test.ts +60 -0
  475. package/src/components/verbs/publish-artifact.ts +122 -0
  476. package/src/components/verbs/publish-image.test.ts +101 -0
  477. package/src/components/verbs/publish-image.ts +265 -0
  478. package/src/config-environments.ts +28 -1
  479. package/src/config.ts +8 -1
  480. package/src/gate-decision-bundle.test.ts +1 -0
  481. package/src/gate-decision-identity.test.ts +9 -0
  482. package/src/gate-decision.ts +26 -3
  483. package/src/graph-ir.ts +27 -0
  484. package/src/graph-walk.test.ts +44 -0
  485. package/src/graph-walk.ts +102 -0
  486. package/src/import/parser.ts +20 -0
  487. package/src/lexicon.ts +74 -6
  488. package/src/lifecycle/gate-ledger.ts +8 -0
  489. package/src/lifecycle/git.ts +2 -2
  490. package/src/lifecycle/ledger-read.test.ts +107 -0
  491. package/src/lifecycle/ledger-read.ts +195 -0
  492. package/src/lifecycle/release-workstation.ts +24 -0
  493. package/src/lifecycle/run-ledger.ts +5 -2
  494. package/src/lint/cross-root.test.ts +122 -0
  495. package/src/lint/discover.ts +3 -1
  496. package/src/lint/post-synth.ts +212 -2
  497. package/src/lint/rules/op/index.ts +2 -0
  498. package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
  499. package/src/op/activities/activity-contracts.ts +5 -2
  500. package/src/op/activities/index.ts +2 -2
  501. package/src/op/activities/review-agent.test.ts +221 -4
  502. package/src/op/activities/review-agent.ts +265 -22
  503. package/src/op/activities/work-evidence.ts +9 -1
  504. package/src/op/builders.ts +9 -5
  505. package/src/op/composites/apply-op.test.ts +108 -0
  506. package/src/op/composites/apply-op.ts +37 -2
  507. package/src/op/gate-approval.test.ts +6 -1
  508. package/src/op/gate-approval.ts +12 -6
  509. package/src/op/gate-quorum-at-base.test.ts +211 -0
  510. package/src/op/gate-quorum.ts +156 -8
  511. package/src/op/gate-review.ts +14 -0
  512. package/src/op/gate.ts +67 -8
  513. package/src/op/index.ts +3 -2
  514. package/src/op/local-executor.ts +69 -9
  515. package/src/op/op-waves-depends-on.test.ts +81 -0
  516. package/src/op/op-waves-hook-targets.test.ts +4 -2
  517. package/src/op/op-waves-quorum-product.test.ts +158 -0
  518. package/src/op/op-waves-run.ts +288 -14
  519. package/src/op/op-waves.ts +143 -14
  520. package/src/op/runtime.ts +8 -0
  521. package/src/op/schedule-overdue.ts +33 -0
  522. package/src/op/stage-hooks.ts +13 -5
  523. package/src/op/workspace-run-env.ts +29 -0
  524. package/src/pr-forge-bundle.test.ts +2 -2
  525. package/src/pr-forge.test.ts +47 -0
  526. package/src/pr-forge.ts +68 -0
  527. package/src/pr-post-open.e2e.test.ts +36 -0
  528. package/src/pr-post.test.ts +102 -3
  529. package/src/pr-post.ts +89 -1
  530. package/src/read-filter.test.ts +54 -0
  531. package/src/read-filter.ts +193 -0
  532. package/src/run-event.ts +1 -1
  533. package/src/stage-hooks-bundle.test.ts +1 -0
  534. package/src/terraform/carve.ts +52 -15
  535. package/src/terraform/cuts.test.ts +173 -0
  536. package/src/terraform/cuts.ts +188 -0
  537. package/src/terraform/folds.ts +44 -0
  538. package/src/terraform/graph.ts +9 -0
  539. package/src/terraform/radius.test.ts +90 -0
  540. package/src/terraform/reach.test.ts +146 -0
  541. package/src/terraform/reach.ts +247 -0
  542. package/src/terraform/score.ts +27 -29
  543. package/src/terraform/state.ts +3 -1
  544. package/src/terraform/types.ts +8 -0
  545. package/src/wave-blocked.ts +28 -3
  546. package/src/wave-loop-golden.test.ts +4 -3
  547. package/src/workspace/behold-kinds.test.ts +1 -1
  548. package/src/workspace/check-contract.test.ts +7 -6
  549. package/src/workspace/check.schema.json +11 -2
  550. package/src/workspace/checks/ci-branch.test.ts +128 -0
  551. package/src/workspace/checks/ci-branch.ts +141 -0
  552. package/src/workspace/checks/links.ts +12 -1
  553. package/src/workspace/checks/org.ts +169 -0
  554. package/src/workspace/checks.ts +64 -7
  555. package/src/workspace/ci-branches.ts +31 -0
  556. package/src/workspace/ci-green-branches.test.ts +153 -0
  557. package/src/workspace/ci-green-cli.ts +7 -7
  558. package/src/workspace/ci-green-workflow.test.ts +4 -3
  559. package/src/workspace/ci-green-workflow.ts +13 -9
  560. package/src/workspace/ci-green.ts +49 -12
  561. package/src/workspace/ci-run.test.ts +72 -1
  562. package/src/workspace/ci-run.ts +68 -8
  563. package/src/workspace/ci-serve.test.ts +95 -0
  564. package/src/workspace/ci-serve.ts +106 -65
  565. package/src/workspace/component-environments.test.ts +25 -2
  566. package/src/workspace/compose-graph.ts +9 -2
  567. package/src/workspace/composites.schema.json +22 -0
  568. package/src/workspace/composites.test.ts +39 -8
  569. package/src/workspace/composites.ts +6 -2
  570. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  571. package/src/workspace/cross-root-lint.test.ts +90 -0
  572. package/src/workspace/cross-root-lint.ts +126 -0
  573. package/src/workspace/dbt-kind.test.ts +3 -2
  574. package/src/workspace/dbt-models-reader.ts +362 -0
  575. package/src/workspace/dbt-models.test.ts +248 -0
  576. package/src/workspace/dbt-project-common.ts +113 -0
  577. package/src/workspace/dbt-project-reader.ts +29 -112
  578. package/src/workspace/decision-rank.ts +40 -0
  579. package/src/workspace/declaration.schema.json +133 -24
  580. package/src/workspace/declaration.ts +84 -15
  581. package/src/workspace/environments.ts +40 -4
  582. package/src/workspace/flyway-dir.ts +113 -0
  583. package/src/workspace/flyway-layout.ts +337 -0
  584. package/src/workspace/graph-cli.ts +25 -10
  585. package/src/workspace/graph-contract.test.ts +4 -2
  586. package/src/workspace/graph.schema.json +34 -0
  587. package/src/workspace/identity.test.ts +14 -2
  588. package/src/workspace/intent.ts +6 -14
  589. package/src/workspace/kind-link-readers.ts +68 -3
  590. package/src/workspace/kinds.test.ts +12 -7
  591. package/src/workspace/kinds.ts +132 -7
  592. package/src/workspace/ledger.schema.json +158 -0
  593. package/src/workspace/lexicon-outputs.ts +132 -13
  594. package/src/workspace/lineage-check.ts +30 -7
  595. package/src/workspace/links.ts +24 -1
  596. package/src/workspace/ls-contract.test.ts +1 -1
  597. package/src/workspace/ls.schema.json +7 -0
  598. package/src/workspace/ls.ts +10 -1
  599. package/src/workspace/member-commands.ts +60 -2
  600. package/src/workspace/member-file-schema.test.ts +124 -0
  601. package/src/workspace/migrate-links.test.ts +99 -0
  602. package/src/workspace/migrate-links.ts +108 -0
  603. package/src/workspace/migration-dirs.test.ts +272 -0
  604. package/src/workspace/migration-dirs.ts +267 -0
  605. package/src/workspace/org-scope.test.ts +238 -0
  606. package/src/workspace/reason-codes.test.ts +6 -1
  607. package/src/workspace/reason-codes.ts +11 -0
  608. package/src/workspace/records-cli.ts +58 -5
  609. package/src/workspace/records.schema.json +5 -0
  610. package/src/workspace/release-candidates.ts +7 -2
  611. package/src/workspace/release-train.ts +157 -0
  612. package/src/workspace/release-workflow.ts +4 -3
  613. package/src/workspace/repo-ref.ts +113 -0
  614. package/src/workspace/run-event.schema.json +2 -2
  615. package/src/workspace/runs-cli.ts +48 -4
  616. package/src/workspace/runs.schema.json +7 -0
  617. package/src/workspace/status-contract.test.ts +46 -1
  618. package/src/workspace/status-decisions.test.ts +100 -0
  619. package/src/workspace/status-decisions.ts +151 -0
  620. package/src/workspace/status-gates.ts +9 -0
  621. package/src/workspace/status.schema.json +6 -0
  622. package/src/workspace/status.ts +17 -3
  623. package/src/workspace/where-filters.test.ts +39 -0
  624. package/src/workspace/work-cli.ts +5 -3
  625. package/src/workspace/work-evidence-ops.test.ts +176 -0
  626. package/src/workspace/work-evidence-ops.ts +189 -0
  627. package/src/workspace/work-evidence.schema.json +49 -2
  628. package/src/workspace/work-evidence.ts +22 -3
  629. package/src/workspace/workspace-gates.ts +200 -0
  630. package/src/workspace/workspace-kinds.schema.json +58 -3
  631. package/src/workspace/workspace-ledger.ts +130 -0
  632. package/src/workspace/workspace-run.test.ts +322 -0
  633. package/src/workspace/workspace-run.ts +461 -0
@@ -22,7 +22,7 @@ import schema from "./declaration.schema.json" with { type: "json" };
22
22
  import { routeConflicts } from "./ci-branches";
23
23
  import { cloudIdentityProblems, CLOUDS, type CloudIdentityDeclaration } from "../ci-identity";
24
24
  import { expandGlob } from "./glob";
25
- import { EXAMPLES_KIND, holdsChantProject } from "./kinds";
25
+ import { EXAMPLES_KIND, holdsChantProject, REPO_KIND } from "./kinds";
26
26
  import { parseJsonText, pointerToken, type TextLocation } from "./jsonc";
27
27
  import type { ReasonCode } from "./reason-codes";
28
28
  import type { SecurityGroup } from "./security";
@@ -30,6 +30,7 @@ import { joinPath, type WorkspaceTree } from "./tree";
30
30
  import { loadAjv2020 } from "./ajv2020";
31
31
  import { readChantPackageVersion } from "../package-version";
32
32
  import { assertPrLoopHooks, type OpWaveHooks } from "../op/op-waves";
33
+ import { quorumProblems, type GateQuorumSpec } from "../op/gate-quorum";
33
34
  import { assertGatePolicySettings, type GatePolicySettings } from "../gate-policy";
34
35
 
35
36
  export const DECLARATION_SCHEMA_ID = schema.$id;
@@ -159,6 +160,13 @@ export interface SignedGate {
159
160
  gate: string;
160
161
  /** The class the signer must be in, or null for any signer the signers file at base lists. */
161
162
  class: PrincipalClass | null;
163
+ /**
164
+ * The approval rules an Op gate of this name takes (#4324): one rule or a
165
+ * list, as an Op's `approval.quorum`. Read here, at base, a change can't
166
+ * lower the quorum its own run needs. Null when the entry sets none, and
167
+ * the Op's own `approval.quorum` then applies.
168
+ */
169
+ quorum: GateQuorumSpec | null;
162
170
  pointer: string;
163
171
  }
164
172
 
@@ -212,13 +220,24 @@ export interface CiPhase {
212
220
  pointer: string;
213
221
  }
214
222
 
223
+ /** Every branch `ci.green` judges (#4325): `branches` when the declaration names several, else `branch`. */
224
+ export function greenBranches(green: Pick<CiGreen, "branch" | "branches">): string[] {
225
+ return green.branches ?? [green.branch];
226
+ }
227
+
215
228
  /** The default `ci.green.window`. */
216
229
  export const DEFAULT_CI_WINDOW = "24h";
217
230
 
218
231
  /** The declaration's `ci.green` block (#3573, ws-103), with its defaults. */
219
232
  export interface CiGreen {
220
- /** The branch whose first-parent commits are tagged. */
233
+ /** The branch whose first-parent commits are tagged. With several (#4325), the first one declared. */
221
234
  branch: string;
235
+ /**
236
+ * Every branch whose first-parent commits are tagged (#4325), in declaration
237
+ * order, the first being `branch`. Present only when the declaration names
238
+ * more than one, so a one-branch declaration reads as it always did.
239
+ */
240
+ branches?: string[];
222
241
  /** How far back a tick looks, such as `24h`. */
223
242
  window: string;
224
243
  /** The phases, in file order. */
@@ -638,9 +657,16 @@ export const DEFAULT_STATE_ROOT = "${XDG_STATE_HOME}/chant/boxes";
638
657
  export interface Member {
639
658
  type: "member";
640
659
  name: string;
641
- /** Relative to the workspace root; `"."` is the root member. */
660
+ /**
661
+ * Relative to the workspace root; `"."` is the root member. A member of kind
662
+ * `repo` has no directory here: its `dir` is {@link repoMemberDir}, which
663
+ * names no directory of this repository, and every reader that looks at
664
+ * member directories leaves it out by its kind (#3168).
665
+ */
642
666
  dir: string;
643
667
  kind: string;
668
+ /** For a member of kind `repo`, the other repository's workspace it names (#3168); null for every other kind. */
669
+ repo: RepoRef | null;
644
670
  roles: MemberRole[];
645
671
  /** Declared generated files, in file order. The implicit ones are not listed here (see `generated-files.ts`). */
646
672
  generated: GeneratedFile[];
@@ -660,6 +686,12 @@ export interface Member {
660
686
  because: string | null;
661
687
  /** Whether `chant workspace export` takes the member (#2552, D10). False when the entry does not say. */
662
688
  travel: boolean;
689
+ /**
690
+ * Whether a workspace gate's approval may stand in for this member's own
691
+ * gates (#2554, ws-039), when its digest covers the member's plan. Read
692
+ * from the declaration at base. Set only when the entry says true.
693
+ */
694
+ acceptWorkspaceGates?: true;
663
695
  /** The security groups this member adds to the declaration's top-level `security` (#4168 step 7), in file order; empty when it names none. */
664
696
  security: SecurityGroup[];
665
697
  /** The member's own `ci.workflow` (#4168 step 6), which wins over the top level's; null when it names none. */
@@ -691,10 +723,26 @@ export interface Pin {
691
723
  integrity: string | null;
692
724
  }
693
725
 
726
+ /** Another repository's workspace, by URL and pinned revision (#3168). */
727
+ export interface RepoRef {
728
+ url: string;
729
+ /** A full commit id. */
730
+ rev: string;
731
+ /** The workspace root inside that repository, relative to its git root; `"."` when the entry doesn't say. */
732
+ workspace: string;
733
+ }
734
+
735
+ /** The `dir` a `repo` member reads as (#3168): a marker, never a directory of this repository. */
736
+ export function repoMemberDir(name: string): string {
737
+ return `@repo/${name}`;
738
+ }
739
+
694
740
  export interface Declaration {
695
741
  name: string;
696
742
  schema: number;
697
743
  minReader: string | null;
744
+ /** `org` for an org-level workspace, which holds only `repo` members; `repo` otherwise, the default (#3168). */
745
+ scope: "repo" | "org";
698
746
  /** Members and groups, in file order. */
699
747
  entries: Entry[];
700
748
  members: Member[];
@@ -817,9 +865,13 @@ function explain(e: AjvError, value: unknown): string {
817
865
  const missing = String(e.params.missingProperty);
818
866
  if (missing === "because" && e.instancePath.endsWith("/handWritten")) return `a hand-written generated file needs "because", saying why it is kept by hand`;
819
867
  if (missing === "because") return `a member of kind other needs "because", saying why it is there`;
868
+ if (missing === "repo") return `a member of kind repo needs "repo", the other repository's url and pinned rev`;
820
869
  return `missing required field ${JSON.stringify(missing)}`;
821
870
  }
822
871
  if (e.keyword === "const" && e.instancePath === "/schema") return `schema must be 1, the only declaration format this chant reads`;
872
+ // A repo member has repo and no dir; every other member has dir and no repo (#3168).
873
+ if (e.keyword === "false schema" && e.instancePath.endsWith("/dir")) return `a member of kind repo has no dir: it names another repository's workspace with repo`;
874
+ if (e.keyword === "false schema" && e.instancePath.endsWith("/repo")) return `only a member of kind repo has repo`;
823
875
  return e.message ?? "is invalid";
824
876
  }
825
877
 
@@ -942,14 +994,17 @@ export function parseDeclaration(text: string, file: string, reader: string = re
942
994
  protocol: l.protocol ?? null,
943
995
  pointer: `${pointer}/links/${j}`,
944
996
  }));
945
- const records = recordKindsOf(e.records, e.dir as string, e.name as string, `${pointer}/records`);
997
+ const repoRaw = e.repo as { url: string; rev: string; workspace?: string } | undefined;
998
+ const dir = e.kind === REPO_KIND ? repoMemberDir(e.name as string) : (e.dir as string);
999
+ const records = recordKindsOf(e.records, dir, e.name as string, `${pointer}/records`);
946
1000
  const diagrams = diagramsOf(e.diagrams, e.name as string, `${pointer}/diagrams`);
947
1001
  const box = boxOf(e.box, `${pointer}/box`);
948
1002
  return {
949
1003
  type: "member",
950
1004
  name: e.name as string,
951
- dir: e.dir as string,
1005
+ dir,
952
1006
  kind: e.kind as string,
1007
+ repo: repoRaw ? { url: repoRaw.url, rev: repoRaw.rev, workspace: repoRaw.workspace ?? "." } : null,
953
1008
  roles,
954
1009
  generated,
955
1010
  outputs: e.outputs === undefined ? null : [...(e.outputs as string[])],
@@ -961,6 +1016,7 @@ export function parseDeclaration(text: string, file: string, reader: string = re
961
1016
  upstream: (e.upstream as string | undefined) ?? null,
962
1017
  because: (e.because as string | undefined) ?? null,
963
1018
  travel: e.travel === true,
1019
+ ...(e.acceptWorkspaceGates === true ? { acceptWorkspaceGates: true as const } : {}),
964
1020
  security: [...((e.security as SecurityGroup[] | undefined) ?? [])],
965
1021
  ciWorkflow: ((e.ci as { workflow?: CiWorkflow } | undefined)?.workflow) ?? null,
966
1022
  ciHooks: ciHooksOf((e.ci as { hooks?: unknown } | undefined)?.hooks, `${pointer}/ci/hooks`, at),
@@ -986,8 +1042,10 @@ export function parseDeclaration(text: string, file: string, reader: string = re
986
1042
  // Placement (#2524 D2): one root member at most, no two members in one
987
1043
  // directory, and only the root member contains other members.
988
1044
  const members = entries.filter((e): e is Member => e.type === "member");
1045
+ // A repo member has no directory here (#3168), so it takes no part in placement.
1046
+ const placed = members.filter((m) => m.kind !== REPO_KIND);
989
1047
  const byDir = new Map<string, Member>();
990
- for (const m of members) {
1048
+ for (const m of placed) {
991
1049
  const other = byDir.get(m.dir);
992
1050
  if (other) {
993
1051
  throw new WorkspaceReadError(
@@ -998,8 +1056,8 @@ export function parseDeclaration(text: string, file: string, reader: string = re
998
1056
  }
999
1057
  byDir.set(m.dir, m);
1000
1058
  }
1001
- for (const m of members) {
1002
- const outer = members.find((o) => o !== m && o.dir !== "." && isInside(m.dir, o.dir));
1059
+ for (const m of placed) {
1060
+ const outer = placed.find((o) => o !== m && o.dir !== "." && isInside(m.dir, o.dir));
1003
1061
  if (outer) {
1004
1062
  throw new WorkspaceReadError(
1005
1063
  "placement-invalid",
@@ -1109,6 +1167,7 @@ export function parseDeclaration(text: string, file: string, reader: string = re
1109
1167
  name: obj.name as string,
1110
1168
  schema: obj.schema as number,
1111
1169
  minReader: (obj.minReader as string | undefined) ?? null,
1170
+ scope: obj.scope === "org" ? "org" : "repo",
1112
1171
  entries,
1113
1172
  members,
1114
1173
  groups: entries.filter((e): e is Group => e.type === "group"),
@@ -1121,7 +1180,7 @@ export function parseDeclaration(text: string, file: string, reader: string = re
1121
1180
  changes: changesOf(obj.changes as Record<string, unknown> | undefined),
1122
1181
  writeScope,
1123
1182
  agents,
1124
- identity: identityOf(obj.identity),
1183
+ identity: identityOf(obj.identity, at),
1125
1184
  ci,
1126
1185
  retention: retentionOf(obj.retention),
1127
1186
  metrics: metricsOf(obj.metrics),
@@ -1181,13 +1240,22 @@ function writeScopeOf(raw: unknown, members: Member[], at: (pointer: string, key
1181
1240
  * (#2548, ws-101): names are unique, every member a session names is a
1182
1241
  * declared member, and a principal is listed by one session at most.
1183
1242
  */
1184
- /** The `identity` block, already validated by the schema (#3163). */
1185
- function identityOf(raw: unknown): IdentityPolicy | null {
1243
+ /**
1244
+ * The `identity` block, already validated by the schema (#3163), with the
1245
+ * quorum rules the schema can't say (#4324): `notAuthor` is refused, since an
1246
+ * Op gate has no pull request to read the author from.
1247
+ */
1248
+ function identityOf(raw: unknown, at: (pointer: string, key?: boolean) => ErrorLocation): IdentityPolicy | null {
1186
1249
  if (raw === undefined) return null;
1187
- const block = raw as { attribution?: "any" | "identified"; gates?: Record<string, { class?: string }> };
1250
+ const block = raw as { attribution?: "any" | "identified"; gates?: Record<string, { class?: string; quorum?: GateQuorumSpec }> };
1188
1251
  const gates: Record<string, SignedGate> = {};
1189
1252
  for (const [gate, entry] of Object.entries(block.gates ?? {})) {
1190
- gates[gate] = { gate, class: entry.class ?? null, pointer: `/identity/gates/${gate.replace(/~/g, "~0").replace(/\//g, "~1")}` };
1253
+ const pointer = `/identity/gates/${gate.replace(/~/g, "~0").replace(/\//g, "~1")}`;
1254
+ if (entry.quorum !== undefined) {
1255
+ const [problem] = quorumProblems(entry.quorum, `identity.gates.${gate}.quorum`, { notAuthor: false });
1256
+ if (problem) throw new WorkspaceReadError("declaration-invalid", problem.replace(/`/g, ""), at(`${pointer}/quorum`));
1257
+ }
1258
+ gates[gate] = { gate, class: entry.class ?? null, quorum: entry.quorum !== undefined ? structuredClone(entry.quorum) : null, pointer };
1191
1259
  }
1192
1260
  return { attribution: block.attribution ?? "any", gates };
1193
1261
  }
@@ -1266,7 +1334,7 @@ function cloudIdentityOf(raw: CloudIdentityDeclaration, at: (pointer: string, ke
1266
1334
 
1267
1335
  function ciOf(raw: unknown, at: (pointer: string, key?: boolean) => ErrorLocation): CiDeclaration | null {
1268
1336
  if (raw === undefined) return null;
1269
- const block = raw as { reportUrl?: string; workflow?: CiWorkflow; hooks?: unknown; identity?: { cloud?: CloudIdentityDeclaration }; branches?: Record<string, string[]>; labels?: Record<string, string[]>; locks?: CiLocks; policy?: unknown; prEnvironment?: { template: string; ttl?: string; teardown?: { name?: string; command: string[]; lexicons?: string[] } }; green?: { branch: string; window?: string; phases: Record<string, string[] | { runs: string[]; skipped?: CiSkipped; build?: CiBuild }>; require: string[]; preMerge?: string[]; signedSince?: string; source?: CiSource } };
1337
+ const block = raw as { reportUrl?: string; workflow?: CiWorkflow; hooks?: unknown; identity?: { cloud?: CloudIdentityDeclaration }; branches?: Record<string, string[]>; labels?: Record<string, string[]>; locks?: CiLocks; policy?: unknown; prEnvironment?: { template: string; ttl?: string; teardown?: { name?: string; command: string[]; lexicons?: string[] } }; green?: { branch: string | string[]; window?: string; phases: Record<string, string[] | { runs: string[]; skipped?: CiSkipped; build?: CiBuild }>; require: string[]; preMerge?: string[]; signedSince?: string; source?: CiSource } };
1270
1338
  const hooks = ciHooksOf(block.hooks, "/ci/hooks", at);
1271
1339
  const policy = ciPolicyOf(block.policy, at);
1272
1340
  const workflow = {
@@ -1327,7 +1395,8 @@ function ciOf(raw: unknown, at: (pointer: string, key?: boolean) => ErrorLocatio
1327
1395
  at(`/ci/green/preMerge/${i}`),
1328
1396
  );
1329
1397
  }
1330
- return { green: { branch: g.branch, window: g.window ?? DEFAULT_CI_WINDOW, phases, require: [...g.require], ...(g.preMerge !== undefined ? { preMerge: [...g.preMerge] } : {}), signedSince: g.signedSince ?? null, source: g.source ?? "checks", pointer: "/ci/green" }, ...workflow, reportUrl };
1398
+ const judged = Array.isArray(g.branch) ? g.branch : [g.branch];
1399
+ return { green: { branch: judged[0]!, ...(judged.length > 1 ? { branches: [...judged] } : {}), window: g.window ?? DEFAULT_CI_WINDOW, phases, require: [...g.require], ...(g.preMerge !== undefined ? { preMerge: [...g.preMerge] } : {}), signedSince: g.signedSince ?? null, source: g.source ?? "checks", pointer: "/ci/green" }, ...workflow, reportUrl };
1331
1400
  }
1332
1401
 
1333
1402
  function agentsOf(raw: unknown, members: Member[], at: (pointer: string, key?: boolean) => ErrorLocation): AgentDeclaration[] {
@@ -23,6 +23,13 @@
23
23
  * would take it, or left out with `environments-component-undeclared` when
24
24
  * the config's environments don't cover it.
25
25
  *
26
+ * Each environment also names its `executor` (#4402): the forge and committed
27
+ * workflow that deploys it, as the member's config declares on the
28
+ * environment's entry (`{ name: "prod", executor: { forge: "github",
29
+ * workflow: "deploy-prod.yml" } }`), a literal entry before a pattern. When
30
+ * none is declared, `forge` and `workflow` are null and `reason` says why.
31
+ * chant never derives it from a generated workflow's name.
32
+ *
26
33
  * `chant run --env` refuses a name the config's `environments` doesn't cover
27
34
  * whenever it declares any (`unknownEnvError` in `../env.ts`), so a ledger
28
35
  * environment the config no longer covers is left out, with a reason. The
@@ -36,7 +43,7 @@
36
43
  */
37
44
 
38
45
  import { execFileSync } from "node:child_process";
39
- import { environmentName, isEnvironmentPattern, matchesDeclaredEnvironment, type EnvironmentDeclaration } from "../config";
46
+ import { environmentExecutor, environmentName, isEnvironmentPattern, matchesDeclaredEnvironment, type EnvironmentDeclaration, type EnvironmentExecutor } from "../config";
40
47
  import type { ComponentEnvironmentDeclaration } from "../components/component";
41
48
  import type { ReasonCode } from "./reason-codes";
42
49
  import { LOCAL_RUNTIME, type MemberRuntimes } from "./runtimes";
@@ -60,6 +67,23 @@ export const ENVIRONMENT_REASON_CODES = [
60
67
  ] as const satisfies readonly ReasonCode[];
61
68
  export type EnvironmentReasonCode = (typeof ENVIRONMENT_REASON_CODES)[number];
62
69
 
70
+ /** Why an environment names no executor (#4402). Closed: part of the read contract. */
71
+ export const EXECUTOR_REASON_CODES = [
72
+ /** The member's chant.config.ts declares no executor for the environment, so nothing says which forge workflow deploys it. */
73
+ "executor-none-declared",
74
+ /** The member's chant.config.ts could not be read, so whether a forge workflow deploys the environment is unknown. */
75
+ "executor-config-unreadable",
76
+ ] as const satisfies readonly ReasonCode[];
77
+ export type ExecutorReasonCode = (typeof EXECUTOR_REASON_CODES)[number];
78
+
79
+ /** The forge workflow that deploys an environment (#4402), or why none is named. */
80
+ export interface ComponentExecutor {
81
+ forge: EnvironmentExecutor["forge"] | null;
82
+ workflow: string | null;
83
+ /** Null when `forge` and `workflow` are set. */
84
+ reason: { code: ExecutorReasonCode; message: string } | null;
85
+ }
86
+
63
87
  export interface EnvironmentReason {
64
88
  code: EnvironmentReasonCode;
65
89
  message: string;
@@ -75,6 +99,8 @@ export interface ComponentEnvironment {
75
99
  source: "config" | "ledger" | "builtin" | "component";
76
100
  /** Where a release of the component goes in this environment, as the component declares it (#3153), or null when it declares nothing for it. */
77
101
  site: ComponentSite | null;
102
+ /** The forge and committed workflow that deploys this environment, from the member's config (#4402). */
103
+ executor: ComponentExecutor;
78
104
  /** The command that deploys the component there, on the site's runtime when the member hosts it and else the default runtime, run in the member's directory. */
79
105
  command: string;
80
106
  }
@@ -99,7 +125,7 @@ export type LedgerEnvironmentReader = (member: { name: string; dir: string }, cw
99
125
  /** What one member's config and ledger say about environments. */
100
126
  export interface MemberEnvironments {
101
127
  /** Each environment in list order, without the per-component site and command. */
102
- environments: Omit<ComponentEnvironment, "command" | "site">[];
128
+ environments: Omit<ComponentEnvironment, "command" | "site" | "executor">[];
103
129
  reasons: EnvironmentReason[];
104
130
  /** The config's environments, for whether `chant run --env` takes a name: null when the config couldn't be read, `[]` when it declares none. */
105
131
  declared?: EnvironmentDeclaration[] | null;
@@ -177,6 +203,16 @@ export function memberEnvironments(runtimes: MemberRuntimes | undefined, ledger:
177
203
  return { environments: out, reasons, declared };
178
204
  }
179
205
 
206
+ /** The executor the member's config declares for `env`, or why there is none. */
207
+ export function executorFor(env: string, member: MemberEnvironments | undefined): ComponentExecutor {
208
+ if (member && member.declared === null) {
209
+ return { forge: null, workflow: null, reason: { code: "executor-config-unreadable", message: `chant.config.ts could not be read, so no executor is known for ${env}` } };
210
+ }
211
+ const found = environmentExecutor(member?.declared ?? undefined, env);
212
+ if (found) return { forge: found.forge, workflow: found.workflow, reason: null };
213
+ return { forge: null, workflow: null, reason: { code: "executor-none-declared", message: `chant.config.ts declares no executor for ${env}` } };
214
+ }
215
+
180
216
  /**
181
217
  * The environments one component may deploy to, each with its command line.
182
218
  * `declared` is what the component's contract says (#3153): an environment
@@ -194,7 +230,7 @@ export function componentEnvironments(
194
230
  hosts: readonly string[] = [],
195
231
  reasons: EnvironmentReason[] = [],
196
232
  ): ComponentEnvironment[] {
197
- const list: Omit<ComponentEnvironment, "command" | "site">[] = [...(member?.environments ?? [{ name: LOCAL_ENVIRONMENT, default: true, source: "builtin" as const }])];
233
+ const list: Omit<ComponentEnvironment, "command" | "site" | "executor">[] = [...(member?.environments ?? [{ name: LOCAL_ENVIRONMENT, default: true, source: "builtin" as const }])];
198
234
  const config = member?.declared;
199
235
  const takes = (env: string): boolean => !config || config.length === 0 || matchesDeclaredEnvironment(config, env);
200
236
  const sites = new Map<string, ComponentSite>();
@@ -212,6 +248,6 @@ export function componentEnvironments(
212
248
  return list.map((e) => {
213
249
  const site = sites.get(e.name) ?? null;
214
250
  const on = site?.runtime && (site.runtime === LOCAL_RUNTIME || hosts.includes(site.runtime)) ? site.runtime : runtime;
215
- return { ...e, site, command: `chant run --components ${component}${on === LOCAL_RUNTIME ? "" : ` --on ${on}`}${e.default ? "" : ` --env ${e.name}`}` };
251
+ return { ...e, site, executor: executorFor(e.name, member), command: `chant run --components ${component}${on === LOCAL_RUNTIME ? "" : ` --on ${on}`}${e.default ? "" : ` --env ${e.name}`}` };
216
252
  });
217
253
  }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The `flyway-dir` reader (#4400): the migrations of a Flyway project, in the
3
+ * order `flyway migrate` applies them. It reads the layout with
4
+ * `./flyway-layout.ts`, the reading `yodel check` shares, and never runs
5
+ * Flyway or substitutes placeholders (a replay does that).
6
+ *
7
+ * File names follow Flyway's migration naming
8
+ * (https://documentation.red-gate.com/fd/migrations-271585107.html):
9
+ *
10
+ * - versioned `V<version>__<description>.sql`, the version digits joined by
11
+ * `.` or `_`;
12
+ * - repeatable `R__<description>.sql`, run after every versioned migration,
13
+ * in the order of their descriptions;
14
+ * - baseline `B<version>__<description>.sql`, listed with the versioned ones;
15
+ * - undo `U<version>__<description>.sql`, which is the `down` file of the
16
+ * versioned migration with that version and is not listed on its own.
17
+ *
18
+ * The prefixes, the separator and the suffixes come from the configuration.
19
+ * Versions compare part by part as numbers, so `V2` comes before `V10` and
20
+ * `V1.1` before `V1.2`. Callbacks are not migrations, and a Java or Kotlin
21
+ * migration is a gap: its code is not SQL.
22
+ */
23
+
24
+ import type { KindLinkRead, KindReadGap, KindReadMigration, KindReaderInput } from "./kind-link-readers";
25
+ import { codeMigrations, findFlywayConfig, isCallback, readFlywayConfig, walk, type FlywayConfig } from "./flyway-layout";
26
+ import { fieldString, withReplay } from "./migration-dirs";
27
+
28
+ const escape = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
29
+
30
+ /** Compare dotted versions part by part as numbers; a missing part is 0. */
31
+ export function compareVersions(a: string, b: string): number {
32
+ const pa = a.split(/[._]/).map(BigInt);
33
+ const pb = b.split(/[._]/).map(BigInt);
34
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
35
+ const x = pa[i] ?? 0n;
36
+ const y = pb[i] ?? 0n;
37
+ if (x !== y) return x < y ? -1 : 1;
38
+ }
39
+ return 0;
40
+ }
41
+
42
+ export interface FlywayFile {
43
+ type: KindReadMigration["type"];
44
+ /** The version written with `.` between its parts; empty for a repeatable migration. */
45
+ version: string;
46
+ description: string;
47
+ file: string;
48
+ }
49
+
50
+ /** The file's migration role under `config`'s naming, or undefined when its name is not a migration's. */
51
+ export function classifyFlywayFile(file: string, config: FlywayConfig): FlywayFile | undefined {
52
+ const name = file.split("/").pop() ?? file;
53
+ if (isCallback(name)) return undefined;
54
+ const suffix = config.sqlMigrationSuffixes.find((s) => name.endsWith(s));
55
+ if (!suffix) return undefined;
56
+ const stem = name.slice(0, -suffix.length);
57
+ const sep = escape(config.sqlMigrationSeparator);
58
+ const repeatable = new RegExp(`^${escape(config.repeatableSqlMigrationPrefix)}${sep}(.+)$`).exec(stem);
59
+ if (repeatable) return { type: "repeatable", version: "", description: repeatable[1]!.replace(/_/g, " "), file };
60
+ const roles: [KindReadMigration["type"], string][] = [
61
+ ["versioned", config.sqlMigrationPrefix],
62
+ ["baseline", config.baselineMigrationPrefix],
63
+ ["undo", config.undoSqlMigrationPrefix],
64
+ ];
65
+ for (const [type, prefix] of roles) {
66
+ if (!prefix) continue;
67
+ const m = new RegExp(`^${escape(prefix)}([0-9]+(?:[._][0-9]+)*)${sep}(.+)$`).exec(stem);
68
+ if (m) return { type, version: m[1]!.replace(/_/g, "."), description: m[2]!.replace(/_/g, " "), file };
69
+ }
70
+ return undefined;
71
+ }
72
+
73
+ /** The configuration file the replay depends on, besides the migrations: it holds the placeholders. */
74
+ export function flywayReplayFiles(input: Pick<KindReaderInput, "tree" | "dir">): string[] {
75
+ const f = findFlywayConfig(input.tree, input.dir);
76
+ return f === undefined ? [] : [f];
77
+ }
78
+
79
+ export const readFlywayDir = (input: KindReaderInput): KindLinkRead => withReplay(listFlywayDir(input), input.tree, input.dir, flywayReplayFiles(input));
80
+
81
+ function listFlywayDir(input: KindReaderInput): KindLinkRead {
82
+ const { tree, dir } = input;
83
+ const gaps: KindReadGap[] = [];
84
+ const result: KindLinkRead = { reader: "flyway-dir", links: [], gaps, migrations: [] };
85
+ const configFile = findFlywayConfig(tree, dir);
86
+ let config: FlywayConfig;
87
+ try {
88
+ config = readFlywayConfig(tree, configFile, dir);
89
+ } catch (err) {
90
+ gaps.push({ file: configFile ?? dir, line: 1, message: `the Flyway configuration could not be read (${(err as Error).message}), so no migration was listed` });
91
+ return result;
92
+ }
93
+ const dialect = fieldString(input.fields, "dialect", config.dialect ?? "postgres");
94
+ for (const l of config.outside) gaps.push({ file: configFile ?? dir, line: 1, message: `the location ${l} lies outside the workspace, so its migrations were not listed` });
95
+
96
+ const files = [...new Set(config.locations.flatMap((d) => walk(tree, d)))];
97
+ const classified = files.map((f) => classifyFlywayFile(f, config)).filter((f): f is FlywayFile => f !== undefined);
98
+ for (const code of codeMigrations(tree, config)) gaps.push({ file: code, line: 1, message: `${code.split("/").pop()!} is a code migration; its code is not SQL, so it is not listed` });
99
+
100
+ const undo = new Map(classified.filter((f) => f.type === "undo").map((f) => [f.version, f.file]));
101
+ const ordered = classified.filter((f) => f.type === "versioned" || f.type === "baseline").sort((a, b) => compareVersions(a.version, b.version) || (a.type === "baseline" ? -1 : 1) || (a.file < b.file ? -1 : 1));
102
+ const repeatable = classified.filter((f) => f.type === "repeatable").sort((a, b) => (a.description < b.description ? -1 : a.description > b.description ? 1 : a.file < b.file ? -1 : 1));
103
+ const seen = new Map<string, string>();
104
+ for (const f of ordered.filter((x) => x.type === "versioned")) {
105
+ const prior = [...seen.keys()].find((v) => compareVersions(v, f.version) === 0);
106
+ if (prior !== undefined) gaps.push({ file: f.file, line: 1, message: `version ${f.version} is also ${seen.get(prior)!}; Flyway refuses two migrations with one version` });
107
+ else seen.set(f.version, f.file);
108
+ }
109
+ [...ordered, ...repeatable].forEach((f, i) =>
110
+ result.migrations!.push({ position: i + 1, version: f.version, name: f.description, type: f.type, file: f.file, line: 1, down: f.type === "versioned" ? (undo.get(f.version) ?? false) : false, dialect }),
111
+ );
112
+ return result;
113
+ }