@intentius/chant 0.124.27 → 0.124.29

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 (681) hide show
  1. package/README.md +1 -1
  2. package/dist/__golden__/wave-loop/fan-out-gated.json +8 -0
  3. package/dist/__golden__/wave-loop/fan-out-no-members.json +4 -0
  4. package/dist/__golden__/wave-loop/fan-out-only.json +6 -0
  5. package/dist/__golden__/wave-loop/op-by-apply-hold.json +2 -0
  6. package/dist/__golden__/wave-loop/op-cost-member.json +3 -0
  7. package/dist/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
  8. package/dist/__golden__/wave-loop/op-held-on.json +2 -0
  9. package/dist/__golden__/wave-loop/op-hooks-held.json +2 -0
  10. package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
  11. package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
  12. package/dist/__golden__/wave-loop/op-hooks-share.json +3 -0
  13. package/dist/__golden__/wave-loop/op-per-run.json +7 -0
  14. package/dist/__golden__/wave-loop/op-pr-review.json +7 -0
  15. package/dist/__golden__/wave-loop/op-sealed.json +3 -0
  16. package/dist/__golden__/wave-loop/op-spend.json +3 -0
  17. package/dist/__golden__/wave-loop/op-wave-commands.json +7 -0
  18. package/dist/__golden__/wave-loop/op-wide-waiting.json +4 -0
  19. package/dist/build-params.d.ts +34 -1
  20. package/dist/build-params.d.ts.map +1 -1
  21. package/dist/build-params.js +31 -1
  22. package/dist/change-set-graph.d.ts +63 -0
  23. package/dist/change-set-graph.d.ts.map +1 -0
  24. package/dist/change-set-graph.js +130 -0
  25. package/dist/change-set.d.ts +62 -3
  26. package/dist/change-set.d.ts.map +1 -1
  27. package/dist/change-set.js +36 -4
  28. package/dist/chant-version.d.ts +9 -0
  29. package/dist/chant-version.d.ts.map +1 -0
  30. package/dist/chant-version.js +16 -0
  31. package/dist/cli/build-params-cli.d.ts +7 -1
  32. package/dist/cli/build-params-cli.d.ts.map +1 -1
  33. package/dist/cli/build-params-cli.js +17 -8
  34. package/dist/cli/commands/build.d.ts +8 -0
  35. package/dist/cli/commands/build.d.ts.map +1 -1
  36. package/dist/cli/commands/build.js +15 -11
  37. package/dist/cli/commands/check-lexicon-docs.d.ts.map +1 -1
  38. package/dist/cli/commands/check-lexicon-docs.js +30 -2
  39. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  40. package/dist/cli/commands/check-lexicon.js +13 -2
  41. package/dist/cli/commands/init-lexicon/templates/docs.d.ts +4 -1
  42. package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -1
  43. package/dist/cli/commands/init-lexicon/templates/docs.js +6 -6
  44. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  45. package/dist/cli/commands/init-lexicon.js +17 -8
  46. package/dist/cli/handlers/approve.d.ts.map +1 -1
  47. package/dist/cli/handlers/approve.js +64 -4
  48. package/dist/cli/handlers/build.d.ts.map +1 -1
  49. package/dist/cli/handlers/build.js +43 -4
  50. package/dist/cli/handlers/change-set.d.ts +10 -0
  51. package/dist/cli/handlers/change-set.d.ts.map +1 -1
  52. package/dist/cli/handlers/change-set.js +51 -1
  53. package/dist/cli/handlers/fan-out.d.ts +10 -1
  54. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  55. package/dist/cli/handlers/fan-out.js +54 -6
  56. package/dist/cli/handlers/lifecycle-gc.d.ts +19 -0
  57. package/dist/cli/handlers/lifecycle-gc.d.ts.map +1 -0
  58. package/dist/cli/handlers/lifecycle-gc.js +143 -0
  59. package/dist/cli/handlers/pr.d.ts +16 -2
  60. package/dist/cli/handlers/pr.d.ts.map +1 -1
  61. package/dist/cli/handlers/pr.js +269 -37
  62. package/dist/cli/handlers/promote.d.ts +7 -0
  63. package/dist/cli/handlers/promote.d.ts.map +1 -1
  64. package/dist/cli/handlers/promote.js +440 -28
  65. package/dist/cli/handlers/release.d.ts +91 -0
  66. package/dist/cli/handlers/release.d.ts.map +1 -0
  67. package/dist/cli/handlers/release.js +589 -0
  68. package/dist/cli/handlers/run.d.ts +38 -2
  69. package/dist/cli/handlers/run.d.ts.map +1 -1
  70. package/dist/cli/handlers/run.js +234 -16
  71. package/dist/cli/main.d.ts.map +1 -1
  72. package/dist/cli/main.js +143 -17
  73. package/dist/cli/mcp/workspace-tools.js +1 -1
  74. package/dist/cli/parse-args.d.ts.map +1 -1
  75. package/dist/cli/parse-args.js +73 -5
  76. package/dist/cli/registry.d.ts +43 -5
  77. package/dist/cli/registry.d.ts.map +1 -1
  78. package/dist/cli/run-events.d.ts +30 -0
  79. package/dist/cli/run-events.d.ts.map +1 -0
  80. package/dist/cli/run-events.js +49 -0
  81. package/dist/cli/version.d.ts +3 -5
  82. package/dist/cli/version.d.ts.map +1 -1
  83. package/dist/cli/version.js +3 -13
  84. package/dist/codegen/docs-in-site.d.ts +71 -0
  85. package/dist/codegen/docs-in-site.d.ts.map +1 -0
  86. package/dist/codegen/docs-in-site.js +177 -0
  87. package/dist/codegen/docs-types.d.ts +14 -1
  88. package/dist/codegen/docs-types.d.ts.map +1 -1
  89. package/dist/codegen/docs.d.ts +18 -1
  90. package/dist/codegen/docs.d.ts.map +1 -1
  91. package/dist/codegen/docs.js +40 -7
  92. package/dist/codegen/rehype-base-url.mjs +15 -9
  93. package/dist/components/auto-release.d.ts +6 -1
  94. package/dist/components/auto-release.d.ts.map +1 -1
  95. package/dist/components/auto-release.js +3 -0
  96. package/dist/components/capability.d.ts +9 -0
  97. package/dist/components/capability.d.ts.map +1 -1
  98. package/dist/components/cli-support.d.ts +6 -0
  99. package/dist/components/cli-support.d.ts.map +1 -1
  100. package/dist/components/cli-support.js +10 -9
  101. package/dist/components/driver.d.ts +50 -9
  102. package/dist/components/driver.d.ts.map +1 -1
  103. package/dist/components/driver.js +116 -54
  104. package/dist/components/fan-out-inputs.d.ts +69 -0
  105. package/dist/components/fan-out-inputs.d.ts.map +1 -0
  106. package/dist/components/fan-out-inputs.js +169 -0
  107. package/dist/components/fan-out-record.d.ts +13 -0
  108. package/dist/components/fan-out-record.d.ts.map +1 -1
  109. package/dist/components/fan-out-record.js +16 -0
  110. package/dist/components/fan-out-run.d.ts +7 -0
  111. package/dist/components/fan-out-run.d.ts.map +1 -1
  112. package/dist/components/fan-out-run.js +85 -26
  113. package/dist/components/fan-out.d.ts +4 -0
  114. package/dist/components/fan-out.d.ts.map +1 -1
  115. package/dist/components/pr-pipeline.d.ts +25 -0
  116. package/dist/components/pr-pipeline.d.ts.map +1 -1
  117. package/dist/components/pr-pipeline.js +22 -4
  118. package/dist/components/pr-run.d.ts +11 -0
  119. package/dist/components/pr-run.d.ts.map +1 -1
  120. package/dist/components/pr-run.js +20 -1
  121. package/dist/components/promote-order.d.ts +38 -0
  122. package/dist/components/promote-order.d.ts.map +1 -0
  123. package/dist/components/promote-order.js +62 -0
  124. package/dist/components/promote.d.ts +38 -2
  125. package/dist/components/promote.d.ts.map +1 -1
  126. package/dist/components/promote.js +77 -2
  127. package/dist/components/release-compile.d.ts +142 -0
  128. package/dist/components/release-compile.d.ts.map +1 -0
  129. package/dist/components/release-compile.js +382 -0
  130. package/dist/components/release-gate.d.ts +135 -0
  131. package/dist/components/release-gate.d.ts.map +1 -0
  132. package/dist/components/release-gate.js +288 -0
  133. package/dist/components/release-promote.d.ts +96 -0
  134. package/dist/components/release-promote.d.ts.map +1 -0
  135. package/dist/components/release-promote.js +204 -0
  136. package/dist/components/run-progress.d.ts +7 -0
  137. package/dist/components/run-progress.d.ts.map +1 -1
  138. package/dist/components/wave-plan.d.ts +8 -1
  139. package/dist/components/wave-plan.d.ts.map +1 -1
  140. package/dist/components/wave-plan.js +11 -3
  141. package/dist/config.d.ts +45 -0
  142. package/dist/config.d.ts.map +1 -1
  143. package/dist/config.js +3 -0
  144. package/dist/flag-params.d.ts +54 -0
  145. package/dist/flag-params.d.ts.map +1 -0
  146. package/dist/flag-params.js +130 -0
  147. package/dist/index.d.ts +1 -0
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +2 -0
  150. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts +120 -0
  151. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -0
  152. package/dist/lifecycle/__fixtures__/publish-fakes.js +304 -0
  153. package/dist/lifecycle/change-set-store.d.ts +68 -0
  154. package/dist/lifecycle/change-set-store.d.ts.map +1 -0
  155. package/dist/lifecycle/change-set-store.js +97 -0
  156. package/dist/lifecycle/commit-sha.d.ts +13 -0
  157. package/dist/lifecycle/commit-sha.d.ts.map +1 -0
  158. package/dist/lifecycle/commit-sha.js +21 -0
  159. package/dist/lifecycle/delivery-metrics.d.ts +139 -0
  160. package/dist/lifecycle/delivery-metrics.d.ts.map +1 -0
  161. package/dist/lifecycle/delivery-metrics.js +145 -0
  162. package/dist/lifecycle/deploy-outcome.d.ts +81 -0
  163. package/dist/lifecycle/deploy-outcome.d.ts.map +1 -0
  164. package/dist/lifecycle/deploy-outcome.js +101 -0
  165. package/dist/lifecycle/gate-change-set.d.ts +78 -0
  166. package/dist/lifecycle/gate-change-set.d.ts.map +1 -0
  167. package/dist/lifecycle/gate-change-set.js +138 -0
  168. package/dist/lifecycle/gate-ledger.d.ts +51 -4
  169. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  170. package/dist/lifecycle/gate-ledger.js +18 -0
  171. package/dist/lifecycle/git.d.ts +30 -1
  172. package/dist/lifecycle/git.d.ts.map +1 -1
  173. package/dist/lifecycle/git.js +31 -5
  174. package/dist/lifecycle/index.d.ts +4 -0
  175. package/dist/lifecycle/index.d.ts.map +1 -1
  176. package/dist/lifecycle/index.js +4 -0
  177. package/dist/lifecycle/mixed-environment.d.ts +95 -0
  178. package/dist/lifecycle/mixed-environment.d.ts.map +1 -0
  179. package/dist/lifecycle/mixed-environment.js +154 -0
  180. package/dist/lifecycle/publish-attachments.d.ts +79 -0
  181. package/dist/lifecycle/publish-attachments.d.ts.map +1 -0
  182. package/dist/lifecycle/publish-attachments.js +179 -0
  183. package/dist/lifecycle/publish-credentials.d.ts +37 -0
  184. package/dist/lifecycle/publish-credentials.d.ts.map +1 -0
  185. package/dist/lifecycle/publish-credentials.js +69 -0
  186. package/dist/lifecycle/publish-declaration.d.ts +97 -0
  187. package/dist/lifecycle/publish-declaration.d.ts.map +1 -0
  188. package/dist/lifecycle/publish-declaration.js +83 -0
  189. package/dist/lifecycle/publish-forge.d.ts +53 -0
  190. package/dist/lifecycle/publish-forge.d.ts.map +1 -0
  191. package/dist/lifecycle/publish-forge.js +298 -0
  192. package/dist/lifecycle/publish-npm.d.ts +61 -0
  193. package/dist/lifecycle/publish-npm.d.ts.map +1 -0
  194. package/dist/lifecycle/publish-npm.js +242 -0
  195. package/dist/lifecycle/publish-oci.d.ts +64 -0
  196. package/dist/lifecycle/publish-oci.d.ts.map +1 -0
  197. package/dist/lifecycle/publish-oci.js +383 -0
  198. package/dist/lifecycle/publish-record.d.ts +66 -0
  199. package/dist/lifecycle/publish-record.d.ts.map +1 -0
  200. package/dist/lifecycle/publish-record.js +84 -0
  201. package/dist/lifecycle/publish-targets.d.ts +45 -0
  202. package/dist/lifecycle/publish-targets.d.ts.map +1 -0
  203. package/dist/lifecycle/publish-targets.js +85 -0
  204. package/dist/lifecycle/release-cut.d.ts +154 -0
  205. package/dist/lifecycle/release-cut.d.ts.map +1 -0
  206. package/dist/lifecycle/release-cut.js +366 -0
  207. package/dist/lifecycle/release-join.d.ts +95 -0
  208. package/dist/lifecycle/release-join.d.ts.map +1 -0
  209. package/dist/lifecycle/release-join.js +139 -0
  210. package/dist/lifecycle/release-ledger.d.ts +54 -0
  211. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  212. package/dist/lifecycle/release-ledger.js +53 -20
  213. package/dist/lifecycle/release-publish.d.ts +312 -0
  214. package/dist/lifecycle/release-publish.d.ts.map +1 -0
  215. package/dist/lifecycle/release-publish.js +335 -0
  216. package/dist/lifecycle/release-revocation.d.ts +80 -0
  217. package/dist/lifecycle/release-revocation.d.ts.map +1 -0
  218. package/dist/lifecycle/release-revocation.js +123 -0
  219. package/dist/lifecycle/release-store.d.ts +200 -0
  220. package/dist/lifecycle/release-store.d.ts.map +1 -0
  221. package/dist/lifecycle/release-store.js +320 -0
  222. package/dist/lifecycle/release-verify.d.ts +61 -0
  223. package/dist/lifecycle/release-verify.d.ts.map +1 -0
  224. package/dist/lifecycle/release-verify.js +92 -0
  225. package/dist/lifecycle/release-workstation.d.ts +91 -0
  226. package/dist/lifecycle/release-workstation.d.ts.map +1 -0
  227. package/dist/lifecycle/release-workstation.js +180 -0
  228. package/dist/lifecycle/retention-policy.d.ts +45 -0
  229. package/dist/lifecycle/retention-policy.d.ts.map +1 -0
  230. package/dist/lifecycle/retention-policy.js +43 -0
  231. package/dist/lifecycle/retention.d.ts +185 -0
  232. package/dist/lifecycle/retention.d.ts.map +1 -0
  233. package/dist/lifecycle/retention.js +400 -0
  234. package/dist/lifecycle/run-ledger.d.ts +4 -0
  235. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  236. package/dist/lifecycle/run-ledger.js +2 -0
  237. package/dist/op/activities/change-coverage.d.ts.map +1 -1
  238. package/dist/op/activities/change-coverage.js +4 -2
  239. package/dist/op/activities/source-release.d.ts.map +1 -1
  240. package/dist/op/activities/source-release.js +7 -3
  241. package/dist/op/activities/source-rollback.d.ts.map +1 -1
  242. package/dist/op/activities/source-rollback.js +7 -3
  243. package/dist/op/gate-name.d.ts +11 -2
  244. package/dist/op/gate-name.d.ts.map +1 -1
  245. package/dist/op/gate-name.js +12 -3
  246. package/dist/op/gate-run-locator.d.ts +22 -0
  247. package/dist/op/gate-run-locator.d.ts.map +1 -1
  248. package/dist/op/gate-run-locator.js +31 -0
  249. package/dist/op/gate.d.ts +27 -3
  250. package/dist/op/gate.d.ts.map +1 -1
  251. package/dist/op/gate.js +57 -3
  252. package/dist/op/local-executor.d.ts +36 -1
  253. package/dist/op/local-executor.d.ts.map +1 -1
  254. package/dist/op/local-executor.js +158 -52
  255. package/dist/op/op-waves-run.d.ts.map +1 -1
  256. package/dist/op/op-waves-run.js +4 -0
  257. package/dist/op/run-live.d.ts +2 -0
  258. package/dist/op/run-live.d.ts.map +1 -1
  259. package/dist/op/run-live.js +1 -1
  260. package/dist/op/runtime.d.ts +46 -0
  261. package/dist/op/runtime.d.ts.map +1 -1
  262. package/dist/op/runtimes/local.d.ts.map +1 -1
  263. package/dist/op/runtimes/local.js +8 -0
  264. package/dist/plan-summary.d.ts.map +1 -1
  265. package/dist/plan-summary.js +8 -2
  266. package/dist/point-decision.d.ts +2 -0
  267. package/dist/point-decision.d.ts.map +1 -1
  268. package/dist/point-decision.js +9 -2
  269. package/dist/pr-loop.d.ts +7 -0
  270. package/dist/pr-loop.d.ts.map +1 -1
  271. package/dist/pr-loop.js +23 -4
  272. package/dist/pr-report-url.d.ts +82 -0
  273. package/dist/pr-report-url.d.ts.map +1 -0
  274. package/dist/pr-report-url.js +174 -0
  275. package/dist/provenance.d.ts +2 -2
  276. package/dist/provenance.d.ts.map +1 -1
  277. package/dist/run-event-store.d.ts +104 -0
  278. package/dist/run-event-store.d.ts.map +1 -0
  279. package/dist/run-event-store.js +251 -0
  280. package/dist/run-event-stream.d.ts +133 -0
  281. package/dist/run-event-stream.d.ts.map +1 -0
  282. package/dist/run-event-stream.js +242 -0
  283. package/dist/run-event.d.ts +285 -0
  284. package/dist/run-event.d.ts.map +1 -0
  285. package/dist/run-event.js +209 -0
  286. package/dist/wave-runtime.mjs +262 -226
  287. package/dist/workspace/__fixtures__/flag-workspace.d.ts +31 -0
  288. package/dist/workspace/__fixtures__/flag-workspace.d.ts.map +1 -0
  289. package/dist/workspace/__fixtures__/flag-workspace.js +114 -0
  290. package/dist/workspace/__fixtures__/run-event-check.d.ts +19 -0
  291. package/dist/workspace/__fixtures__/run-event-check.d.ts.map +1 -0
  292. package/dist/workspace/__fixtures__/run-event-check.js +59 -0
  293. package/dist/workspace/change-set-show.d.ts +56 -0
  294. package/dist/workspace/change-set-show.d.ts.map +1 -0
  295. package/dist/workspace/change-set-show.js +54 -0
  296. package/dist/workspace/change-set-show.schema.json +102 -0
  297. package/dist/workspace/change-set.schema.json +32 -1
  298. package/dist/workspace/changes-cli.d.ts.map +1 -1
  299. package/dist/workspace/changes-cli.js +10 -1
  300. package/dist/workspace/changes.d.ts +37 -0
  301. package/dist/workspace/changes.d.ts.map +1 -1
  302. package/dist/workspace/changes.js +49 -2
  303. package/dist/workspace/changes.schema.json +135 -0
  304. package/dist/workspace/check.schema.json +4 -2
  305. package/dist/workspace/checks/records.d.ts +9 -1
  306. package/dist/workspace/checks/records.d.ts.map +1 -1
  307. package/dist/workspace/checks/records.js +35 -1
  308. package/dist/workspace/checks.d.ts +1 -0
  309. package/dist/workspace/checks.d.ts.map +1 -1
  310. package/dist/workspace/checks.js +2 -1
  311. package/dist/workspace/ci-green-cli.d.ts +19 -4
  312. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  313. package/dist/workspace/ci-green-cli.js +75 -12
  314. package/dist/workspace/ci-green-forge.d.ts +20 -3
  315. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  316. package/dist/workspace/ci-green-forge.js +6 -4
  317. package/dist/workspace/ci-green-workflow.d.ts +11 -0
  318. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  319. package/dist/workspace/ci-green-workflow.js +6 -0
  320. package/dist/workspace/ci-green.d.ts +281 -13
  321. package/dist/workspace/ci-green.d.ts.map +1 -1
  322. package/dist/workspace/ci-green.js +456 -38
  323. package/dist/workspace/ci-last-green.schema.json +32 -2
  324. package/dist/workspace/ci-list.schema.json +525 -0
  325. package/dist/workspace/commit-links.d.ts +85 -0
  326. package/dist/workspace/commit-links.d.ts.map +1 -0
  327. package/dist/workspace/commit-links.js +163 -0
  328. package/dist/workspace/declaration.d.ts +35 -0
  329. package/dist/workspace/declaration.d.ts.map +1 -1
  330. package/dist/workspace/declaration.js +27 -1
  331. package/dist/workspace/declaration.schema.json +76 -0
  332. package/dist/workspace/declared-kinds.d.ts +16 -0
  333. package/dist/workspace/declared-kinds.d.ts.map +1 -1
  334. package/dist/workspace/declared-kinds.js +25 -0
  335. package/dist/workspace/delivery-metrics.d.ts +91 -0
  336. package/dist/workspace/delivery-metrics.d.ts.map +1 -0
  337. package/dist/workspace/delivery-metrics.js +217 -0
  338. package/dist/workspace/delivery-metrics.schema.json +519 -0
  339. package/dist/workspace/flags-read.d.ts +37 -0
  340. package/dist/workspace/flags-read.d.ts.map +1 -0
  341. package/dist/workspace/flags-read.js +103 -0
  342. package/dist/workspace/flags.d.ts +100 -0
  343. package/dist/workspace/flags.d.ts.map +1 -0
  344. package/dist/workspace/flags.js +98 -0
  345. package/dist/workspace/graph-cli.js +1 -1
  346. package/dist/workspace/identity-gate-rule.d.ts +37 -0
  347. package/dist/workspace/identity-gate-rule.d.ts.map +1 -1
  348. package/dist/workspace/identity-gate-rule.js +72 -7
  349. package/dist/workspace/identity.d.ts +12 -0
  350. package/dist/workspace/identity.d.ts.map +1 -1
  351. package/dist/workspace/identity.js +13 -1
  352. package/dist/workspace/intent-cli.d.ts +11 -2
  353. package/dist/workspace/intent-cli.d.ts.map +1 -1
  354. package/dist/workspace/intent-cli.js +54 -5
  355. package/dist/workspace/intent-trace.d.ts +219 -0
  356. package/dist/workspace/intent-trace.d.ts.map +1 -0
  357. package/dist/workspace/intent-trace.js +314 -0
  358. package/dist/workspace/intent.d.ts +36 -7
  359. package/dist/workspace/intent.d.ts.map +1 -1
  360. package/dist/workspace/intent.js +192 -22
  361. package/dist/workspace/intent.schema.json +702 -6
  362. package/dist/workspace/ls.d.ts +4 -0
  363. package/dist/workspace/ls.d.ts.map +1 -1
  364. package/dist/workspace/ls.js +2 -0
  365. package/dist/workspace/ls.schema.json +3 -1
  366. package/dist/workspace/member-pipeline.d.ts +6 -0
  367. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  368. package/dist/workspace/member-pipeline.js +6 -0
  369. package/dist/workspace/overlap.d.ts +146 -0
  370. package/dist/workspace/overlap.d.ts.map +1 -0
  371. package/dist/workspace/overlap.js +276 -0
  372. package/dist/workspace/promotion-order.d.ts +41 -0
  373. package/dist/workspace/promotion-order.d.ts.map +1 -0
  374. package/dist/workspace/promotion-order.js +95 -0
  375. package/dist/workspace/reason-codes.d.ts +4 -0
  376. package/dist/workspace/reason-codes.d.ts.map +1 -1
  377. package/dist/workspace/reason-codes.js +7 -1
  378. package/dist/workspace/records.d.ts +15 -2
  379. package/dist/workspace/records.d.ts.map +1 -1
  380. package/dist/workspace/records.js +32 -0
  381. package/dist/workspace/records.schema.json +21 -2
  382. package/dist/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  383. package/dist/workspace/reference-kinds/flag/flag.schema.json +53 -0
  384. package/dist/workspace/releases.d.ts +81 -0
  385. package/dist/workspace/releases.d.ts.map +1 -0
  386. package/dist/workspace/releases.js +103 -0
  387. package/dist/workspace/releases.schema.json +513 -0
  388. package/dist/workspace/run-event.schema.json +295 -0
  389. package/dist/workspace/status-gates.d.ts +34 -1
  390. package/dist/workspace/status-gates.d.ts.map +1 -1
  391. package/dist/workspace/status-gates.js +31 -2
  392. package/dist/workspace/status-stewards.d.ts +4 -0
  393. package/dist/workspace/status-stewards.d.ts.map +1 -1
  394. package/dist/workspace/status-stewards.js +2 -0
  395. package/dist/workspace/status.d.ts +117 -0
  396. package/dist/workspace/status.d.ts.map +1 -1
  397. package/dist/workspace/status.js +218 -4
  398. package/dist/workspace/status.schema.json +268 -2
  399. package/dist/workspace/trust/ci-tag-statement.d.ts +102 -0
  400. package/dist/workspace/trust/ci-tag-statement.d.ts.map +1 -0
  401. package/dist/workspace/trust/ci-tag-statement.js +123 -0
  402. package/dist/workspace/trust/op-run-statement.d.ts +91 -0
  403. package/dist/workspace/trust/op-run-statement.d.ts.map +1 -0
  404. package/dist/workspace/trust/op-run-statement.js +143 -0
  405. package/dist/workspace/trust/rotation.d.ts +18 -2
  406. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  407. package/dist/workspace/trust/rotation.js +65 -16
  408. package/dist/workspace/trust/seal.d.ts +11 -0
  409. package/dist/workspace/trust/seal.d.ts.map +1 -1
  410. package/dist/workspace/trust/seal.js +9 -0
  411. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
  412. package/dist/workspace/trust/ssh-commit.js +10 -10
  413. package/dist/workspace/wip.d.ts.map +1 -1
  414. package/dist/workspace/wip.js +11 -3
  415. package/package.json +1 -1
  416. package/src/__golden__/wave-loop/fan-out-gated.json +8 -0
  417. package/src/__golden__/wave-loop/fan-out-no-members.json +4 -0
  418. package/src/__golden__/wave-loop/fan-out-only.json +6 -0
  419. package/src/__golden__/wave-loop/op-by-apply-hold.json +2 -0
  420. package/src/__golden__/wave-loop/op-cost-member.json +3 -0
  421. package/src/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
  422. package/src/__golden__/wave-loop/op-held-on.json +2 -0
  423. package/src/__golden__/wave-loop/op-hooks-held.json +2 -0
  424. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
  425. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
  426. package/src/__golden__/wave-loop/op-hooks-share.json +3 -0
  427. package/src/__golden__/wave-loop/op-per-run.json +7 -0
  428. package/src/__golden__/wave-loop/op-pr-review.json +7 -0
  429. package/src/__golden__/wave-loop/op-sealed.json +3 -0
  430. package/src/__golden__/wave-loop/op-spend.json +3 -0
  431. package/src/__golden__/wave-loop/op-wave-commands.json +7 -0
  432. package/src/__golden__/wave-loop/op-wide-waiting.json +4 -0
  433. package/src/build-params.test.ts +46 -0
  434. package/src/build-params.ts +55 -1
  435. package/src/change-set-graph.test.ts +72 -0
  436. package/src/change-set-graph.ts +141 -0
  437. package/src/change-set.ts +87 -6
  438. package/src/chant-version.ts +16 -0
  439. package/src/cli/build-params-cli.ts +22 -9
  440. package/src/cli/commands/build.ts +25 -11
  441. package/src/cli/commands/check-lexicon-docs.test.ts +51 -0
  442. package/src/cli/commands/check-lexicon-docs.ts +39 -2
  443. package/src/cli/commands/check-lexicon.ts +14 -2
  444. package/src/cli/commands/init-lexicon/templates/docs.ts +7 -6
  445. package/src/cli/commands/init-lexicon.test.ts +25 -0
  446. package/src/cli/commands/init-lexicon.ts +18 -8
  447. package/src/cli/handlers/approve-release.test.ts +84 -0
  448. package/src/cli/handlers/approve-revoked.test.ts +155 -0
  449. package/src/cli/handlers/approve.ts +65 -2
  450. package/src/cli/handlers/build.test.ts +67 -0
  451. package/src/cli/handlers/build.ts +46 -4
  452. package/src/cli/handlers/change-set.ts +49 -1
  453. package/src/cli/handlers/fan-out.test.ts +228 -1
  454. package/src/cli/handlers/fan-out.ts +53 -6
  455. package/src/cli/handlers/intent-trace.e2e.test.ts +201 -0
  456. package/src/cli/handlers/lifecycle-gc.test.ts +126 -0
  457. package/src/cli/handlers/lifecycle-gc.ts +146 -0
  458. package/src/cli/handlers/operator.test.ts +37 -0
  459. package/src/cli/handlers/pr.test.ts +341 -0
  460. package/src/cli/handlers/pr.ts +292 -47
  461. package/src/cli/handlers/promote.test.ts +669 -7
  462. package/src/cli/handlers/promote.ts +464 -29
  463. package/src/cli/handlers/release-implicit.e2e.test.ts +161 -0
  464. package/src/cli/handlers/release-join.e2e.test.ts +185 -0
  465. package/src/cli/handlers/release-publish-targets.e2e.test.ts +295 -0
  466. package/src/cli/handlers/release-verify.e2e.test.ts +117 -0
  467. package/src/cli/handlers/release-workstation-ci.e2e.test.ts +135 -0
  468. package/src/cli/handlers/release.e2e.test.ts +199 -0
  469. package/src/cli/handlers/release.ts +593 -0
  470. package/src/cli/handlers/run-auto-release.test.ts +80 -0
  471. package/src/cli/handlers/run-events-cmd.test.ts +92 -0
  472. package/src/cli/handlers/run-release.test.ts +55 -0
  473. package/src/cli/handlers/run.test.ts +30 -0
  474. package/src/cli/handlers/run.ts +243 -18
  475. package/src/cli/main.test.ts +8 -0
  476. package/src/cli/main.ts +143 -17
  477. package/src/cli/mcp/never-over-mcp.test.ts +2 -0
  478. package/src/cli/mcp/workspace-tools.ts +1 -1
  479. package/src/cli/parse-args.ts +56 -5
  480. package/src/cli/registry.ts +43 -5
  481. package/src/cli/run-events.ts +57 -0
  482. package/src/cli/version.ts +3 -13
  483. package/src/codegen/docs-in-site.test.ts +166 -0
  484. package/src/codegen/docs-in-site.ts +182 -0
  485. package/src/codegen/docs-site/AgentPrompt.astro +26 -1
  486. package/src/codegen/docs-types.ts +14 -1
  487. package/src/codegen/docs.ts +60 -7
  488. package/src/codegen/rehype-base-url.d.mts +3 -1
  489. package/src/codegen/rehype-base-url.mjs +15 -9
  490. package/src/codegen/rehype-base-url.test.ts +34 -0
  491. package/src/components/auto-release.test.ts +30 -0
  492. package/src/components/auto-release.ts +9 -1
  493. package/src/components/capability.ts +9 -0
  494. package/src/components/cli-support.test.ts +82 -0
  495. package/src/components/cli-support.ts +16 -9
  496. package/src/components/driver.test.ts +24 -0
  497. package/src/components/driver.ts +165 -56
  498. package/src/components/fan-out-inputs.test.ts +85 -0
  499. package/src/components/fan-out-inputs.ts +192 -0
  500. package/src/components/fan-out-record.test.ts +10 -0
  501. package/src/components/fan-out-record.ts +19 -0
  502. package/src/components/fan-out-run.ts +104 -35
  503. package/src/components/fan-out.ts +4 -0
  504. package/src/components/pr-pipeline.ts +35 -4
  505. package/src/components/pr-run.ts +30 -1
  506. package/src/components/promote-order.test.ts +90 -0
  507. package/src/components/promote-order.ts +75 -0
  508. package/src/components/promote.test.ts +10 -1
  509. package/src/components/promote.ts +94 -3
  510. package/src/components/release-compile.test.ts +147 -0
  511. package/src/components/release-compile.ts +459 -0
  512. package/src/components/release-gate.test.ts +215 -0
  513. package/src/components/release-gate.ts +355 -0
  514. package/src/components/release-promote.test.ts +159 -0
  515. package/src/components/release-promote.ts +232 -0
  516. package/src/components/run-progress.ts +7 -0
  517. package/src/components/wave-plan.ts +16 -3
  518. package/src/config.ts +15 -1
  519. package/src/flag-params.test.ts +144 -0
  520. package/src/flag-params.ts +134 -0
  521. package/src/index.ts +2 -0
  522. package/src/lifecycle/__fixtures__/publish-fakes.ts +351 -0
  523. package/src/lifecycle/change-set-store.test.ts +217 -0
  524. package/src/lifecycle/change-set-store.ts +113 -0
  525. package/src/lifecycle/commit-sha.ts +23 -0
  526. package/src/lifecycle/delivery-metrics.ts +263 -0
  527. package/src/lifecycle/deploy-outcome.ts +147 -0
  528. package/src/lifecycle/gate-change-set.e2e.test.ts +122 -0
  529. package/src/lifecycle/gate-change-set.ts +164 -0
  530. package/src/lifecycle/gate-ledger.test.ts +33 -0
  531. package/src/lifecycle/gate-ledger.ts +68 -3
  532. package/src/lifecycle/git.ts +61 -8
  533. package/src/lifecycle/index.ts +4 -0
  534. package/src/lifecycle/mixed-environment.test.ts +97 -0
  535. package/src/lifecycle/mixed-environment.ts +204 -0
  536. package/src/lifecycle/publish-attachments.ts +196 -0
  537. package/src/lifecycle/publish-credentials.ts +84 -0
  538. package/src/lifecycle/publish-declaration.ts +95 -0
  539. package/src/lifecycle/publish-forge.ts +325 -0
  540. package/src/lifecycle/publish-npm.ts +259 -0
  541. package/src/lifecycle/publish-oci.ts +396 -0
  542. package/src/lifecycle/publish-record.ts +113 -0
  543. package/src/lifecycle/publish-resume.test.ts +168 -0
  544. package/src/lifecycle/publish-targets.test.ts +494 -0
  545. package/src/lifecycle/publish-targets.ts +100 -0
  546. package/src/lifecycle/release-cut-signed.test.ts +180 -0
  547. package/src/lifecycle/release-cut.test.ts +483 -0
  548. package/src/lifecycle/release-cut.ts +503 -0
  549. package/src/lifecycle/release-flag.test.ts +112 -0
  550. package/src/lifecycle/release-join.test.ts +68 -0
  551. package/src/lifecycle/release-join.ts +182 -0
  552. package/src/lifecycle/release-ledger.test.ts +14 -0
  553. package/src/lifecycle/release-ledger.ts +85 -17
  554. package/src/lifecycle/release-publish.test.ts +225 -0
  555. package/src/lifecycle/release-publish.ts +568 -0
  556. package/src/lifecycle/release-revocation.ts +147 -0
  557. package/src/lifecycle/release-store.ts +434 -0
  558. package/src/lifecycle/release-verify.test.ts +110 -0
  559. package/src/lifecycle/release-verify.ts +120 -0
  560. package/src/lifecycle/release-workstation.test.ts +204 -0
  561. package/src/lifecycle/release-workstation.ts +216 -0
  562. package/src/lifecycle/retention-growth.e2e.test.ts +279 -0
  563. package/src/lifecycle/retention-policy.ts +63 -0
  564. package/src/lifecycle/retention.test.ts +363 -0
  565. package/src/lifecycle/retention.ts +508 -0
  566. package/src/lifecycle/run-ledger.test.ts +10 -0
  567. package/src/lifecycle/run-ledger.ts +6 -0
  568. package/src/op/activities/change-coverage.ts +4 -1
  569. package/src/op/activities/source-release.ts +8 -3
  570. package/src/op/activities/source-rollback.ts +8 -4
  571. package/src/op/commit-run-gate-deploy-join.test.ts +117 -0
  572. package/src/op/gate-name.ts +13 -3
  573. package/src/op/gate-release.test.ts +126 -0
  574. package/src/op/gate-run-locator.test.ts +110 -0
  575. package/src/op/gate-run-locator.ts +35 -0
  576. package/src/op/gate.ts +88 -6
  577. package/src/op/local-executor.ts +207 -52
  578. package/src/op/op-waves-run.ts +4 -0
  579. package/src/op/run-events.test.ts +166 -0
  580. package/src/op/run-live.ts +1 -1
  581. package/src/op/runtime.ts +39 -0
  582. package/src/op/runtimes/local.test.ts +16 -0
  583. package/src/op/runtimes/local.ts +9 -0
  584. package/src/plan-summary.test.ts +20 -0
  585. package/src/plan-summary.ts +8 -1
  586. package/src/point-decision.ts +12 -2
  587. package/src/pr-loop.ts +25 -4
  588. package/src/pr-report-url.test.ts +131 -0
  589. package/src/pr-report-url.ts +209 -0
  590. package/src/provenance.ts +2 -2
  591. package/src/run-event-store.test.ts +144 -0
  592. package/src/run-event-store.ts +273 -0
  593. package/src/run-event-stream.test.ts +175 -0
  594. package/src/run-event-stream.ts +309 -0
  595. package/src/run-event.test.ts +277 -0
  596. package/src/run-event.ts +471 -0
  597. package/src/wave-loop-golden.test.ts +9 -0
  598. package/src/workspace/__fixtures__/flag-workspace.ts +132 -0
  599. package/src/workspace/__fixtures__/older-records/change-set-984534ea9.json +100 -0
  600. package/src/workspace/__fixtures__/older-records/older-records.json +326 -0
  601. package/src/workspace/__fixtures__/run-event-check.ts +58 -0
  602. package/src/workspace/ancestry-index.test.ts +93 -0
  603. package/src/workspace/change-set-show.schema.json +102 -0
  604. package/src/workspace/change-set-show.ts +72 -0
  605. package/src/workspace/change-set.schema.json +32 -1
  606. package/src/workspace/changes-cli.ts +10 -1
  607. package/src/workspace/changes.schema.json +135 -0
  608. package/src/workspace/changes.test.ts +1 -1
  609. package/src/workspace/changes.ts +84 -2
  610. package/src/workspace/check.schema.json +4 -2
  611. package/src/workspace/checks/records.ts +35 -1
  612. package/src/workspace/checks.ts +2 -1
  613. package/src/workspace/ci-green-cli.ts +75 -13
  614. package/src/workspace/ci-green-forge.ts +24 -4
  615. package/src/workspace/ci-green-runs.test.ts +242 -0
  616. package/src/workspace/ci-green-signed.test.ts +302 -0
  617. package/src/workspace/ci-green-workflow.test.ts +16 -0
  618. package/src/workspace/ci-green-workflow.ts +12 -0
  619. package/src/workspace/ci-green.test.ts +131 -2
  620. package/src/workspace/ci-green.ts +635 -42
  621. package/src/workspace/ci-last-green.schema.json +32 -2
  622. package/src/workspace/ci-list.schema.json +525 -0
  623. package/src/workspace/commit-links.test.ts +279 -0
  624. package/src/workspace/commit-links.ts +183 -0
  625. package/src/workspace/declaration.schema.json +76 -0
  626. package/src/workspace/declaration.test.ts +28 -0
  627. package/src/workspace/declaration.ts +60 -2
  628. package/src/workspace/declared-kinds.ts +40 -1
  629. package/src/workspace/delivery-metrics.schema.json +519 -0
  630. package/src/workspace/delivery-metrics.test.ts +236 -0
  631. package/src/workspace/delivery-metrics.ts +286 -0
  632. package/src/workspace/flags-read.ts +121 -0
  633. package/src/workspace/flags.test.ts +141 -0
  634. package/src/workspace/flags.ts +157 -0
  635. package/src/workspace/graph-cli.ts +1 -1
  636. package/src/workspace/identity-gate-rule.ts +91 -7
  637. package/src/workspace/identity.ts +14 -1
  638. package/src/workspace/intent-cli.ts +46 -5
  639. package/src/workspace/intent-trace.test.ts +173 -0
  640. package/src/workspace/intent-trace.ts +484 -0
  641. package/src/workspace/intent.schema.json +702 -6
  642. package/src/workspace/intent.ts +196 -26
  643. package/src/workspace/ls.schema.json +3 -1
  644. package/src/workspace/ls.ts +6 -0
  645. package/src/workspace/member-pipeline.test.ts +17 -0
  646. package/src/workspace/member-pipeline.ts +9 -0
  647. package/src/workspace/older-records.test.ts +412 -0
  648. package/src/workspace/overlap.test.ts +165 -0
  649. package/src/workspace/overlap.ts +340 -0
  650. package/src/workspace/promotion-order.ts +97 -0
  651. package/src/workspace/read-contract.e2e.test.ts +5 -1
  652. package/src/workspace/reason-codes.test.ts +7 -1
  653. package/src/workspace/reason-codes.ts +7 -1
  654. package/src/workspace/record-assets.test.ts +2 -1
  655. package/src/workspace/records-contract.e2e.test.ts +2 -1
  656. package/src/workspace/records.schema.json +21 -2
  657. package/src/workspace/records.ts +36 -2
  658. package/src/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  659. package/src/workspace/reference-kinds/flag/flag.schema.json +53 -0
  660. package/src/workspace/releases.schema.json +513 -0
  661. package/src/workspace/releases.test.ts +108 -0
  662. package/src/workspace/releases.ts +133 -0
  663. package/src/workspace/run-event.schema.json +295 -0
  664. package/src/workspace/status-contract.test.ts +81 -1
  665. package/src/workspace/status-gates.ts +64 -1
  666. package/src/workspace/status-mixed.test.ts +152 -0
  667. package/src/workspace/status-revoked.test.ts +153 -0
  668. package/src/workspace/status-stewards.ts +6 -0
  669. package/src/workspace/status.schema.json +268 -2
  670. package/src/workspace/status.ts +334 -4
  671. package/src/workspace/trust/ci-tag-statement.ts +151 -0
  672. package/src/workspace/trust/op-run-statement.ts +148 -0
  673. package/src/workspace/trust/rotation.ts +61 -14
  674. package/src/workspace/trust/seal.ts +10 -0
  675. package/src/workspace/trust/ssh-commit.ts +10 -9
  676. package/src/workspace/wip.ts +11 -2
  677. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +0 -14
  678. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +0 -16
  679. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +0 -8
  680. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +0 -15
  681. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +0 -10
@@ -56,7 +56,9 @@ import type { PendingGateRecord } from "../lifecycle/gate-ledger";
56
56
  import type { CapabilityRegistry, DeployContext } from "./capability";
57
57
  import { isPromotedArtifact } from "./auto-release";
58
58
  import type { ReleaseIdentity } from "../telemetry-attribution";
59
- import type { RunProgressEvent, RunProgressStatus } from "./run-progress";
59
+ import type { RunProgressEvent } from "./run-progress";
60
+ import type { RunEventSettleStatus } from "../run-event";
61
+ import { gateEventsOf, joinRunEventSinks, progressSinkOf, type RunEventSink } from "../run-event-stream";
60
62
 
61
63
  export type { RunProgressEvent } from "./run-progress";
62
64
 
@@ -153,7 +155,16 @@ export interface DriverStepRecord {
153
155
  output?: unknown;
154
156
  error?: string;
155
157
  /** Set on a `gate` step that passed (#2119): who resolved it, when, and at what address. */
156
- approval?: { gate: string; resolvedBy: string; timestamp: string; url?: string };
158
+ approval?: {
159
+ gate: string;
160
+ resolvedBy: string;
161
+ timestamp: string;
162
+ url?: string;
163
+ /** The gate ledger the approval is in, when it isn't the component's own: a release gate's (#4045). */
164
+ op?: string;
165
+ /** Set when the gate passed over an empty change set (#4045) rather than on a person's approval. */
166
+ empty?: true;
167
+ };
157
168
  }
158
169
 
159
170
  export interface DriverComponentResult {
@@ -334,6 +345,42 @@ export function resolveStepInput(
334
345
  return walk(input) as Record<string, unknown>;
335
346
  }
336
347
 
348
+ /**
349
+ * The components (or stacks) whose outputs `input` reads through
350
+ * cross-component wiring, `stackOutput()` or `@<component>.publish.*`, and
351
+ * which have no value for it in `componentOutputs`, sorted and each once
352
+ * (#4084). {@link resolveStepInput} turns each such reference into
353
+ * `undefined`; a plan uses this to say whose outputs it is waiting on.
354
+ */
355
+ export function unresolvedWiringSources(
356
+ input: Record<string, unknown>,
357
+ componentOutputs: Record<string, Record<string, unknown>>,
358
+ ): string[] {
359
+ const found = new Set<string>();
360
+ const walk = (value: unknown): void => {
361
+ if (typeof value === "string") {
362
+ if (PRIOR_STEP_REF.test(value)) return;
363
+ const ref = value.match(COMPONENT_ARTIFACT_REF);
364
+ if (ref && resolvePath(componentOutputs[ref[1]]?.publish, ref[2]) === undefined) found.add(ref[1]);
365
+ return;
366
+ }
367
+ if (Array.isArray(value)) {
368
+ value.forEach(walk);
369
+ return;
370
+ }
371
+ if (value && typeof value === "object") {
372
+ if ("stackOutput" in value) {
373
+ const { stack, name } = (value as { stackOutput: { stack: string; name: string } }).stackOutput;
374
+ if (resolvePath(componentOutputs[stack], name) === undefined) found.add(stack);
375
+ return;
376
+ }
377
+ Object.values(value as Record<string, unknown>).forEach(walk);
378
+ }
379
+ };
380
+ walk(input);
381
+ return [...found].sort();
382
+ }
383
+
337
384
  // ── Step + phase execution ───────────────────────────────────────────────
338
385
 
339
386
  /**
@@ -378,8 +425,8 @@ class GateStop extends Error {
378
425
  }
379
426
  }
380
427
 
381
- /** A result status as the progress stream spells it — the only difference is `fail` vs `failed`, which the two vocabularies have always disagreed on. */
382
- function progressStatus(status: DriverComponentResult["status"]): RunProgressStatus {
428
+ /** A result status as the event stream spells it — the only difference is `fail` vs `failed`, which the two vocabularies have always disagreed on. */
429
+ function progressStatus(status: DriverComponentResult["status"]): RunEventSettleStatus {
383
430
  return status === "fail" ? "failed" : status;
384
431
  }
385
432
 
@@ -395,6 +442,27 @@ export interface GateContext {
395
442
  releases?: ReadonlyMap<string, string>;
396
443
  /** This component's plan digest. Set by {@link runComponentDeploy}, never by a caller. */
397
444
  planDigest?: string;
445
+ /**
446
+ * The release gate binding (#4045): set by a promote under a release.
447
+ * Every gate the run reaches is then decided in `op`'s ledger against the
448
+ * change-set document's digest, the release and the environment, in place
449
+ * of the component's own ledger and composition digest.
450
+ */
451
+ releaseGate?: ReleaseGateBinding;
452
+ }
453
+
454
+ /**
455
+ * What a release gate binds (#4045, ws-104 question 2): the change-set
456
+ * document's digest, the release, and (from the run) the environment.
457
+ */
458
+ export interface ReleaseGateBinding {
459
+ /** The gate ledger the release gate is recorded in, for every component of the promote. */
460
+ op: string;
461
+ /** The digest of the change-set document planned for this release and environment. */
462
+ planDigest: string;
463
+ releaseDigest: string;
464
+ /** Reads the document stored under a digest and says whether it is empty (`evaluateGate`'s `verifyEmpty`). */
465
+ verifyEmpty?: (planDigest: string) => Promise<boolean>;
398
466
  }
399
467
 
400
468
  /** Run a single capability step. Never throws for a capability-run failure; returns a fail record instead. */
@@ -451,14 +519,16 @@ async function runCapabilityStep(
451
519
  * gate is a read of the ledger rather than work, and starting activities a
452
520
  * pending gate is about to strand defeats the point of stopping at it.
453
521
  *
454
- * `onProgress`, when supplied, is called with a `phase-start` event before any
455
- * step runs, a `step` event around each capability invocation (`"running"`
456
- * then `"ok"`/`"failed"`), and a `phase-done` event once the phase settles —
457
- * purely additive observation, never consulted for control flow. Recursion
458
- * into a nested fan-out phase passes the same callback through, so a nested
459
- * phase's events use its own name. Left `undefined` by every caller that
460
- * doesn't opt into `--progress-json` (see ./run-progress.ts), in which case
461
- * every `onProgress?.(...)` call below is a no-op and behavior is unchanged.
522
+ * `emit`, when supplied, gets the phase's run events (#4041): `phase-start`
523
+ * before any step runs, a `step-start` and a `step-settle` around each gate
524
+ * and each capability invocation, the gate's `gate-resolved` or
525
+ * `gate-waiting`, a `skipped` settle with `skip: "not-run"` for each step a
526
+ * failure or a gate stopped, and `phase-settle` once the phase settles. It
527
+ * is observation only, never consulted for control flow. Recursion into a
528
+ * nested fan-out phase passes the same sink through, so a nested phase's
529
+ * events use its own name. `--progress-json` reads the same events through
530
+ * `progressOfRunEvent` (../run-event-stream.ts), which keeps the older
531
+ * stream's shape.
462
532
  */
463
533
  async function runPhase(
464
534
  phaseDef: DriverPhase,
@@ -467,22 +537,34 @@ async function runPhase(
467
537
  phaseOutputs: Record<string, Record<string, unknown>>,
468
538
  componentOutputs: Record<string, Record<string, unknown>>,
469
539
  gates: GateContext,
470
- onProgress?: (event: RunProgressEvent) => void,
540
+ emit?: RunEventSink,
471
541
  ): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[] }> {
542
+ /** Where a step of this phase sits, for its events. */
543
+ const stepAt = (entry: DriverStep | DriverGate | DriverPhase, step: string) => ({
544
+ component: ctx.component,
545
+ phase: phaseDef.phase,
546
+ step,
547
+ index: phaseDef.steps.indexOf(entry),
548
+ });
472
549
  /** Decide this phase's gates against the ledger, in authored order, before any of its work starts. Throws `GateStop` at the first one nobody has approved. */
473
550
  const decideGates = async (): Promise<DriverStepRecord[]> => {
474
551
  const gateRecords: DriverStepRecord[] = [];
475
552
  for (const gate of phaseDef.steps.filter(isGateStep)) {
476
553
  const start = Date.now();
477
554
  const base = { component: ctx.component, phase: phaseDef.phase, kind: `gate:${gateName(gate)}` };
555
+ const at = stepAt(gate, base.kind);
556
+ emit?.({ type: "step-start", ...at });
478
557
  let check: Awaited<ReturnType<typeof evaluateGate>>;
479
558
  try {
480
559
  check = await evaluateGate(gates.port, {
481
- op: ctx.component,
560
+ op: gates.releaseGate?.op ?? ctx.component,
482
561
  gate: gateName(gate),
483
562
  // #2574: an approval counts only for this environment and this plan.
484
563
  environment: ctx.env,
485
564
  ...(gates.planDigest !== undefined ? { planDigest: gates.planDigest } : {}),
565
+ // #4045: and under a release, only for that release.
566
+ ...(gates.releaseGate ? { releaseDigest: gates.releaseGate.releaseDigest } : {}),
567
+ ...(gates.releaseGate?.verifyEmpty ? { verifyEmpty: gates.releaseGate.verifyEmpty } : {}),
486
568
  ...(gate.description ? { description: gate.description } : {}),
487
569
  ...(gate.timeout ? { timeout: gate.timeout } : {}),
488
570
  ...(gates.now ? { now: gates.now } : {}),
@@ -492,11 +574,22 @@ async function runPhase(
492
574
  // executor's gate step does, and the component unwinds like any failure.
493
575
  if (!(err instanceof GateNotRecordableError)) throw err;
494
576
  gateRecords.push({ ...base, status: "fail" as const, durationMs: Date.now() - start, error: err.message });
577
+ emit?.({ type: "step-settle", ...at, status: "failed", durationMs: Date.now() - start, error: err.message });
495
578
  for (const skipped of phaseDef.steps.filter((s): s is DriverStep | DriverPhase => !isGateStep(s))) {
496
579
  gateRecords.push(skippedRecord(skipped));
497
580
  }
498
581
  throw new StepFailure(gateRecords, []);
499
582
  }
583
+ for (const body of gateEventsOf(
584
+ check,
585
+ { ...at, op: gates.releaseGate?.op ?? ctx.component, gate: gateName(gate) },
586
+ {
587
+ durationMs: Date.now() - start,
588
+ ...(!check.satisfied && check.mismatch ? { message: "an approval stands for this gate, but for another environment or plan" } : {}),
589
+ },
590
+ )) {
591
+ emit?.(body);
592
+ }
500
593
  if (!check.satisfied) {
501
594
  gateRecords.push({ ...base, status: "skipped" as const, durationMs: Date.now() - start });
502
595
  for (const skipped of phaseDef.steps.filter((s): s is DriverStep | DriverPhase => !isGateStep(s))) {
@@ -513,6 +606,8 @@ async function runPhase(
513
606
  resolvedBy: check.resolution.resolvedBy,
514
607
  timestamp: check.resolution.timestamp,
515
608
  ...(check.resolution.url ? { url: check.resolution.url } : {}),
609
+ ...(gates.releaseGate ? { op: gates.releaseGate.op } : {}),
610
+ ...(check.via === "empty" ? { empty: true as const } : {}),
516
611
  },
517
612
  });
518
613
  }
@@ -534,7 +629,7 @@ async function runPhase(
534
629
  }> => {
535
630
  if (isPhaseStep(entry)) {
536
631
  try {
537
- const nested = await runPhase(entry, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
632
+ const nested = await runPhase(entry, ctx, registry, phaseOutputs, componentOutputs, gates, emit);
538
633
  return { ...nested, failed: false };
539
634
  } catch (err) {
540
635
  if (err instanceof StepFailure) return { records: err.records, executed: err.executed, failed: true };
@@ -554,7 +649,8 @@ async function runPhase(
554
649
  throw err;
555
650
  }
556
651
  }
557
- onProgress?.({ type: "step", component: ctx.component, phase: phaseDef.phase, step: entry.kind, status: "running" });
652
+ const at = stepAt(entry, entry.kind);
653
+ emit?.({ type: "step-start", ...at });
558
654
  const { record, resolvedInput, output } = await runCapabilityStep(
559
655
  entry,
560
656
  phaseDef.phase,
@@ -563,12 +659,11 @@ async function runPhase(
563
659
  phaseOutputs,
564
660
  componentOutputs,
565
661
  );
566
- onProgress?.({
567
- type: "step",
568
- component: ctx.component,
569
- phase: phaseDef.phase,
570
- step: entry.kind,
662
+ emit?.({
663
+ type: "step-settle",
664
+ ...at,
571
665
  status: record.status === "ok" ? "ok" : "failed",
666
+ durationMs: record.durationMs,
572
667
  ...(record.error !== undefined ? { error: record.error } : {}),
573
668
  });
574
669
  if (record.status === "ok") {
@@ -586,13 +681,12 @@ async function runPhase(
586
681
  };
587
682
  };
588
683
 
589
- const skippedRecord = (entry: DriverStep | DriverPhase): DriverStepRecord => ({
590
- component: ctx.component,
591
- phase: phaseDef.phase,
592
- kind: isPhaseStep(entry) ? entry.phase : (entry as DriverStep).kind,
593
- status: "skipped",
594
- durationMs: 0,
595
- });
684
+ /** A step a failure or a gate stopped before it started: recorded, and settled `skipped` with `skip: "not-run"`. */
685
+ const skippedRecord = (entry: DriverStep | DriverPhase): DriverStepRecord => {
686
+ const kind = isPhaseStep(entry) ? entry.phase : (entry as DriverStep).kind;
687
+ emit?.({ type: "step-settle", ...stepAt(entry, kind), status: "skipped", skip: "not-run", durationMs: null });
688
+ return { component: ctx.component, phase: phaseDef.phase, kind, status: "skipped", durationMs: 0 };
689
+ };
596
690
 
597
691
  const runEntries = async (): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[] }> => {
598
692
  const gateRecords = await decideGates();
@@ -626,16 +720,16 @@ async function runPhase(
626
720
  return { records, executed };
627
721
  };
628
722
 
629
- onProgress?.({ type: "phase-start", component: ctx.component, phase: phaseDef.phase });
723
+ emit?.({ type: "phase-start", component: ctx.component, phase: phaseDef.phase });
630
724
  try {
631
725
  const result = await runEntries();
632
- onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "ok" });
726
+ emit?.({ type: "phase-settle", component: ctx.component, phase: phaseDef.phase, status: "ok" });
633
727
  return result;
634
728
  } catch (err) {
635
729
  if (err instanceof GateStop) {
636
- onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "gated" });
730
+ emit?.({ type: "phase-settle", component: ctx.component, phase: phaseDef.phase, status: "gated" });
637
731
  } else if (err instanceof StepFailure) {
638
- onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "failed" });
732
+ emit?.({ type: "phase-settle", component: ctx.component, phase: phaseDef.phase, status: "failed" });
639
733
  }
640
734
  throw err;
641
735
  }
@@ -710,14 +804,14 @@ async function rollbackExecuted(
710
804
  * any) are recorded into `componentOutputs` under its own name so downstream
711
805
  * components can reference `@<name>.publish.*`.
712
806
  *
713
- * `onProgress`, when supplied, is forwarded to every `runPhase` call (both the
714
- * forward `deploy` phases and, on failure, the component's own authored
715
- * `rollback` phases) so a `--progress-json` consumer sees `phase-start`/
716
- * `step`/`phase-done` events for whichever phases actually ran. The saga
717
- * unwind step-by-step compensation (`rollbackExecuted` below) is not part of
718
- * the `RunProgressEvent` contract and stays silent — it isn't a `deploy`
719
- * phase, and its record statuses (`rolled-back`/`rollback-opted-out`) don't
720
- * map onto the `step` event's `running`/`ok`/`failed` shape.
807
+ * `onProgress` (the older `RunProgressEvent` stream) and `onRunEvent` (run
808
+ * events, #4041), when supplied, are forwarded to every `runPhase` call (both
809
+ * the forward `deploy` phases and, on failure, the component's own authored
810
+ * `rollback` phases), so a consumer sees the phase and step events of
811
+ * whichever phases actually ran. The saga unwind step-by-step compensation
812
+ * (`rollbackExecuted` below) stays silent: it isn't a `deploy` phase, and
813
+ * its record statuses (`rolled-back`/`rollback-opted-out`) are not step
814
+ * statuses either stream has.
721
815
  */
722
816
  export async function runComponentDeploy(
723
817
  component: DriverComponent,
@@ -726,7 +820,9 @@ export async function runComponentDeploy(
726
820
  componentOutputs: Record<string, Record<string, unknown>>,
727
821
  onProgress?: (event: RunProgressEvent) => void,
728
822
  gateContext: GateContext = { port: gitGateLedgerPort() },
823
+ onRunEvent?: RunEventSink,
729
824
  ): Promise<DriverComponentResult> {
825
+ const emit = joinRunEventSinks(onRunEvent, progressSinkOf(onProgress));
730
826
  // Each component tracks its own release: a digest one component promoted never stamps another's deploy.
731
827
  if (ctx.release) ctx = { ...ctx, release: { ...ctx.release } };
732
828
  const phaseOutputs: Record<string, Record<string, unknown>> = {};
@@ -738,19 +834,22 @@ export async function runComponentDeploy(
738
834
  if (ctx.release && release !== undefined && ctx.release.version === undefined) ctx.release.version = release;
739
835
  const gates: GateContext = {
740
836
  ...gateContext,
741
- planDigest: componentPlanDigest({
742
- environment: ctx.env,
743
- component,
744
- ...(ctx.vars ? { vars: ctx.vars } : {}),
745
- ...(release !== undefined ? { release } : {}),
746
- }),
837
+ // #4045: a release gate binds the release's change set, not this composition.
838
+ planDigest:
839
+ gateContext.releaseGate?.planDigest ??
840
+ componentPlanDigest({
841
+ environment: ctx.env,
842
+ component,
843
+ ...(ctx.vars ? { vars: ctx.vars } : {}),
844
+ ...(release !== undefined ? { release } : {}),
845
+ }),
747
846
  };
748
847
  const records: DriverStepRecord[] = [];
749
848
  const allExecuted: ExecutedStep[] = [];
750
849
 
751
850
  try {
752
851
  for (const phaseDef of component.deploy) {
753
- const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
852
+ const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, emit);
754
853
  records.push(...result.records);
755
854
  allExecuted.push(...result.executed);
756
855
  }
@@ -784,7 +883,7 @@ export async function runComponentDeploy(
784
883
 
785
884
  for (const phaseDef of [...(component.rollback ?? [])].reverse()) {
786
885
  try {
787
- const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
886
+ const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, emit);
788
887
  records.push(...result.records);
789
888
  } catch (compErr) {
790
889
  if (compErr instanceof StepFailure || compErr instanceof GateStop) records.push(...compErr.records);
@@ -919,12 +1018,20 @@ export interface InterpretRunOptions {
919
1018
  * byte-for-byte the same as before this option existed.
920
1019
  */
921
1020
  onProgress?: (event: RunProgressEvent) => void;
1021
+ /**
1022
+ * Where the run's events go (#4041, `chant run --components --events-json`):
1023
+ * the run-event bodies the stream in ../run-event-stream.ts stamps. Like
1024
+ * `onProgress`, never consulted for control flow.
1025
+ */
1026
+ onRunEvent?: RunEventSink;
922
1027
  /** Where a `gate` step's facts are read and written (#2119). Defaults to the `chant/lifecycle` orphan branch; a test passes `memoryGateLedgerPort()` from `../op/gate.ts`. */
923
1028
  gates?: GateLedgerPort;
924
1029
  /** ISO-8601 "now" for gate decisions, so a test is deterministic. */
925
1030
  now?: string;
926
1031
  /** The recorded digest a promote or rollback deploys, per component (#2574). Part of the plan a gate approval is bound to. */
927
1032
  releases?: ReadonlyMap<string, string>;
1033
+ /** A promote under a release (#4045): what every gate the run reaches binds. See {@link GateContext.releaseGate}. */
1034
+ releaseGate?: ReleaseGateBinding;
928
1035
  /**
929
1036
  * The release each component deploys (#3061, ws-081), threaded into its
930
1037
  * `DeployContext.release`. The driver fills in `version` when a publish
@@ -969,14 +1076,15 @@ export async function runInterpretDriver(
969
1076
  const { order, waves } = resolveComponentGraph(components);
970
1077
  const byName = new Map(components.map((c) => [c.name, c]));
971
1078
  const componentOutputs: Record<string, Record<string, unknown>> = { ...(options.componentOutputs ?? {}) };
972
- const { onProgress } = options;
1079
+ const emit = joinRunEventSinks(options.onRunEvent, progressSinkOf(options.onProgress));
973
1080
  const gates: GateContext = {
974
1081
  port: options.gates ?? gitGateLedgerPort(),
975
1082
  ...(options.now ? { now: options.now } : {}),
976
1083
  ...(options.releases ? { releases: options.releases } : {}),
1084
+ ...(options.releaseGate ? { releaseGate: options.releaseGate } : {}),
977
1085
  };
978
1086
 
979
- onProgress?.({ type: "run-start", waves });
1087
+ emit?.({ type: "run-start", waves });
980
1088
 
981
1089
  const results: DriverComponentResult[] = [];
982
1090
  let failedComponent: string | undefined;
@@ -984,26 +1092,27 @@ export async function runInterpretDriver(
984
1092
 
985
1093
  waveLoop: for (const [waveIndex, wave] of waves.entries()) {
986
1094
  const waveNum = waveIndex + 1;
987
- onProgress?.({ type: "wave-start", wave: waveNum, components: wave });
1095
+ emit?.({ type: "wave-start", wave: waveNum, components: wave });
988
1096
  const waveComponents = wave.map((name) => byName.get(name)!);
989
1097
  const waveResults = await Promise.all(
990
1098
  waveComponents.map(async (component) => {
991
- onProgress?.({ type: "component-start", wave: waveNum, component: component.name });
1099
+ emit?.({ type: "component-start", wave: waveNum, component: component.name });
992
1100
  const result = await runComponentDeploy(
993
1101
  component,
994
1102
  deployContext(options, component.name),
995
1103
  registry,
996
1104
  componentOutputs,
997
- onProgress,
1105
+ undefined,
998
1106
  gates,
1107
+ emit,
999
1108
  );
1000
- onProgress?.({ type: "component-done", wave: waveNum, component: component.name, status: progressStatus(result.status) });
1109
+ emit?.({ type: "component-settle", wave: waveNum, component: component.name, status: progressStatus(result.status) });
1001
1110
  return result;
1002
1111
  }),
1003
1112
  );
1004
1113
  results.push(...waveResults);
1005
1114
  const stopped = waveResults.find((r) => r.status !== "ok");
1006
- onProgress?.({ type: "wave-done", wave: waveNum, status: progressStatus(stopped?.status ?? "ok") });
1115
+ emit?.({ type: "wave-settle", wave: waveNum, status: progressStatus(stopped?.status ?? "ok") });
1007
1116
  if (stopped) {
1008
1117
  // A failure in the same wave outranks a gate: something is actually
1009
1118
  // broken, and reporting the run as "waiting on a human" would hide it.
@@ -1016,7 +1125,7 @@ export async function runInterpretDriver(
1016
1125
 
1017
1126
  const status: DriverRunResult["status"] = failedComponent ? "fail" : gated ? "gated" : "ok";
1018
1127
  const ok = status === "ok";
1019
- onProgress?.({ type: "run-done", status: progressStatus(status) });
1128
+ emit?.({ type: "run-settle", status: progressStatus(status), durationMs: null });
1020
1129
  const result: DriverRunResult = {
1021
1130
  order, waves, results, ok, status, failedComponent, componentOutputs,
1022
1131
  ...(gated
@@ -0,0 +1,85 @@
1
+ /**
2
+ * What each component would apply, as a digest (#4081), and which of an
3
+ * earlier attempt's progress holds against it.
4
+ */
5
+
6
+ import { describe, expect, test } from "vitest";
7
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { componentInputDigests, progressThatCarries } from "./fan-out-inputs";
11
+ import type { DriverComponent } from "./driver";
12
+
13
+ function project(): string {
14
+ const root = mkdtempSync(join(tmpdir(), "fan-out-inputs-"));
15
+ mkdirSync(join(root, "dist"));
16
+ for (const name of ["net", "cluster", "app"]) writeFileSync(join(root, "dist", `${name}.json`), `{"name":"${name}"}`);
17
+ return root;
18
+ }
19
+
20
+ const component = (name: string, dependsOn: string[] = [], extra: Record<string, unknown> = {}): DriverComponent => ({
21
+ name,
22
+ dependsOn,
23
+ deploy: [{ phase: "Apply", steps: [{ kind: "cfn-deploy", stack: name, template: `dist/${name}.json`, ...extra }] }],
24
+ });
25
+
26
+ const estate = [component("net"), component("cluster", ["net"]), component("app", ["cluster"])];
27
+
28
+ describe("componentInputDigests", () => {
29
+ test("is stable for the same project, environment and files", () => {
30
+ const root = project();
31
+ expect(componentInputDigests(estate, { projectRoot: root, env: "prod" })).toEqual(
32
+ componentInputDigests(estate, { projectRoot: root, env: "prod" }),
33
+ );
34
+ });
35
+
36
+ test("covers the bytes of a file a step input names, and everything downstream of it", () => {
37
+ const root = project();
38
+ const before = componentInputDigests(estate, { projectRoot: root, env: "prod" });
39
+ writeFileSync(join(root, "dist", "cluster.json"), `{"name":"cluster","queue":true}`);
40
+ const after = componentInputDigests(estate, { projectRoot: root, env: "prod" });
41
+ expect(after.net).toBe(before.net);
42
+ expect(after.cluster).not.toBe(before.cluster);
43
+ expect(after.app).not.toBe(before.app);
44
+ });
45
+
46
+ test("covers a directory a step names, by its files", () => {
47
+ const root = project();
48
+ const chart = [component("chart", [], { chart: "dist" })];
49
+ const before = componentInputDigests(chart, { projectRoot: root, env: "prod" });
50
+ writeFileSync(join(root, "dist", "app.json"), "{}");
51
+ expect(componentInputDigests(chart, { projectRoot: root, env: "prod" }).chart).not.toBe(before.chart);
52
+ });
53
+
54
+ test("covers the environment and the authored steps", () => {
55
+ const root = project();
56
+ const prod = componentInputDigests(estate, { projectRoot: root, env: "prod" });
57
+ expect(componentInputDigests(estate, { projectRoot: root, env: "staging" }).net).not.toBe(prod.net);
58
+ const moved = [component("net", [], { inputs: { size: 2 } }), ...estate.slice(1)];
59
+ expect(componentInputDigests(moved, { projectRoot: root, env: "prod" }).net).not.toBe(prod.net);
60
+ });
61
+
62
+ test("ignores a string that is not a file, a path outside the project, and the phase name", () => {
63
+ const root = project();
64
+ mkdirSync(join(root, "Apply"));
65
+ const before = componentInputDigests(estate, { projectRoot: root, env: "prod" });
66
+ writeFileSync(join(root, "Apply", "x"), "changes nothing");
67
+ expect(componentInputDigests(estate, { projectRoot: root, env: "prod" })).toEqual(before);
68
+ const outside = [component("net", [], { other: "../elsewhere.json" })];
69
+ expect(() => componentInputDigests(outside, { projectRoot: root, env: "prod" })).not.toThrow();
70
+ });
71
+ });
72
+
73
+ describe("progressThatCarries", () => {
74
+ test("carries a component only when its recorded input is the one it has now", () => {
75
+ const split = progressThatCarries(
76
+ { completed: ["net", "cluster", "app"], inputs: { net: "a", cluster: "b" } },
77
+ { net: "a", cluster: "B", app: "c" },
78
+ );
79
+ expect(split).toEqual({ carried: ["net"], changed: ["app", "cluster"], unrecorded: false });
80
+ });
81
+
82
+ test("a record with no input digests carries nothing", () => {
83
+ expect(progressThatCarries({ completed: ["net"] }, { net: "a" })).toEqual({ carried: [], changed: ["net"], unrecorded: true });
84
+ });
85
+ });