@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
@@ -0,0 +1,192 @@
1
+ /**
2
+ * What each component of a fan-out would apply, as one digest per component
3
+ * (#4081), and which of an earlier attempt's progress still holds against it.
4
+ *
5
+ * A fan-out's plan digest identifies the derivation: who runs, in what order,
6
+ * off which edges. Two different changes that touch the same components in
7
+ * the same shape derive the same plan, so the plan digest alone cannot say
8
+ * whether "cluster-a already applied" is about the change in front of us.
9
+ * The attempt record therefore keeps, for each component it applied, the
10
+ * input digest computed here, and a resumed attempt carries a component as
11
+ * `already-applied` only when that digest is the one the component has now.
12
+ *
13
+ * ## What a component's input digest covers
14
+ *
15
+ * - The environment. Progress against `local` says nothing about `prod`.
16
+ * - The composition: every phase and step as authored, `rollback` included.
17
+ * A `stackOutput` reference is hashed as the reference, not its value.
18
+ * - The bytes of every file a step input names. A string input that resolves,
19
+ * relative to the project root, to a file or directory inside the root is
20
+ * read and hashed, so `template: "dist/cluster-a.template.json"` covers the
21
+ * built template and a rebuild that changes it changes the digest. A
22
+ * directory is hashed by its files, skipping `.git`, `node_modules` and
23
+ * `.chant`, the last because the attempt record itself lives there.
24
+ * - The input digests of the components it depends on. A parameter filled
25
+ * from an upstream output gets its value from that upstream's apply, so a
26
+ * change upstream changes the digest of everything downstream of it, the
27
+ * same reach the fan-out's own walk has.
28
+ *
29
+ * Nothing decided during the run goes in: no run id, no time, no output an
30
+ * apply produced.
31
+ */
32
+
33
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
34
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
35
+ import { computePlanDigest } from "../lifecycle/plan-digest";
36
+ import { sha256Hex } from "../content-digest";
37
+ import type { DriverComponent, DriverPhase } from "./driver";
38
+
39
+ export interface ComponentInputOptions {
40
+ /** The root step inputs' file paths are read relative to, the project the fan-out runs in. */
41
+ projectRoot: string;
42
+ /** The environment the fan-out applies to. */
43
+ env: string;
44
+ /** Environment config resolved ahead of the run, when the caller has any. */
45
+ vars?: Record<string, unknown>;
46
+ }
47
+
48
+ const SKIPPED_DIRS = new Set([".git", "node_modules", ".chant"]);
49
+
50
+ /** Inside `root`, and not `root` itself: a bare "." names the whole project, which is no one step's input. */
51
+ function insideRoot(root: string, path: string): boolean {
52
+ const rel = relative(root, path);
53
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
54
+ }
55
+
56
+ /** Hash a file, or a directory by the relative path and bytes of each file under it. */
57
+ function hashPath(path: string): string | undefined {
58
+ let stat;
59
+ try {
60
+ stat = statSync(path);
61
+ } catch {
62
+ return undefined;
63
+ }
64
+ if (stat.isFile()) return `sha256:${sha256Hex(readFileSync(path))}`;
65
+ if (!stat.isDirectory()) return undefined;
66
+ const files: Record<string, string> = {};
67
+ const walk = (dir: string): void => {
68
+ for (const entry of readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
69
+ if (SKIPPED_DIRS.has(entry.name)) continue;
70
+ const full = join(dir, entry.name);
71
+ if (entry.isDirectory()) walk(full);
72
+ else if (entry.isFile()) files[relative(path, full).split(sep).join("/")] = sha256Hex(readFileSync(full));
73
+ }
74
+ };
75
+ walk(path);
76
+ return computePlanDigest("component-input-dir", files);
77
+ }
78
+
79
+ /** Every file or directory a component's steps name, keyed by the string the step wrote. */
80
+ function referencedFiles(component: DriverComponent, root: string): Record<string, string> {
81
+ const out: Record<string, string> = {};
82
+ const visit = (value: unknown): void => {
83
+ if (typeof value === "string") {
84
+ if (value === "" || value.includes("\n") || value in out) return;
85
+ const path = resolve(root, value);
86
+ if (!insideRoot(root, path) || !existsSync(path)) return;
87
+ const digest = hashPath(path);
88
+ if (digest !== undefined) out[value] = digest;
89
+ return;
90
+ }
91
+ if (Array.isArray(value)) value.forEach(visit);
92
+ else if (value && typeof value === "object") Object.values(value).forEach(visit);
93
+ };
94
+ // Only a step's inputs name files. A phase name or a step's `kind` that
95
+ // happens to match a directory in the project is not one.
96
+ const visitPhases = (phases: DriverPhase[] | undefined): void => {
97
+ for (const phase of phases ?? []) {
98
+ for (const step of phase.steps) {
99
+ if (isPhase(step)) {
100
+ visitPhases([step]);
101
+ continue;
102
+ }
103
+ if (step.kind === "gate") continue;
104
+ const { kind: _kind, ...inputs } = step;
105
+ visit(inputs);
106
+ }
107
+ visitPhases(phase.onFailure);
108
+ }
109
+ };
110
+ visitPhases(component.deploy);
111
+ visitPhases(component.rollback);
112
+ return out;
113
+ }
114
+
115
+ function isPhase(step: DriverPhase["steps"][number]): step is DriverPhase {
116
+ return typeof (step as { phase?: unknown }).phase === "string" && Array.isArray((step as DriverPhase).steps);
117
+ }
118
+
119
+ /**
120
+ * One input digest per component in `components`, keyed by name. Each folds
121
+ * in the digests of the components it depends on, so `components` should be
122
+ * the whole project: a dependency it does not contain is hashed by name only.
123
+ */
124
+ export function componentInputDigests(
125
+ components: DriverComponent[],
126
+ options: ComponentInputOptions,
127
+ ): Record<string, string> {
128
+ const root = resolve(options.projectRoot);
129
+ const byName = new Map(components.map((c) => [c.name, c]));
130
+ const digests = new Map<string, string>();
131
+ const visiting = new Set<string>();
132
+
133
+ const digestOf = (name: string): string | null => {
134
+ const known = digests.get(name);
135
+ if (known !== undefined) return known;
136
+ const component = byName.get(name);
137
+ // An unknown dependency or a cycle is refused by the fan-out's derivation
138
+ // before this runs; here it only has to not loop.
139
+ if (!component || visiting.has(name)) return null;
140
+ visiting.add(name);
141
+ const upstream = [...(component.dependsOn ?? [])].sort().map((dep) => ({ component: dep, digest: digestOf(dep) }));
142
+ visiting.delete(name);
143
+ const digest = computePlanDigest("component-input", {
144
+ environment: options.env,
145
+ component: name,
146
+ deploy: component.deploy,
147
+ rollback: component.rollback ?? null,
148
+ vars: options.vars ?? null,
149
+ files: referencedFiles(component, root),
150
+ upstream,
151
+ });
152
+ digests.set(name, digest);
153
+ return digest;
154
+ };
155
+
156
+ for (const c of components) digestOf(c.name);
157
+ return Object.fromEntries([...digests.entries()].sort(([a], [b]) => a.localeCompare(b)));
158
+ }
159
+
160
+ /** What of an earlier attempt's progress holds against the inputs the components have now. */
161
+ export interface CarriedProgress {
162
+ /** Components the attempt applied whose input is the same now. These stay `already-applied`. */
163
+ carried: string[];
164
+ /** Components the attempt applied whose input moved since. These run again. */
165
+ changed: string[];
166
+ /**
167
+ * True when the record has no input digests at all, as one written before
168
+ * #4081 has. Nothing carries from such a record, since nothing in it says
169
+ * what was applied.
170
+ */
171
+ unrecorded: boolean;
172
+ }
173
+
174
+ /**
175
+ * Split an attempt's `completed` by whether each component's input is the
176
+ * same as now. A component the record holds no digest for counts as changed:
177
+ * a claim that it applied is only worth keeping for the input it applied.
178
+ */
179
+ export function progressThatCarries(
180
+ attempt: { completed: string[]; inputs?: Record<string, string> },
181
+ now: Record<string, string>,
182
+ ): CarriedProgress {
183
+ const recorded = attempt.inputs;
184
+ const carried: string[] = [];
185
+ const changed: string[] = [];
186
+ for (const name of [...attempt.completed].sort()) {
187
+ const then = recorded?.[name];
188
+ if (then !== undefined && now[name] !== undefined && then === now[name]) carried.push(name);
189
+ else changed.push(name);
190
+ }
191
+ return { carried, changed, unrecorded: recorded === undefined };
192
+ }
@@ -70,3 +70,13 @@ describe("prApply (#3464)", () => {
70
70
  for (const name of ["a.json", "b.json", "c.json"]) expect(readFanOutAttempt(join(dir, name))?.prApply).toBeUndefined();
71
71
  });
72
72
  });
73
+
74
+ describe("inputs (#4081)", () => {
75
+ test("round-trips, and a record without them reads as none", () => {
76
+ const dir = mkdtempSync(join(tmpdir(), "fan-out-record-"));
77
+ writeFanOutAttempt(join(dir, "a.json"), { digest: "d", completed: ["net"], failed: [], outputs: {}, inputs: { net: "jcs1-sha256:x" } });
78
+ expect(readFanOutAttempt(join(dir, "a.json"))?.inputs).toEqual({ net: "jcs1-sha256:x" });
79
+ writeFileSync(join(dir, "b.json"), JSON.stringify({ digest: "d", completed: ["net"], failed: [], outputs: {} }));
80
+ expect(readFanOutAttempt(join(dir, "b.json"))?.inputs).toBeUndefined();
81
+ });
82
+ });
@@ -25,6 +25,14 @@
25
25
  * `carried` holds what a step asked to keep for its member (#3459). It rides
26
26
  * in the record rather than beside it because the record is the one file a
27
27
  * per-wave CI job hands to the next.
28
+ *
29
+ * `inputs` holds, for each component in `completed`, the input digest it
30
+ * applied (#4081, ./fan-out-inputs.ts). The plan digest only identifies the
31
+ * derivation, and two different changes with the same shape derive the same
32
+ * one, so the digest alone would carry "cluster-a already applied" into a
33
+ * change that never applied it. A resumed attempt carries a component only
34
+ * when its input digest is the same now. A record written before #4081 has
35
+ * no `inputs`, and none of its progress carries.
28
36
  */
29
37
 
30
38
  import { existsSync, readFileSync } from "node:fs";
@@ -68,6 +76,11 @@ export interface FanOutAttempt {
68
76
  carried?: Record<string, unknown>;
69
77
  /** A pull request's apply only (#3464). */
70
78
  prApply?: PrApplyRecord;
79
+ /**
80
+ * The input digest each completed component applied (#4081), keyed by
81
+ * name. Absent on a record written before it, which then carries nothing.
82
+ */
83
+ inputs?: Record<string, string>;
71
84
  }
72
85
 
73
86
  const isRecord = (value: unknown): value is Record<string, unknown> =>
@@ -109,6 +122,11 @@ export function readFanOutAttempt(path: string): FanOutAttempt | undefined {
109
122
  }
110
123
  const waves = readWaveRecords(parsed.waves);
111
124
  const prApply = readPrApplyRecord(parsed.prApply);
125
+ let inputs: Record<string, string> | undefined;
126
+ if (isRecord(parsed.inputs)) {
127
+ inputs = {};
128
+ for (const [name, value] of Object.entries(parsed.inputs)) if (typeof value === "string") inputs[name] = value;
129
+ }
112
130
  return {
113
131
  digest: typeof parsed.digest === "string" ? parsed.digest : "",
114
132
  completed: Array.isArray(parsed.completed) ? parsed.completed.filter((n): n is string => typeof n === "string") : [],
@@ -117,6 +135,7 @@ export function readFanOutAttempt(path: string): FanOutAttempt | undefined {
117
135
  ...(waves.length > 0 ? { waves } : {}),
118
136
  ...(isRecord(parsed.carried) && Object.keys(parsed.carried).length > 0 ? { carried: parsed.carried } : {}),
119
137
  ...(prApply ? { prApply } : {}),
138
+ ...(inputs ? { inputs } : {}),
120
139
  };
121
140
  }
122
141
 
@@ -49,12 +49,58 @@ import type { ReleaseIdentity } from "../telemetry-attribution";
49
49
  import { downstreamWithin, remainingFanOut, type FanOutPlan, type FanOutProgress, type FanOutSkip } from "./fan-out";
50
50
  import { evaluateGate, gitGateLedgerPort, type GateCheck, type GateLedgerPort } from "../op/gate";
51
51
  import type { RunProgressEvent } from "./run-progress";
52
+ import { emitGateStep, joinRunEventSinks, progressSinkOf, type RunEventSink } from "../run-event-stream";
52
53
  import type { CapabilityRegistry } from "./capability";
53
54
  import type { PendingGateRecord } from "../lifecycle/gate-ledger";
54
55
  import type { DeployContext } from "./capability";
55
56
  import { planWaveComponent, type WaveComponentPlan } from "./wave-plan";
56
57
  import { decideWaveGate, runWaveLoop, waveGateName, waveSetDigest, type WaveMember, type WaveRecord } from "../wave-engine";
57
58
 
59
+ /** The sink a fan-out emits to: run events, and the older stream through them. */
60
+ function fanOutSink(options: FanOutRunOptions): RunEventSink | undefined {
61
+ return joinRunEventSinks(options.onRunEvent, progressSinkOf(options.onProgress));
62
+ }
63
+
64
+ /** The 1-based wave of each component in `waves`. */
65
+ function waveNumbers(waves: string[][]): Map<string, number> {
66
+ const out = new Map<string, number>();
67
+ waves.forEach((wave, i) => wave.forEach((name) => out.set(name, i + 1)));
68
+ return out;
69
+ }
70
+
71
+ /**
72
+ * The settles of components a fan-out does not start (#4007): `blocked`
73
+ * when a dependency failed or stopped at a gate, `already-applied` when an
74
+ * earlier attempt applied it. Each is said once, with no `component-start`
75
+ * before it, so a reader of the stream sees every component of the plan.
76
+ */
77
+ function skipSettles(emit: RunEventSink | undefined, waveOf: Map<string, number>) {
78
+ const said = new Set<string>();
79
+ const say = (component: string, wave: number | undefined, body: { status: "blocked"; blockedBy: string } | { status: "already-applied" }): void => {
80
+ if (!emit || wave === undefined || said.has(component)) return;
81
+ said.add(component);
82
+ emit({ type: "component-settle", wave, component, ...body });
83
+ };
84
+ return {
85
+ /** Each component in `blockedBy` not yet said, in wave order then by name. */
86
+ blocked(blockedBy: Map<string, string>): void {
87
+ const order = [...blockedBy.keys()].sort((a, b) => (waveOf.get(a) ?? 0) - (waveOf.get(b) ?? 0) || a.localeCompare(b));
88
+ for (const component of order) say(component, waveOf.get(component), { status: "blocked", blockedBy: blockedBy.get(component)! });
89
+ },
90
+ /**
91
+ * What an earlier attempt left (`remainingFanOut`'s skips): the components
92
+ * it applied, and the ones its failures blocked. Their wave is the one
93
+ * they have in the derivation, `derived`, which a resumed run re-layers.
94
+ */
95
+ carried(skipped: FanOutSkip[], derived: Map<string, number>): void {
96
+ for (const skip of skipped) {
97
+ if (skip.reason === "already-applied") say(skip.component, derived.get(skip.component), { status: "already-applied" });
98
+ else if (skip.reason === "blocked" && skip.blockedBy) say(skip.component, derived.get(skip.component), { status: "blocked", blockedBy: skip.blockedBy });
99
+ }
100
+ },
101
+ };
102
+ }
103
+
58
104
  /**
59
105
  * One gate per wave (#3049), each bound to its wave's set digest. The other
60
106
  * mode beside {@link FanOutGate}: that one approves the whole set once, this
@@ -115,6 +161,12 @@ export interface FanOutRunOptions {
115
161
  /** Outputs of components this run is not running: the ones the plan lists in `seeds`. */
116
162
  componentOutputs?: Record<string, Record<string, unknown>>;
117
163
  onProgress?: (event: RunProgressEvent) => void;
164
+ /**
165
+ * Where the run's events go (#4041, `--events-json`). A gate over the set
166
+ * or over a wave is a `gate:<name>` step of a `gate` phase with no
167
+ * component, settled before the components it lets through start.
168
+ */
169
+ onRunEvent?: RunEventSink;
118
170
  gates?: GateLedgerPort;
119
171
  now?: string;
120
172
  /** One approval over the ordered set, bound to `plan.digest`. */
@@ -206,18 +258,27 @@ export async function runFanOut(
206
258
  return runGatedWaves(plan, active, components, registry, options, options.waveGate, gates, componentOutputs);
207
259
  }
208
260
 
261
+ const emit = fanOutSink(options);
262
+ emit?.({ type: "run-start", waves: active.waves });
263
+ const skips = skipSettles(emit, waveNumbers(active.waves));
264
+ skips.carried(active.skipped, waveNumbers(plan.waves));
265
+
209
266
  if (options.gate) {
210
- const check = await evaluateGate(gates.port, {
211
- op: options.gate.op,
212
- gate: options.gate.gate,
213
- planDigest: active.digest,
214
- ...(options.gate.description ? { description: options.gate.description } : {}),
215
- ...(options.gate.timeout ? { timeout: options.gate.timeout } : {}),
216
- ...(options.now ? { now: options.now } : {}),
217
- });
267
+ const gate = options.gate;
268
+ const check = await emitGateStep(emit, gate, () =>
269
+ evaluateGate(gates.port, {
270
+ op: gate.op,
271
+ gate: gate.gate,
272
+ planDigest: active.digest,
273
+ ...(gate.description ? { description: gate.description } : {}),
274
+ ...(gate.timeout ? { timeout: gate.timeout } : {}),
275
+ ...(options.now ? { now: options.now } : {}),
276
+ }),
277
+ );
218
278
  if (!check.satisfied) {
219
279
  // Nothing ran, so nothing is half-applied and there is nothing to
220
280
  // compensate. A gate is a fact, not a failure.
281
+ emit?.({ type: "run-settle", status: "gated", durationMs: null });
221
282
  return {
222
283
  plan: active,
223
284
  status: "gated",
@@ -246,29 +307,28 @@ export async function runFanOut(
246
307
  }
247
308
  };
248
309
 
249
- options.onProgress?.({ type: "run-start", waves: active.waves });
250
-
251
310
  for (const [waveIndex, wave] of active.waves.entries()) {
252
311
  const waveNum = waveIndex + 1;
253
312
  // A component whose upstream failed in an earlier wave is not dispatched.
254
313
  const runnable = wave.filter((name) => inPlan.has(name) && !blockedBy.has(name));
255
314
  if (runnable.length === 0) continue;
256
315
 
257
- options.onProgress?.({ type: "wave-start", wave: waveNum, components: runnable });
316
+ emit?.({ type: "wave-start", wave: waveNum, components: runnable });
258
317
  const waveResults = await Promise.all(
259
318
  runnable.map(async (name) => {
260
- options.onProgress?.({ type: "component-start", wave: waveNum, component: name });
319
+ emit?.({ type: "component-start", wave: waveNum, component: name });
261
320
  const planned = options.plans?.[name];
262
321
  const result = await runComponentDeploy(
263
322
  byName.get(name)!,
264
323
  { ...fanOutContext(options, name), ...(planned && Object.keys(planned).length > 0 ? { plans: planned } : {}) },
265
324
  registry,
266
325
  componentOutputs,
267
- options.onProgress,
326
+ undefined,
268
327
  gates,
328
+ emit,
269
329
  );
270
- options.onProgress?.({
271
- type: "component-done",
330
+ emit?.({
331
+ type: "component-settle",
272
332
  wave: waveNum,
273
333
  component: name,
274
334
  status: result.status === "fail" ? "failed" : result.status,
@@ -297,11 +357,13 @@ export async function runFanOut(
297
357
  }
298
358
 
299
359
  const waveFailed = waveResults.some((r) => r.status === "fail");
300
- options.onProgress?.({
301
- type: "wave-done",
360
+ emit?.({
361
+ type: "wave-settle",
302
362
  wave: waveNum,
303
363
  status: waveFailed ? "failed" : waveResults.some((r) => r.status === "gated") ? "gated" : "ok",
304
364
  });
365
+ // What this wave's failures and gates hold back settles now, before the next wave starts.
366
+ skips.blocked(blockedBy);
305
367
  }
306
368
 
307
369
  const blocked: FanOutSkip[] = [...blockedBy.entries()]
@@ -311,7 +373,7 @@ export async function runFanOut(
311
373
  // A failure outranks a gate: something is actually broken, and reporting the
312
374
  // run as "waiting on a human" would hide it. Same precedence the driver uses.
313
375
  const status: FanOutRunResult["status"] = failed.length > 0 ? "fail" : gatedFact ? "gated" : "ok";
314
- options.onProgress?.({ type: "run-done", status: status === "fail" ? "failed" : status });
376
+ emit?.({ type: "run-settle", status: status === "fail" ? "failed" : status, durationMs: null });
315
377
 
316
378
  return {
317
379
  plan: active,
@@ -391,7 +453,10 @@ async function runGatedWaves(
391
453
  }
392
454
  };
393
455
 
394
- options.onProgress?.({ type: "run-start", waves: plan.waves });
456
+ const emit = fanOutSink(options);
457
+ emit?.({ type: "run-start", waves: plan.waves });
458
+ const skips = skipSettles(emit, waveNumbers(plan.waves));
459
+ skips.carried(active.skipped, waveNumbers(plan.waves));
395
460
 
396
461
  /** What planning one wave gave. */
397
462
  interface Planned {
@@ -459,6 +524,7 @@ async function runGatedWaves(
459
524
  results.push(planFailure(f.component, f.error ?? "plan failed"));
460
525
  markBlocked(f.component);
461
526
  }
527
+ skips.blocked(blockedBy);
462
528
 
463
529
  const toRun = runnable.filter((name) => plansFor.has(name));
464
530
  const record: WaveRecord = {
@@ -477,14 +543,16 @@ async function runGatedWaves(
477
543
  return { end: "next" };
478
544
  }
479
545
 
480
- const check = await decideWaveGate(gates.port, {
481
- op: waveGate.op,
482
- gate: gateName,
483
- digest,
484
- description: waveGate.description ?? `wave ${waveNum} of ${plan.waves.length}: ${toRun.join(", ")}`,
485
- ...(waveGate.timeout ? { timeout: waveGate.timeout } : {}),
486
- ...(options.now ? { now: options.now } : {}),
487
- });
546
+ const check = await emitGateStep(emit, { op: waveGate.op, gate: gateName }, () =>
547
+ decideWaveGate(gates.port, {
548
+ op: waveGate.op,
549
+ gate: gateName,
550
+ digest,
551
+ description: waveGate.description ?? `wave ${waveNum} of ${plan.waves.length}: ${toRun.join(", ")}`,
552
+ ...(waveGate.timeout ? { timeout: waveGate.timeout } : {}),
553
+ ...(options.now ? { now: options.now } : {}),
554
+ }),
555
+ );
488
556
  if (!check.satisfied) {
489
557
  // Nothing in this wave ran, and no later wave is planned: its plan
490
558
  // would read outputs this wave has not written.
@@ -502,15 +570,15 @@ async function runGatedWaves(
502
570
  },
503
571
 
504
572
  async apply({ k: waveNum }, { contexts, plansFor, waveFailures }, { check, record, toRun }) {
505
- options.onProgress?.({ type: "wave-start", wave: waveNum, components: toRun });
573
+ emit?.({ type: "wave-start", wave: waveNum, components: toRun });
506
574
  const waveResults = await Promise.all(
507
575
  toRun.map(async (name) => {
508
- options.onProgress?.({ type: "component-start", wave: waveNum, component: name });
576
+ emit?.({ type: "component-start", wave: waveNum, component: name });
509
577
  const plans = plansFor.get(name)!;
510
578
  const ctx = { ...contexts.get(name)!, ...(Object.keys(plans).length > 0 ? { plans } : {}) };
511
- const result = await runComponentDeploy(byName.get(name)!, ctx, registry, componentOutputs, options.onProgress, gates);
512
- options.onProgress?.({
513
- type: "component-done",
579
+ const result = await runComponentDeploy(byName.get(name)!, ctx, registry, componentOutputs, undefined, gates, emit);
580
+ emit?.({
581
+ type: "component-settle",
514
582
  wave: waveNum,
515
583
  component: name,
516
584
  status: result.status === "fail" ? "failed" : result.status,
@@ -543,11 +611,12 @@ async function runGatedWaves(
543
611
  };
544
612
  waves.push(settled);
545
613
  options.onWaveSettled?.(settled);
546
- options.onProgress?.({
547
- type: "wave-done",
614
+ emit?.({
615
+ type: "wave-settle",
548
616
  wave: waveNum,
549
617
  status: waveFailures.length > 0 ? "failed" : waveResults.some((r) => r.status === "gated") ? "gated" : "ok",
550
618
  });
619
+ skips.blocked(blockedBy);
551
620
  return "next";
552
621
  },
553
622
  });
@@ -557,7 +626,7 @@ async function runGatedWaves(
557
626
  .map(([component, by]) => ({ component, reason: "blocked" as const, blockedBy: by }));
558
627
 
559
628
  const status: FanOutRunResult["status"] = failed.length > 0 ? "fail" : gatedFact ? "gated" : "ok";
560
- options.onProgress?.({ type: "run-done", status: status === "fail" ? "failed" : status });
629
+ emit?.({ type: "run-settle", status: status === "fail" ? "failed" : status, durationMs: null });
561
630
 
562
631
  return {
563
632
  // The derivation's waves, not the narrowed re-layering: their numbers name the gates.
@@ -89,6 +89,10 @@ export interface FanOutRequest {
89
89
  * {@link FanOutPlan.digest} so an approval is bound to *what* would be
90
90
  * applied and not only to who would run. Absent, the digest still identifies
91
91
  * the derivation — the selection, the order and the edges it came from.
92
+ *
93
+ * `chant components fan-out` does not pass it: its approval stays bound to
94
+ * the derivation, and it binds a resumed attempt's progress to each
95
+ * component's input instead (./fan-out-inputs.ts, #4081).
92
96
  */
93
97
  inputDigests?: Record<string, string>;
94
98
  /**
@@ -29,6 +29,13 @@
29
29
  * squash merges and rebase merges alike, and every job measures from the
30
30
  * merge base of that commit and its own head (`resolveMergeBase`).
31
31
  *
32
+ * With `events` (#4007) both commands pass `--events-json`, so the job log
33
+ * carries the run-event stream, and keep a copy of it under the report
34
+ * directory through `CHANT_RUN_EVENTS_DIR`, so the report artifact carries
35
+ * it too. With `reportUrl` both pass `--report-url`, which copies the report,
36
+ * the change set and the events where a reader outside CI can fetch them;
37
+ * the job's own environment brings the credentials an `s3://` URL needs.
38
+ *
32
39
  * In a workspace member (#3465) both commands run in the member's directory
33
40
  * and pass `--member <name>`, so the member's gate (`pr-<number>-<member>`),
34
41
  * note and statuses stay apart from every other member's on the same pull
@@ -68,6 +75,13 @@ export function prLoopSetup(image: string): string[] {
68
75
  return image === PR_LOOP_IMAGE ? PR_LOOP_SETUP : [];
69
76
  }
70
77
 
78
+ /**
79
+ * Where the jobs keep their run-event files with `events` (#4007), as
80
+ * `CHANT_RUN_EVENTS_DIR`: inside the report directory, so the report
81
+ * artifact carries them.
82
+ */
83
+ export const PR_LOOP_EVENTS_DIR = `${PR_LOOP_REPORT_DIR}/run-events`;
84
+
71
85
  /** The `prLoop` generator option (`ComponentPipelineOptions.prLoop`). */
72
86
  export interface PrLoopPipelineOptions {
73
87
  /** The gate the apply waits on. Default `pr-apply`. */
@@ -79,6 +93,18 @@ export interface PrLoopPipelineOptions {
79
93
  branch?: string;
80
94
  /** Count an approval only from someone who approved the pull request on the forge. Default true. */
81
95
  requireReview?: boolean;
96
+ /**
97
+ * Stream each job's run events (#4007): `--events-json` on both commands,
98
+ * and `CHANT_RUN_EVENTS_DIR` set to {@link PR_LOOP_EVENTS_DIR}. Default false.
99
+ */
100
+ events?: boolean;
101
+ /**
102
+ * Copy each job's report, change set and events to this `s3://` or
103
+ * `file://` URL (#4007, `--report-url`), under `<pr>/<commit>/`. It is
104
+ * passed in double quotes, so it may name a variable the job expands,
105
+ * such as `$CHANT_REPORT_URL`.
106
+ */
107
+ reportUrl?: string;
82
108
  /**
83
109
  * Which GitHub-shaped forge the workflow is for. Set by the forgejo
84
110
  * generator, which reuses the github one; a caller never needs to.
@@ -112,16 +138,21 @@ export function prLoopJobs(forge: ForgeKind, env: string, options: PrLoopPipelin
112
138
  const common = [
113
139
  "--env", env, "--gate", gate, "--output", PR_LOOP_REPORT_DIR, "--forge", forge,
114
140
  ...(member ? ["--member", member] : []),
141
+ ...(options.events ? ["--events-json"] : []),
142
+ ...(options.reportUrl ? ["--report-url", JSON.stringify(options.reportUrl)] : []),
115
143
  ];
116
144
  const github = forge !== "gitlab";
117
- const token: Record<string, string> = github ? { GITHUB_TOKEN: GITHUB_JOB_TOKEN } : {};
145
+ const jobEnv: Record<string, string> = {
146
+ ...(github ? { GITHUB_TOKEN: GITHUB_JOB_TOKEN } : {}),
147
+ ...(options.events ? { CHANT_RUN_EVENTS_DIR: PR_LOOP_EVENTS_DIR } : {}),
148
+ };
118
149
  return [
119
150
  {
120
151
  jobName: "plan",
121
152
  command: ["chant", "components", "pr-plan", "--base", '"$BASE_SHA"', "--pr", '"$PR_NUMBER"', ...common].join(" "),
122
153
  env: github
123
- ? { BASE_SHA: "${{ github.event.pull_request.base.sha }}", PR_NUMBER: "${{ github.event.pull_request.number }}", ...token }
124
- : { BASE_SHA: "$CI_MERGE_REQUEST_DIFF_BASE_SHA", PR_NUMBER: "$CI_MERGE_REQUEST_IID" },
154
+ ? { BASE_SHA: "${{ github.event.pull_request.base.sha }}", PR_NUMBER: "${{ github.event.pull_request.number }}", ...jobEnv }
155
+ : { BASE_SHA: "$CI_MERGE_REQUEST_DIFF_BASE_SHA", PR_NUMBER: "$CI_MERGE_REQUEST_IID", ...jobEnv },
125
156
  },
126
157
  {
127
158
  jobName: "apply",
@@ -130,7 +161,7 @@ export function prLoopJobs(forge: ForgeKind, env: string, options: PrLoopPipelin
130
161
  ...(options.requireReview === false ? [] : ["--require-review"]),
131
162
  "--resume", PR_APPLY_RECORD,
132
163
  ].join(" "),
133
- env: github ? { BASE_SHA: "${{ github.event.before }}", ...token } : { BASE_SHA: "$CI_COMMIT_BEFORE_SHA" },
164
+ env: github ? { BASE_SHA: "${{ github.event.before }}", ...jobEnv } : { BASE_SHA: "$CI_COMMIT_BEFORE_SHA", ...jobEnv },
134
165
  ...(github ? {} : { setup: [gitlabBaseFallback(options.branch)] }),
135
166
  },
136
167
  ];