@intentius/chant 0.124.28 → 0.124.30

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 (449) hide show
  1. package/dist/build-params.d.ts +34 -1
  2. package/dist/build-params.d.ts.map +1 -1
  3. package/dist/build-params.js +31 -1
  4. package/dist/change-set-graph.d.ts +8 -1
  5. package/dist/change-set-graph.d.ts.map +1 -1
  6. package/dist/change-set-graph.js +4 -2
  7. package/dist/change-set.d.ts +10 -0
  8. package/dist/change-set.d.ts.map +1 -1
  9. package/dist/change-set.js +4 -3
  10. package/dist/cli/build-params-cli.d.ts +7 -1
  11. package/dist/cli/build-params-cli.d.ts.map +1 -1
  12. package/dist/cli/build-params-cli.js +17 -8
  13. package/dist/cli/commands/build.d.ts.map +1 -1
  14. package/dist/cli/commands/build.js +6 -3
  15. package/dist/cli/handlers/approve.d.ts.map +1 -1
  16. package/dist/cli/handlers/approve.js +45 -0
  17. package/dist/cli/handlers/build.d.ts.map +1 -1
  18. package/dist/cli/handlers/build.js +18 -4
  19. package/dist/cli/handlers/fan-out.d.ts +9 -0
  20. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  21. package/dist/cli/handlers/fan-out.js +67 -8
  22. package/dist/cli/handlers/lifecycle-gc.d.ts +19 -0
  23. package/dist/cli/handlers/lifecycle-gc.d.ts.map +1 -0
  24. package/dist/cli/handlers/lifecycle-gc.js +143 -0
  25. package/dist/cli/handlers/pr.d.ts +11 -3
  26. package/dist/cli/handlers/pr.d.ts.map +1 -1
  27. package/dist/cli/handlers/pr.js +134 -26
  28. package/dist/cli/handlers/promote.d.ts +7 -0
  29. package/dist/cli/handlers/promote.d.ts.map +1 -1
  30. package/dist/cli/handlers/promote.js +210 -33
  31. package/dist/cli/handlers/release.d.ts +62 -5
  32. package/dist/cli/handlers/release.d.ts.map +1 -1
  33. package/dist/cli/handlers/release.js +414 -28
  34. package/dist/cli/handlers/run.d.ts +11 -1
  35. package/dist/cli/handlers/run.d.ts.map +1 -1
  36. package/dist/cli/handlers/run.js +67 -6
  37. package/dist/cli/main.d.ts.map +1 -1
  38. package/dist/cli/main.js +91 -10
  39. package/dist/cli/parse-args.d.ts.map +1 -1
  40. package/dist/cli/parse-args.js +73 -2
  41. package/dist/cli/registry.d.ts +32 -4
  42. package/dist/cli/registry.d.ts.map +1 -1
  43. package/dist/cli/run-events.d.ts +3 -2
  44. package/dist/cli/run-events.d.ts.map +1 -1
  45. package/dist/cli/run-events.js +5 -3
  46. package/dist/components/auto-release.d.ts +2 -0
  47. package/dist/components/auto-release.d.ts.map +1 -1
  48. package/dist/components/auto-release.js +1 -0
  49. package/dist/components/capability.d.ts +9 -0
  50. package/dist/components/capability.d.ts.map +1 -1
  51. package/dist/components/driver.d.ts +8 -0
  52. package/dist/components/driver.d.ts.map +1 -1
  53. package/dist/components/driver.js +35 -0
  54. package/dist/components/fan-out-inputs.d.ts +69 -0
  55. package/dist/components/fan-out-inputs.d.ts.map +1 -0
  56. package/dist/components/fan-out-inputs.js +169 -0
  57. package/dist/components/fan-out-record.d.ts +13 -0
  58. package/dist/components/fan-out-record.d.ts.map +1 -1
  59. package/dist/components/fan-out-record.js +16 -0
  60. package/dist/components/fan-out-run.d.ts.map +1 -1
  61. package/dist/components/fan-out-run.js +50 -0
  62. package/dist/components/fan-out.d.ts +4 -0
  63. package/dist/components/fan-out.d.ts.map +1 -1
  64. package/dist/components/pr-pipeline.d.ts +49 -0
  65. package/dist/components/pr-pipeline.d.ts.map +1 -1
  66. package/dist/components/pr-pipeline.js +38 -4
  67. package/dist/components/pr-run.d.ts +20 -2
  68. package/dist/components/pr-run.d.ts.map +1 -1
  69. package/dist/components/pr-run.js +26 -13
  70. package/dist/components/promote.d.ts +23 -0
  71. package/dist/components/promote.d.ts.map +1 -1
  72. package/dist/components/promote.js +60 -2
  73. package/dist/components/release-compile.d.ts +9 -0
  74. package/dist/components/release-compile.d.ts.map +1 -1
  75. package/dist/components/release-compile.js +9 -3
  76. package/dist/components/release-gate.d.ts +11 -1
  77. package/dist/components/release-gate.d.ts.map +1 -1
  78. package/dist/components/release-gate.js +10 -4
  79. package/dist/components/wave-plan.d.ts +16 -0
  80. package/dist/components/wave-plan.d.ts.map +1 -1
  81. package/dist/components/wave-plan.js +36 -2
  82. package/dist/config.d.ts +38 -0
  83. package/dist/config.d.ts.map +1 -1
  84. package/dist/config.js +2 -0
  85. package/dist/flag-params.d.ts +54 -0
  86. package/dist/flag-params.d.ts.map +1 -0
  87. package/dist/flag-params.js +130 -0
  88. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts +120 -0
  89. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -0
  90. package/dist/lifecycle/__fixtures__/publish-fakes.js +304 -0
  91. package/dist/lifecycle/change-set-store.d.ts +2 -1
  92. package/dist/lifecycle/change-set-store.d.ts.map +1 -1
  93. package/dist/lifecycle/change-set-store.js +2 -1
  94. package/dist/lifecycle/delivery-metrics.d.ts +139 -0
  95. package/dist/lifecycle/delivery-metrics.d.ts.map +1 -0
  96. package/dist/lifecycle/delivery-metrics.js +145 -0
  97. package/dist/lifecycle/deploy-outcome.d.ts +81 -0
  98. package/dist/lifecycle/deploy-outcome.d.ts.map +1 -0
  99. package/dist/lifecycle/deploy-outcome.js +101 -0
  100. package/dist/lifecycle/gate-change-set.d.ts +10 -1
  101. package/dist/lifecycle/gate-change-set.d.ts.map +1 -1
  102. package/dist/lifecycle/gate-change-set.js +35 -3
  103. package/dist/lifecycle/gate-ledger.d.ts +2 -3
  104. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  105. package/dist/lifecycle/git.d.ts +30 -1
  106. package/dist/lifecycle/git.d.ts.map +1 -1
  107. package/dist/lifecycle/git.js +31 -5
  108. package/dist/lifecycle/index.d.ts +4 -0
  109. package/dist/lifecycle/index.d.ts.map +1 -1
  110. package/dist/lifecycle/index.js +4 -0
  111. package/dist/lifecycle/mixed-environment.d.ts +95 -0
  112. package/dist/lifecycle/mixed-environment.d.ts.map +1 -0
  113. package/dist/lifecycle/mixed-environment.js +154 -0
  114. package/dist/lifecycle/publish-attachments.d.ts +79 -0
  115. package/dist/lifecycle/publish-attachments.d.ts.map +1 -0
  116. package/dist/lifecycle/publish-attachments.js +179 -0
  117. package/dist/lifecycle/publish-credentials.d.ts +37 -0
  118. package/dist/lifecycle/publish-credentials.d.ts.map +1 -0
  119. package/dist/lifecycle/publish-credentials.js +69 -0
  120. package/dist/lifecycle/publish-declaration.d.ts +97 -0
  121. package/dist/lifecycle/publish-declaration.d.ts.map +1 -0
  122. package/dist/lifecycle/publish-declaration.js +83 -0
  123. package/dist/lifecycle/publish-forge.d.ts +53 -0
  124. package/dist/lifecycle/publish-forge.d.ts.map +1 -0
  125. package/dist/lifecycle/publish-forge.js +298 -0
  126. package/dist/lifecycle/publish-npm.d.ts +61 -0
  127. package/dist/lifecycle/publish-npm.d.ts.map +1 -0
  128. package/dist/lifecycle/publish-npm.js +242 -0
  129. package/dist/lifecycle/publish-oci.d.ts +64 -0
  130. package/dist/lifecycle/publish-oci.d.ts.map +1 -0
  131. package/dist/lifecycle/publish-oci.js +383 -0
  132. package/dist/lifecycle/publish-record.d.ts +66 -0
  133. package/dist/lifecycle/publish-record.d.ts.map +1 -0
  134. package/dist/lifecycle/publish-record.js +84 -0
  135. package/dist/lifecycle/publish-targets.d.ts +45 -0
  136. package/dist/lifecycle/publish-targets.d.ts.map +1 -0
  137. package/dist/lifecycle/publish-targets.js +85 -0
  138. package/dist/lifecycle/release-cut.d.ts +48 -1
  139. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  140. package/dist/lifecycle/release-cut.js +116 -23
  141. package/dist/lifecycle/release-join.d.ts +95 -0
  142. package/dist/lifecycle/release-join.d.ts.map +1 -0
  143. package/dist/lifecycle/release-join.js +139 -0
  144. package/dist/lifecycle/release-ledger.d.ts +8 -3
  145. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  146. package/dist/lifecycle/release-ledger.js +2 -0
  147. package/dist/lifecycle/release-publish.d.ts +312 -0
  148. package/dist/lifecycle/release-publish.d.ts.map +1 -0
  149. package/dist/lifecycle/release-publish.js +335 -0
  150. package/dist/lifecycle/release-revocation.d.ts +80 -0
  151. package/dist/lifecycle/release-revocation.d.ts.map +1 -0
  152. package/dist/lifecycle/release-revocation.js +123 -0
  153. package/dist/lifecycle/release-store.d.ts +12 -2
  154. package/dist/lifecycle/release-store.d.ts.map +1 -1
  155. package/dist/lifecycle/release-store.js +4 -2
  156. package/dist/lifecycle/release-verify.d.ts +61 -0
  157. package/dist/lifecycle/release-verify.d.ts.map +1 -0
  158. package/dist/lifecycle/release-verify.js +92 -0
  159. package/dist/lifecycle/release-workstation.d.ts +91 -0
  160. package/dist/lifecycle/release-workstation.d.ts.map +1 -0
  161. package/dist/lifecycle/release-workstation.js +180 -0
  162. package/dist/lifecycle/retention-policy.d.ts +45 -0
  163. package/dist/lifecycle/retention-policy.d.ts.map +1 -0
  164. package/dist/lifecycle/retention-policy.js +43 -0
  165. package/dist/lifecycle/retention.d.ts +185 -0
  166. package/dist/lifecycle/retention.d.ts.map +1 -0
  167. package/dist/lifecycle/retention.js +400 -0
  168. package/dist/lifecycle/run-ledger.d.ts +1 -1
  169. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  170. package/dist/lifecycle/run-ledger.js +9 -0
  171. package/dist/op/activities/activity-contracts.d.ts +1 -0
  172. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  173. package/dist/op/activities/activity-contracts.js +1 -0
  174. package/dist/op/activities/shell.d.ts +6 -0
  175. package/dist/op/activities/shell.d.ts.map +1 -1
  176. package/dist/op/activities/shell.js +1 -1
  177. package/dist/op/local-executor.d.ts +23 -1
  178. package/dist/op/local-executor.d.ts.map +1 -1
  179. package/dist/op/local-executor.js +9 -3
  180. package/dist/op/runtime.d.ts +27 -0
  181. package/dist/op/runtime.d.ts.map +1 -1
  182. package/dist/op/runtime.js +20 -0
  183. package/dist/plan-summary.d.ts.map +1 -1
  184. package/dist/plan-summary.js +8 -2
  185. package/dist/pr-forge.d.ts +23 -0
  186. package/dist/pr-forge.d.ts.map +1 -1
  187. package/dist/pr-forge.js +44 -0
  188. package/dist/pr-loop.d.ts +17 -0
  189. package/dist/pr-loop.d.ts.map +1 -1
  190. package/dist/pr-loop.js +30 -4
  191. package/dist/pr-report-url.d.ts +82 -0
  192. package/dist/pr-report-url.d.ts.map +1 -0
  193. package/dist/pr-report-url.js +174 -0
  194. package/dist/provenance.d.ts +2 -2
  195. package/dist/provenance.d.ts.map +1 -1
  196. package/dist/run-event-store.d.ts +29 -2
  197. package/dist/run-event-store.d.ts.map +1 -1
  198. package/dist/run-event-store.js +50 -3
  199. package/dist/run-event-stream.d.ts +4 -3
  200. package/dist/run-event-stream.d.ts.map +1 -1
  201. package/dist/run-event-stream.js +7 -3
  202. package/dist/run-event.d.ts +34 -1
  203. package/dist/run-event.d.ts.map +1 -1
  204. package/dist/run-event.js +4 -0
  205. package/dist/wave-runtime.mjs +260 -229
  206. package/dist/workspace/__fixtures__/flag-workspace.d.ts +31 -0
  207. package/dist/workspace/__fixtures__/flag-workspace.d.ts.map +1 -0
  208. package/dist/workspace/__fixtures__/flag-workspace.js +114 -0
  209. package/dist/workspace/change-set.schema.json +5 -1
  210. package/dist/workspace/check.schema.json +4 -2
  211. package/dist/workspace/checks/records.d.ts +9 -1
  212. package/dist/workspace/checks/records.d.ts.map +1 -1
  213. package/dist/workspace/checks/records.js +35 -1
  214. package/dist/workspace/checks.d.ts +1 -0
  215. package/dist/workspace/checks.d.ts.map +1 -1
  216. package/dist/workspace/checks.js +2 -1
  217. package/dist/workspace/ci-green-forge.d.ts +2 -0
  218. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  219. package/dist/workspace/ci-green.d.ts +10 -0
  220. package/dist/workspace/ci-green.d.ts.map +1 -1
  221. package/dist/workspace/ci-green.js +14 -5
  222. package/dist/workspace/ci-run.d.ts +222 -0
  223. package/dist/workspace/ci-run.d.ts.map +1 -0
  224. package/dist/workspace/ci-run.js +464 -0
  225. package/dist/workspace/ci-serve.d.ts +214 -0
  226. package/dist/workspace/ci-serve.d.ts.map +1 -0
  227. package/dist/workspace/ci-serve.js +412 -0
  228. package/dist/workspace/declaration.d.ts +16 -0
  229. package/dist/workspace/declaration.d.ts.map +1 -1
  230. package/dist/workspace/declaration.js +26 -0
  231. package/dist/workspace/declaration.schema.json +64 -0
  232. package/dist/workspace/declared-kinds.d.ts +16 -0
  233. package/dist/workspace/declared-kinds.d.ts.map +1 -1
  234. package/dist/workspace/declared-kinds.js +25 -0
  235. package/dist/workspace/delivery-metrics.d.ts +91 -0
  236. package/dist/workspace/delivery-metrics.d.ts.map +1 -0
  237. package/dist/workspace/delivery-metrics.js +217 -0
  238. package/dist/workspace/delivery-metrics.schema.json +519 -0
  239. package/dist/workspace/flags-read.d.ts +37 -0
  240. package/dist/workspace/flags-read.d.ts.map +1 -0
  241. package/dist/workspace/flags-read.js +103 -0
  242. package/dist/workspace/flags.d.ts +100 -0
  243. package/dist/workspace/flags.d.ts.map +1 -0
  244. package/dist/workspace/flags.js +98 -0
  245. package/dist/workspace/graph-cli.js +1 -1
  246. package/dist/workspace/intent-cli.d.ts +11 -2
  247. package/dist/workspace/intent-cli.d.ts.map +1 -1
  248. package/dist/workspace/intent-cli.js +54 -5
  249. package/dist/workspace/intent-trace.d.ts +219 -0
  250. package/dist/workspace/intent-trace.d.ts.map +1 -0
  251. package/dist/workspace/intent-trace.js +314 -0
  252. package/dist/workspace/intent.d.ts +30 -6
  253. package/dist/workspace/intent.d.ts.map +1 -1
  254. package/dist/workspace/intent.js +141 -21
  255. package/dist/workspace/intent.schema.json +702 -6
  256. package/dist/workspace/overlap.d.ts +146 -0
  257. package/dist/workspace/overlap.d.ts.map +1 -0
  258. package/dist/workspace/overlap.js +276 -0
  259. package/dist/workspace/pr-report.schema.json +5 -0
  260. package/dist/workspace/reason-codes.d.ts +2 -0
  261. package/dist/workspace/reason-codes.d.ts.map +1 -1
  262. package/dist/workspace/reason-codes.js +3 -0
  263. package/dist/workspace/records.d.ts +15 -2
  264. package/dist/workspace/records.d.ts.map +1 -1
  265. package/dist/workspace/records.js +32 -0
  266. package/dist/workspace/records.schema.json +21 -2
  267. package/dist/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  268. package/dist/workspace/reference-kinds/flag/flag.schema.json +53 -0
  269. package/dist/workspace/releases.d.ts +9 -0
  270. package/dist/workspace/releases.d.ts.map +1 -1
  271. package/dist/workspace/releases.js +9 -0
  272. package/dist/workspace/releases.schema.json +123 -1
  273. package/dist/workspace/run-event.schema.json +24 -6
  274. package/dist/workspace/status-gates.d.ts +8 -0
  275. package/dist/workspace/status-gates.d.ts.map +1 -1
  276. package/dist/workspace/status-stewards.d.ts +2 -0
  277. package/dist/workspace/status-stewards.d.ts.map +1 -1
  278. package/dist/workspace/status-stewards.js +1 -0
  279. package/dist/workspace/status.d.ts +78 -0
  280. package/dist/workspace/status.d.ts.map +1 -1
  281. package/dist/workspace/status.js +170 -3
  282. package/dist/workspace/status.schema.json +210 -2
  283. package/dist/workspace/wip.d.ts.map +1 -1
  284. package/dist/workspace/wip.js +11 -3
  285. package/package.json +1 -1
  286. package/src/build-params.test.ts +46 -0
  287. package/src/build-params.ts +55 -1
  288. package/src/change-set-graph.ts +10 -2
  289. package/src/change-set.ts +14 -3
  290. package/src/cli/build-params-cli.ts +22 -9
  291. package/src/cli/commands/build.ts +6 -3
  292. package/src/cli/handlers/approve-release.test.ts +5 -1
  293. package/src/cli/handlers/approve-revoked.test.ts +155 -0
  294. package/src/cli/handlers/approve.ts +47 -0
  295. package/src/cli/handlers/build.test.ts +30 -0
  296. package/src/cli/handlers/build.ts +20 -4
  297. package/src/cli/handlers/fan-out.test.ts +262 -1
  298. package/src/cli/handlers/fan-out.ts +72 -8
  299. package/src/cli/handlers/intent-trace.e2e.test.ts +201 -0
  300. package/src/cli/handlers/lifecycle-gc.test.ts +126 -0
  301. package/src/cli/handlers/lifecycle-gc.ts +146 -0
  302. package/src/cli/handlers/pr.test.ts +148 -1
  303. package/src/cli/handlers/pr.ts +144 -28
  304. package/src/cli/handlers/promote.test.ts +280 -2
  305. package/src/cli/handlers/promote.ts +210 -34
  306. package/src/cli/handlers/release-implicit.e2e.test.ts +12 -4
  307. package/src/cli/handlers/release-join.e2e.test.ts +185 -0
  308. package/src/cli/handlers/release-publish-targets.e2e.test.ts +295 -0
  309. package/src/cli/handlers/release-verify.e2e.test.ts +117 -0
  310. package/src/cli/handlers/release-workstation-ci.e2e.test.ts +135 -0
  311. package/src/cli/handlers/release.e2e.test.ts +146 -32
  312. package/src/cli/handlers/release.ts +415 -28
  313. package/src/cli/handlers/run-auto-release.test.ts +9 -0
  314. package/src/cli/handlers/run-release.test.ts +55 -0
  315. package/src/cli/handlers/run.ts +69 -5
  316. package/src/cli/main.test.ts +1 -0
  317. package/src/cli/main.ts +91 -10
  318. package/src/cli/parse-args.ts +54 -2
  319. package/src/cli/registry.ts +32 -4
  320. package/src/cli/run-events.ts +5 -2
  321. package/src/components/auto-release.test.ts +9 -0
  322. package/src/components/auto-release.ts +3 -0
  323. package/src/components/capability.ts +9 -0
  324. package/src/components/driver.test.ts +24 -0
  325. package/src/components/driver.ts +36 -0
  326. package/src/components/fan-out-inputs.test.ts +85 -0
  327. package/src/components/fan-out-inputs.ts +192 -0
  328. package/src/components/fan-out-record.test.ts +10 -0
  329. package/src/components/fan-out-record.ts +19 -0
  330. package/src/components/fan-out-run.ts +48 -0
  331. package/src/components/fan-out.ts +4 -0
  332. package/src/components/pr-pipeline.ts +67 -4
  333. package/src/components/pr-run.test.ts +127 -0
  334. package/src/components/pr-run.ts +32 -12
  335. package/src/components/promote.ts +68 -2
  336. package/src/components/release-compile.ts +17 -3
  337. package/src/components/release-gate.ts +18 -4
  338. package/src/components/wave-plan.ts +45 -2
  339. package/src/config.ts +8 -0
  340. package/src/flag-params.test.ts +144 -0
  341. package/src/flag-params.ts +134 -0
  342. package/src/lifecycle/__fixtures__/publish-fakes.ts +351 -0
  343. package/src/lifecycle/change-set-store.ts +2 -1
  344. package/src/lifecycle/delivery-metrics.ts +263 -0
  345. package/src/lifecycle/deploy-outcome.ts +147 -0
  346. package/src/lifecycle/gate-change-set.ts +37 -6
  347. package/src/lifecycle/gate-ledger.ts +2 -2
  348. package/src/lifecycle/git.ts +61 -8
  349. package/src/lifecycle/index.ts +4 -0
  350. package/src/lifecycle/mixed-environment.test.ts +97 -0
  351. package/src/lifecycle/mixed-environment.ts +204 -0
  352. package/src/lifecycle/publish-attachments.ts +196 -0
  353. package/src/lifecycle/publish-credentials.ts +84 -0
  354. package/src/lifecycle/publish-declaration.ts +95 -0
  355. package/src/lifecycle/publish-forge.ts +325 -0
  356. package/src/lifecycle/publish-npm.ts +259 -0
  357. package/src/lifecycle/publish-oci.ts +396 -0
  358. package/src/lifecycle/publish-record.ts +113 -0
  359. package/src/lifecycle/publish-resume.test.ts +168 -0
  360. package/src/lifecycle/publish-targets.test.ts +494 -0
  361. package/src/lifecycle/publish-targets.ts +100 -0
  362. package/src/lifecycle/release-cut.test.ts +74 -2
  363. package/src/lifecycle/release-cut.ts +158 -22
  364. package/src/lifecycle/release-flag.test.ts +112 -0
  365. package/src/lifecycle/release-join.test.ts +68 -0
  366. package/src/lifecycle/release-join.ts +182 -0
  367. package/src/lifecycle/release-ledger.ts +9 -3
  368. package/src/lifecycle/release-publish.test.ts +225 -0
  369. package/src/lifecycle/release-publish.ts +568 -0
  370. package/src/lifecycle/release-revocation.ts +147 -0
  371. package/src/lifecycle/release-store.ts +15 -4
  372. package/src/lifecycle/release-verify.test.ts +110 -0
  373. package/src/lifecycle/release-verify.ts +120 -0
  374. package/src/lifecycle/release-workstation.test.ts +204 -0
  375. package/src/lifecycle/release-workstation.ts +216 -0
  376. package/src/lifecycle/retention-growth.e2e.test.ts +279 -0
  377. package/src/lifecycle/retention-policy.ts +63 -0
  378. package/src/lifecycle/retention.test.ts +363 -0
  379. package/src/lifecycle/retention.ts +508 -0
  380. package/src/lifecycle/run-ledger.ts +7 -1
  381. package/src/op/activities/activity-contracts.ts +1 -0
  382. package/src/op/activities/shell.ts +7 -1
  383. package/src/op/local-executor.ts +27 -4
  384. package/src/op/runtime.ts +42 -0
  385. package/src/plan-summary.test.ts +20 -0
  386. package/src/plan-summary.ts +8 -1
  387. package/src/pr-forge.test.ts +25 -0
  388. package/src/pr-forge.ts +62 -0
  389. package/src/pr-loop.test.ts +13 -1
  390. package/src/pr-loop.ts +41 -4
  391. package/src/pr-report-url.test.ts +131 -0
  392. package/src/pr-report-url.ts +209 -0
  393. package/src/provenance.ts +2 -2
  394. package/src/run-event-store.ts +63 -3
  395. package/src/run-event-stream.ts +8 -4
  396. package/src/run-event.ts +38 -1
  397. package/src/workspace/__fixtures__/flag-workspace.ts +132 -0
  398. package/src/workspace/__fixtures__/older-records/change-set-984534ea9.json +100 -0
  399. package/src/workspace/__fixtures__/older-records/older-records.json +326 -0
  400. package/src/workspace/change-set.schema.json +5 -1
  401. package/src/workspace/check.schema.json +4 -2
  402. package/src/workspace/checks/records.ts +35 -1
  403. package/src/workspace/checks.ts +2 -1
  404. package/src/workspace/ci-green-forge.ts +2 -0
  405. package/src/workspace/ci-green.ts +20 -5
  406. package/src/workspace/ci-run.test.ts +416 -0
  407. package/src/workspace/ci-run.ts +571 -0
  408. package/src/workspace/ci-serve.test.ts +268 -0
  409. package/src/workspace/ci-serve.ts +521 -0
  410. package/src/workspace/declaration.schema.json +64 -0
  411. package/src/workspace/declaration.test.ts +28 -0
  412. package/src/workspace/declaration.ts +38 -0
  413. package/src/workspace/declared-kinds.ts +40 -1
  414. package/src/workspace/delivery-metrics.schema.json +519 -0
  415. package/src/workspace/delivery-metrics.test.ts +236 -0
  416. package/src/workspace/delivery-metrics.ts +286 -0
  417. package/src/workspace/flags-read.ts +121 -0
  418. package/src/workspace/flags.test.ts +141 -0
  419. package/src/workspace/flags.ts +157 -0
  420. package/src/workspace/graph-cli.ts +1 -1
  421. package/src/workspace/intent-cli.ts +46 -5
  422. package/src/workspace/intent-trace.test.ts +173 -0
  423. package/src/workspace/intent-trace.ts +484 -0
  424. package/src/workspace/intent.schema.json +702 -6
  425. package/src/workspace/intent.ts +148 -25
  426. package/src/workspace/older-records.test.ts +412 -0
  427. package/src/workspace/overlap.test.ts +165 -0
  428. package/src/workspace/overlap.ts +340 -0
  429. package/src/workspace/pr-report.schema.json +5 -0
  430. package/src/workspace/read-contract.e2e.test.ts +2 -1
  431. package/src/workspace/reason-codes.test.ts +5 -0
  432. package/src/workspace/reason-codes.ts +3 -0
  433. package/src/workspace/record-assets.test.ts +2 -1
  434. package/src/workspace/records-contract.e2e.test.ts +2 -1
  435. package/src/workspace/records.schema.json +21 -2
  436. package/src/workspace/records.ts +36 -2
  437. package/src/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  438. package/src/workspace/reference-kinds/flag/flag.schema.json +53 -0
  439. package/src/workspace/releases.schema.json +123 -1
  440. package/src/workspace/releases.ts +11 -0
  441. package/src/workspace/run-event.schema.json +24 -6
  442. package/src/workspace/status-contract.test.ts +29 -0
  443. package/src/workspace/status-gates.ts +8 -0
  444. package/src/workspace/status-mixed.test.ts +152 -0
  445. package/src/workspace/status-revoked.test.ts +153 -0
  446. package/src/workspace/status-stewards.ts +3 -0
  447. package/src/workspace/status.schema.json +210 -2
  448. package/src/workspace/status.ts +254 -3
  449. package/src/workspace/wip.ts +11 -2
@@ -12,6 +12,13 @@
12
12
  * failed or stopped at a gate, so the ledger never misses a deploy that
13
13
  * happened. Unlike an auto-recorded release, the record is what these
14
14
  * commands are for, so a failed write is an error rather than a warning.
15
+ * A run that applied partly, or failed, also appends a deploy outcome
16
+ * (#4035, ../../lifecycle/deploy-outcome.ts) naming what it did to each
17
+ * component, so `workspace status` reads the environment as mixed.
18
+ *
19
+ * `rollback --release` (#4035) is a promote of an earlier release into the
20
+ * environment: every component of the release at the digest the environment
21
+ * ran from it, through the release gate `promote --release` binds (#4045).
15
22
  */
16
23
  import { resolve } from "node:path";
17
24
  import { readFileSync } from "node:fs";
@@ -26,14 +33,15 @@ import { fanOutRegistry } from "../../components/fan-out-support.js";
26
33
  import { renderDriverHuman } from "../../components/driver-output.js";
27
34
  import { ndjsonProgressSink } from "../../components/run-progress.js";
28
35
  import { openCliRunEvents, refusesBothStreams } from "../run-events.js";
29
- import { parseDigestPins, planPromotion, planRollback, planRedeploy, withoutBuildSteps, runPromotion, promotionRecord, rollbackRecord, redeployRecord, gateApprover, gateAdmission, } from "../../components/promote.js";
36
+ import { parseDigestPins, planPromotion, planRollback, planReleaseRollback, planRedeploy, withoutBuildSteps, runPromotion, promotionRecord, rollbackRecord, redeployRecord, gateApprover, gateAdmission, } from "../../components/promote.js";
30
37
  import { summaryLedgerPrefix, writeGatedRunSummary } from "../../op/gate-summary.js";
31
38
  import { approveCommand, describeGateMismatch, gateIsSealed, gitGateLedgerPort } from "../../op/gate.js";
32
39
  import { resolveCliBuildParams, parseParamFlags } from "../build-params-cli.js";
33
40
  import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format.js";
34
41
  import { GATED_EXIT_CODE } from "./run.js";
42
+ import { redeployLine, releaseRollbackLine, rollbackTarget, unsettledComponents } from "../../lifecycle/mixed-environment.js";
35
43
  const PROMOTE_USAGE = "chant components promote --to <env> [--from <env>] [--allow-skip] [--release <label|digest>] [--component <name> [--digest <sha256:...>] | --digest <component>=<sha256:...> ...] [--dry-run] [--json]";
36
- const ROLLBACK_USAGE = "chant components rollback <env> --component <name> [--digest <sha256:...>] [--dry-run] [--json]";
44
+ const ROLLBACK_USAGE = "chant components rollback <env> (--component <name> [--digest <sha256:...>] | --release <label|digest>) [--dry-run] [--json]";
37
45
  const REDEPLOY_USAGE = "chant components redeploy <env> --component <name> [--digest <sha256:...>] [--dry-run] [--json]";
38
46
  function renderPlan(verb, plan, removed) {
39
47
  console.error(formatBold(verb === "promote" ? `promote ${plan.from} -> ${plan.to}` : `${verb} ${plan.to}`));
@@ -117,7 +125,8 @@ async function bindReleaseGate(input) {
117
125
  const releaseDigest = under.release.releaseDigest;
118
126
  // What the environment runs now, to compare each component with.
119
127
  const { readRelease } = await import("../../lifecycle/release-store.js");
120
- const latest = latestPerComponent((await readLedger(env)).filter((r) => r.env === env));
128
+ const envRecords = (await readLedger(env)).filter((r) => r.env === env);
129
+ const latest = latestPerComponent(envRecords);
121
130
  const releases = new Map();
122
131
  const current = new Map();
123
132
  for (const item of plan.items) {
@@ -129,6 +138,12 @@ async function bindReleaseGate(input) {
129
138
  releases.set(named, await readRelease(named).catch(() => null));
130
139
  current.set(item.component, { record, release: named !== undefined ? (releases.get(named) ?? null) : null });
131
140
  }
141
+ // #4035: a component a run left failed or gated runs something the ledger doesn't say.
142
+ const { readDeployOutcomes } = await import("../../lifecycle/deploy-outcome.js");
143
+ const unsettled = new Map();
144
+ for (const [component, u] of unsettledComponents(envRecords, await readDeployOutcomes(env).catch(() => []))) {
145
+ unsettled.set(component, `the ${u.outcome.verb} run ${u.outcome.runId} left ${component} ${u.state} in "${env}" and nothing has been recorded for it since, so what it runs is not known`);
146
+ }
132
147
  const doc = await gate.planReleaseChangeSet({
133
148
  release: under.release,
134
149
  env,
@@ -136,6 +151,7 @@ async function bindReleaseGate(input) {
136
151
  digests: new Map(plan.items.map((i) => [i.component, i.digest])),
137
152
  registry: input.registry,
138
153
  current,
154
+ unsettled,
139
155
  seededOutputs: input.seededOutputs,
140
156
  });
141
157
  const provisional = gate.provisionalMembers(doc);
@@ -359,7 +375,11 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
359
375
  const timestamp = new Date().toISOString();
360
376
  const recorded = [];
361
377
  let recordError;
362
- if (deployed.length > 0) {
378
+ // #4035: a run that applied partly, or failed, records what it did to each
379
+ // component, so the environment reads as mixed until it is settled.
380
+ const { deployOutcomeOf, appendDeployOutcome } = await import("../../lifecycle/deploy-outcome.js");
381
+ const outcome = deployOutcomeOf({ verb, plan, run, releaseDigest: under?.release.releaseDigest ?? null, runId, timestamp, actor: actor });
382
+ if (deployed.length > 0 || outcome) {
363
383
  try {
364
384
  for (const item of deployed) {
365
385
  const result = run.results.find((r) => r.component === item.component);
@@ -369,6 +389,8 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
369
389
  const { record: written } = await appendReleaseRecord(under ? { ...input, releaseDigest: under.release.releaseDigest } : input);
370
390
  recorded.push(written);
371
391
  }
392
+ if (outcome)
393
+ await appendDeployOutcome(outcome);
372
394
  await pushLifecycle();
373
395
  }
374
396
  catch (err) {
@@ -377,7 +399,7 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
377
399
  }
378
400
  if (args.json) {
379
401
  const withChangeSet = under && changeSetJson ? { release: { ...releaseJson.release, ...changeSetJson } } : releaseJson;
380
- console.log(JSON.stringify({ ...planJson(plan, removed), ...withChangeSet, run, recorded }, null, 2));
402
+ console.log(JSON.stringify({ ...planJson(plan, removed), ...withChangeSet, run, recorded, ...(outcome ? { outcome } : {}) }, null, 2));
381
403
  }
382
404
  else {
383
405
  for (const r of recorded) {
@@ -388,9 +410,20 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
388
410
  : `Redeployed ${formatBold(r.component)} in ${plan.to} at ${r.digest}`));
389
411
  }
390
412
  }
413
+ if (outcome && recordError === undefined) {
414
+ const unsettled = outcome.components.filter((c) => c.outcome === "failed" || c.outcome === "gated");
415
+ console.error(formatWarning({
416
+ message: `"${plan.to}" now runs a mix: ${outcome.components.map((c) => `${c.component} ${c.outcome}`).join(", ")}. ` +
417
+ `chant workspace status ${plan.to} --json lists what each component runs and the rollback line`,
418
+ }));
419
+ for (const c of unsettled)
420
+ console.error(formatInfo(`settle ${c.component}: ${redeployLine(plan.to, c.component)}, or run the same ${verb} again`));
421
+ }
391
422
  if (recordError !== undefined) {
392
423
  console.error(formatError({
393
- message: `deployed to "${plan.to}", but the release record was not written: ${recordError}`,
424
+ message: deployed.length > 0
425
+ ? `deployed to "${plan.to}", but the release record was not written: ${recordError}`
426
+ : `the outcome of the ${verb} in "${plan.to}" was not written: ${recordError}`,
394
427
  hint: `Pull the chant/lifecycle branch and check \`chant components status ${plan.to}\` before running this again.`,
395
428
  }));
396
429
  return 1;
@@ -436,6 +469,114 @@ function actorOrRefuse(ctx) {
436
469
  }
437
470
  return { actor };
438
471
  }
472
+ /** The revoked commits, or the exit code of a refusal already printed when the ci tags can't be judged (#4033). */
473
+ async function revokedOrRefuse(what) {
474
+ const { readRevokedCommits } = await import("../../lifecycle/release-revocation.js");
475
+ try {
476
+ return await readRevokedCommits(process.cwd());
477
+ }
478
+ catch (err) {
479
+ console.error(formatError({
480
+ message: `the ci tags can't be judged, so whether ${what} is revoked is unknown: ${err instanceof Error ? err.message : String(err)} [declaration-invalid]`,
481
+ hint: "Fix ci.green in chant.workspace.json at base; chant workspace check names the problem.",
482
+ }));
483
+ return 1;
484
+ }
485
+ }
486
+ /**
487
+ * Resolve `--release` for a promote or a rollback to `env` (#4026, #4035):
488
+ * the release, its label and its target for `env`. Refused, with the exit
489
+ * code returned, when the release can't be found, has no target for `env`,
490
+ * is of a project with no components (#4046), or was cut from a revoked
491
+ * commit (#4033), so a gate pending for it can't pass.
492
+ */
493
+ async function resolveUnderRelease(ref, env, verb, fix) {
494
+ const { resolveRelease } = await import("../../lifecycle/release-store.js");
495
+ const { targetFor, isImplicitRelease } = await import("../../components/release-promote.js");
496
+ const found = await resolveRelease(ref);
497
+ if (!found) {
498
+ console.error(formatError({ message: `no release is labelled or digested "${ref}" in this member`, hint: "List them with: chant release list" }));
499
+ return 1;
500
+ }
501
+ const target = targetFor(found.release, env);
502
+ if ("error" in target) {
503
+ console.error(formatError({ message: target.error }));
504
+ return 1;
505
+ }
506
+ // #4046: a release of a project with no components records build output
507
+ // and no component, so there is no deploy step here to point at it.
508
+ if (isImplicitRelease(found.release)) {
509
+ const name = found.label ?? found.release.releaseDigest;
510
+ console.error(formatError({
511
+ message: `release ${name} is of a project with no components, so ${verb} has no component to deploy`,
512
+ hint: `Write its "${env}" build output with \`chant release export ${name} --env ${env}\`, then run the project's own deploy against those files.`,
513
+ }));
514
+ return 1;
515
+ }
516
+ // #4033 (ws-105): a release cut from a revoked commit is never deployed,
517
+ // so a gate pending for it can't pass. Read from local tags, as the cut reads them.
518
+ const revoked = await revokedOrRefuse(`release ${found.label ?? found.release.releaseDigest}`);
519
+ if (typeof revoked === "number")
520
+ return revoked;
521
+ const { revocationOf, revokedRefusal } = await import("../../lifecycle/release-revocation.js");
522
+ const revocation = revocationOf(found.release, revoked);
523
+ if (revocation) {
524
+ console.error(formatError(revokedRefusal({ releaseDigest: found.release.releaseDigest, label: found.label }, revocation, await fix(found.release))));
525
+ return 1;
526
+ }
527
+ return { release: found.release, label: found.label, target: target.target };
528
+ }
529
+ /**
530
+ * The line that rolls `env` back past `exclude` (#4035): to the newest
531
+ * release in its ledger that is still kept and not revoked, by label, or
532
+ * null when there is none.
533
+ */
534
+ async function rollbackLineFor(env, records, exclude, revoked) {
535
+ const { readRelease, readCuts, labelsByDigest } = await import("../../lifecycle/release-store.js");
536
+ const { revocationOf } = await import("../../lifecycle/release-revocation.js");
537
+ const target = await rollbackTarget({
538
+ records,
539
+ exclude,
540
+ check: async (digest) => {
541
+ const release = await readRelease(digest).catch(() => null);
542
+ return { kept: release !== null, revoked: release !== null && revocationOf(release, revoked) !== null };
543
+ },
544
+ });
545
+ if (!target)
546
+ return null;
547
+ const labels = await readCuts().then((c) => labelsByDigest(c.cuts), () => new Map());
548
+ return releaseRollbackLine(env, target, labels.get(target));
549
+ }
550
+ /**
551
+ * Refuse a rollback or a redeploy that would put back a release cut from a
552
+ * revoked commit (#4033, #4035), naming the release to go back to instead.
553
+ * Returns the exit code of the refusal, or undefined when nothing restored
554
+ * names a revoked release.
555
+ */
556
+ async function refuseRevokedRestore(verb, plan, records) {
557
+ const named = [...new Set(plan.items.map((i) => i.source.releaseDigest).filter((d) => d !== undefined))];
558
+ if (named.length === 0)
559
+ return undefined;
560
+ const revoked = await revokedOrRefuse(`the release this ${verb} restores`);
561
+ if (typeof revoked === "number")
562
+ return revoked;
563
+ if (revoked.size === 0)
564
+ return undefined;
565
+ const { readRelease, readCuts, labelsByDigest } = await import("../../lifecycle/release-store.js");
566
+ const { revocationOf, revokedRefusal } = await import("../../lifecycle/release-revocation.js");
567
+ for (const digest of named) {
568
+ const release = await readRelease(digest).catch(() => null);
569
+ const revocation = release ? revocationOf(release, revoked) : null;
570
+ if (!revocation)
571
+ continue;
572
+ const labels = await readCuts().then((c) => labelsByDigest(c.cuts), () => new Map());
573
+ const back = await rollbackLineFor(plan.to, records, new Set([digest]), revoked);
574
+ console.error(formatError(revokedRefusal({ releaseDigest: digest, label: labels.get(digest) ?? null }, revocation, back ? `Restore a release cut from a green commit instead: ${back}` : `No other release "${plan.to}" ran is kept and green; promote a release cut from a green commit (\`chant ci last-green\` names the newest).`)));
575
+ console.error(formatError({ message: "nothing was deployed" }));
576
+ return 1;
577
+ }
578
+ return undefined;
579
+ }
439
580
  export async function runComponentsPromote(ctx) {
440
581
  const { args } = ctx;
441
582
  const to = args.migrateTo;
@@ -488,29 +629,10 @@ export async function runComponentsPromote(ctx) {
488
629
  // #4026: --release names the release this promote deploys, by label or digest.
489
630
  let under;
490
631
  if (args.release) {
491
- const { resolveRelease } = await import("../../lifecycle/release-store.js");
492
- const { targetFor, isImplicitRelease } = await import("../../components/release-promote.js");
493
- const found = await resolveRelease(args.release);
494
- if (!found) {
495
- console.error(formatError({ message: `no release is labelled or digested "${args.release}" in this member`, hint: "List them with: chant release list" }));
496
- return 1;
497
- }
498
- const target = targetFor(found.release, to);
499
- if ("error" in target) {
500
- console.error(formatError({ message: target.error }));
501
- return 1;
502
- }
503
- // #4046: a release of a project with no components records build output
504
- // and no component, so there is no deploy step here to point at it.
505
- if (isImplicitRelease(found.release)) {
506
- const name = found.label ?? found.release.releaseDigest;
507
- console.error(formatError({
508
- message: `release ${name} is of a project with no components, so promote has no component to deploy`,
509
- hint: `Write its "${to}" build output with \`chant release export ${name} --env ${to}\`, then run the project's own deploy against those files.`,
510
- }));
511
- return 1;
512
- }
513
- under = { release: found.release, label: found.label, target: target.target };
632
+ const found = await resolveUnderRelease(args.release, to, "promote", () => "Promote a release cut from a green commit: `chant ci last-green` names the newest, and `chant release list` marks the revoked releases. Fetch the tags first: git fetch origin --tags");
633
+ if (typeof found === "number")
634
+ return found;
635
+ under = found;
514
636
  }
515
637
  const plan = planPromotion({
516
638
  from,
@@ -530,20 +652,31 @@ export async function runComponentsPromote(ctx) {
530
652
  export async function runComponentsRollback(ctx) {
531
653
  const { args } = ctx;
532
654
  const env = args.extraPositional;
533
- if (!env || !args.component) {
534
- console.error(formatError({ message: "an environment and --component <name> are required", hint: ROLLBACK_USAGE }));
655
+ if (!env || (!args.component && !args.release)) {
656
+ console.error(formatError({ message: "an environment and --component <name> or --release <label|digest> are required", hint: ROLLBACK_USAGE }));
657
+ return 1;
658
+ }
659
+ if (args.component && args.release) {
660
+ console.error(formatError({ message: "--release rolls back every component of a release, so it does not take --component", hint: ROLLBACK_USAGE }));
661
+ return 1;
662
+ }
663
+ if (args.release && args.digest) {
664
+ console.error(formatError({ message: "--digest picks one release of one component, so it needs --component, not --release", hint: ROLLBACK_USAGE }));
535
665
  return 1;
536
666
  }
537
667
  const who = actorOrRefuse(ctx);
538
668
  if (typeof who === "number")
539
669
  return who;
670
+ if (args.release)
671
+ return runReleaseRollback(ctx, env, args.release, who.actor);
540
672
  const project = await loadProject(ctx, args.component);
541
673
  if (typeof project === "number")
542
674
  return project;
543
675
  await fetchLifecycle().catch(() => false);
676
+ const records = await readLedger(env);
544
677
  const plan = planRollback({
545
678
  env,
546
- records: await readLedger(env),
679
+ records,
547
680
  declared: project.targets.map((c) => c.name),
548
681
  component: args.component,
549
682
  ...(args.digest ? { digest: args.digest } : {}),
@@ -552,8 +685,48 @@ export async function runComponentsRollback(ctx) {
552
685
  console.error(formatError({ message: plan.error, hint: ROLLBACK_USAGE }));
553
686
  return 1;
554
687
  }
688
+ const refused = await refuseRevokedRestore("rollback", plan, records);
689
+ if (refused !== undefined)
690
+ return refused;
555
691
  return deployPlan(ctx, "rollback", plan, project, who.actor, rollbackRecord);
556
692
  }
693
+ /**
694
+ * `chant components rollback <env> --release <label|digest>` (#4035): a
695
+ * gated promote of an earlier release into `env`. Every component of the
696
+ * release is restored at the digest `env` recorded running it from that
697
+ * release, its deploy reads the templates the release recorded for `env`,
698
+ * and its gates bind the release's change set planned against what `env`
699
+ * runs now, as `promote --release` binds them (#4045).
700
+ */
701
+ async function runReleaseRollback(ctx, env, ref, actor) {
702
+ const project = await loadProject(ctx, "all");
703
+ if (typeof project === "number")
704
+ return project;
705
+ await fetchLifecycle().catch(() => false);
706
+ const records = await readLedger(env);
707
+ const under = await resolveUnderRelease(ref, env, "rollback", async (release) => {
708
+ const revoked = await revokedOrRefuse("the release before it").then((r) => (typeof r === "number" ? new Map() : r));
709
+ const back = await rollbackLineFor(env, records, new Set([release.releaseDigest]), revoked);
710
+ return back ? `Roll back to a release cut from a green commit: ${back}` : "Roll back to a release cut from a green commit; `chant release list` marks the revoked releases.";
711
+ });
712
+ if (typeof under === "number")
713
+ return under;
714
+ const { readDeployOutcomes } = await import("../../lifecycle/deploy-outcome.js");
715
+ const outcomes = await readDeployOutcomes(env).catch(() => []);
716
+ const plan = planReleaseRollback({
717
+ env,
718
+ records,
719
+ declared: project.targets.map((c) => c.name),
720
+ release: under.release,
721
+ label: under.label,
722
+ unsettled: new Set(unsettledComponents(records, outcomes).keys()),
723
+ });
724
+ if ("error" in plan) {
725
+ console.error(formatError({ message: plan.error, hint: ROLLBACK_USAGE }));
726
+ return 1;
727
+ }
728
+ return deployPlan(ctx, "rollback", plan, project, actor, rollbackRecord, under);
729
+ }
557
730
  export async function runComponentsRedeploy(ctx) {
558
731
  const { args } = ctx;
559
732
  const env = args.extraPositional;
@@ -568,9 +741,10 @@ export async function runComponentsRedeploy(ctx) {
568
741
  if (typeof project === "number")
569
742
  return project;
570
743
  await fetchLifecycle().catch(() => false);
744
+ const records = await readLedger(env);
571
745
  const plan = planRedeploy({
572
746
  env,
573
- records: await readLedger(env),
747
+ records,
574
748
  declared: project.targets.map((c) => c.name),
575
749
  component: args.component,
576
750
  ...(args.digest ? { digest: args.digest } : {}),
@@ -579,5 +753,8 @@ export async function runComponentsRedeploy(ctx) {
579
753
  console.error(formatError({ message: plan.error, hint: REDEPLOY_USAGE }));
580
754
  return 1;
581
755
  }
756
+ const refused = await refuseRevokedRestore("redeploy", plan, records);
757
+ if (refused !== undefined)
758
+ return refused;
582
759
  return deployPlan(ctx, "redeploy", plan, project, who.actor, redeployRecord);
583
760
  }
@@ -1,10 +1,22 @@
1
1
  /**
2
2
  * `chant release` (#4026, ws-104): the release is what graduates.
3
3
  *
4
- * release cut [<label>] [--build <command>] [--param k=v]... [--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>] [--actor <name>] [--sign [<key file>]] [--json]
5
- * cut a release of this member from the checkout's HEAD, which must be green;
4
+ * release cut [<label>] [--yes] [--build <command>] [--param k=v]... [--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>] [--actor <name>] [--sign [<key file>]] [--json]
5
+ * a dry run of a cut of this member from the checkout's HEAD, which must be
6
+ * clean, on trunk and pushed, and green (#4027); `--yes` cuts, records,
7
+ * and tags the commit `release/<label>` locally;
6
8
  * --sign signs the cut with the actor's ssh key (#4031); `--src`, `-o` and
7
9
  * `--lexicon` shape the build of a project with no components (#4046)
10
+ * release publish <label|digest> [--yes] [--allow-unsigned] [--require-provenance] [--json]
11
+ * publish a cut release (#4027) to the targets release.publish declares
12
+ * (#4047): a dry run unless --yes; refuses a revoked one, one with no
13
+ * signature that verifies against .chant/allowed_signers unless
14
+ * --allow-unsigned (#4049), and with a target a checkout that is not
15
+ * the release's commit; warns with no OIDC provenance, and refuses
16
+ * under --require-provenance; attaches SBOMs and provenance (#4049)
17
+ * release verify <label|digest> [--json]
18
+ * check the release's signature offline against .chant/allowed_signers
19
+ * at the release's commit (#4049)
8
20
  * release list [--json]
9
21
  * every release of this member with its targets, its cuts and where it runs;
10
22
  * `--json` prints the read contract's `releases` document
@@ -13,12 +25,57 @@
13
25
  * release compile --env <env> [--build <command>] [--artifacts --component <a,b>] --json
14
26
  * internal: what the cut runs in a child process per environment
15
27
  *
16
- * The workstation UX for `cut` grows in #4027. A declaration whose
17
- * `identity.gates` names a `release` gate requires a signed cut by an actor
18
- * in its class (#4031).
28
+ * The workstation checks, the actor and the tag are in
29
+ * ../../lifecycle/release-workstation.ts, and the publish contract in
30
+ * ../../lifecycle/release-publish.ts. A declaration whose `identity.gates`
31
+ * names a `release` gate requires a signed cut by an actor in its class (#4031).
19
32
  */
20
33
  import type { CommandContext } from "../registry.js";
34
+ /** What to run after a cut (#4027): publish from CI, or push the tag so CI publishes, or deploy the first environment. */
35
+ export declare function nextCommands(req: {
36
+ ref: string;
37
+ tag: string | null;
38
+ inCi: boolean;
39
+ firstEnv: string | null;
40
+ /** A project with no components deploys with `release export`, not promote (#4046). */
41
+ noComponents: boolean;
42
+ }): string[];
43
+ /** The command line that ran, without `--json`, with `--yes` added: what a dry run says to run next. */
44
+ export declare function sameWithYes(argv: readonly string[]): string;
45
+ /**
46
+ * `release cut [<label>]` (#4026, #4027). A dry run unless `--yes`: it
47
+ * refuses a dirty tree, a commit that is not on trunk and pushed, and one
48
+ * that is not green, compiles every environment, and prints what the cut
49
+ * would record, build and tag, and what publishes where. With `--yes` it
50
+ * cuts, signs with `--sign`, records the cut with its actor and run id,
51
+ * tags the commit locally and prints the next command.
52
+ */
21
53
  export declare function runReleaseCut(ctx: CommandContext): Promise<number>;
54
+ /**
55
+ * `release publish <label|digest> [--yes]` (#4027, #4047): publish a cut
56
+ * release to the targets the member declares under `release.publish` in
57
+ * its `chant.config.ts`. It refuses a release no cut names, one cut from a
58
+ * revoked commit, one with no signature that verifies against the signers
59
+ * file at base unless `--allow-unsigned` (#4049; never under
60
+ * identity.gates.release), and, when there is a target, a checkout that is
61
+ * not the release's commit with a clean tree. It warns before publishing
62
+ * when the run has no OIDC token, so what it publishes carries no
63
+ * provenance, and refuses under `--require-provenance`. Each target attaches
64
+ * an SBOM and the release's provenance statement (#4049). Every
65
+ * target is planned (its files read and checked, its credentials found)
66
+ * before any publishes. Without `--yes` it is a dry run that prints the plan
67
+ * and uploads nothing. With `--yes` it stages every target, then reveals them
68
+ * (#4048, `runPublish`), recording each step in `_releases/publishes.jsonl`,
69
+ * so running it again after a failure resumes. Every line is redacted.
70
+ */
71
+ export declare function runReleasePublish(ctx: CommandContext): Promise<number>;
72
+ /**
73
+ * `release verify <label|digest> [--json]` (#4049): check, offline, that the
74
+ * release was signed by a key `.chant/allowed_signers` lists at the release's
75
+ * commit, and that its file is the digest of what it holds. Exits 0 when it
76
+ * verifies and 1 when it does not or can't be checked.
77
+ */
78
+ export declare function runReleaseVerify(ctx: CommandContext): Promise<number>;
22
79
  export declare function runReleaseList(ctx: CommandContext): Promise<number>;
23
80
  /**
24
81
  * `release export <label|digest> --env <env> [-o <dir>]` (#4046): write each
@@ -1 +1 @@
1
- {"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/release.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuBlD,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoDxE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBzE;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC3E;AAED,gHAAgH;AAChH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB5E;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5E"}
1
+ {"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/release.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAmBlD,0HAA0H;AAC1H,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uFAAuF;IACvF,YAAY,EAAE,OAAO,CAAC;CACvB,GAAG,MAAM,EAAE,CASX;AAED,wGAAwG;AACxG,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAG3D;AAiBD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyMxE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2G5E;AAQD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAkC3E;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BzE;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC3E;AAED,gHAAgH;AAChH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB5E;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5E"}