@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,117 @@
1
+ /**
2
+ * `chant release verify` and the publish's signature check, end to end
3
+ * (#4049), in a temp repo with a temp bare remote and throwaway ssh keys. A
4
+ * release cut signed with a key `.chant/allowed_signers` lists verifies, and a
5
+ * publish takes it; an unsigned one and one signed by a key the file does not
6
+ * list fail `release verify`, and a publish refuses them unless
7
+ * `--allow-unsigned`. Nothing is published: the member declares no target.
8
+ */
9
+
10
+ import { describe, expect, test } from "vitest";
11
+ import { execFileSync, spawnSync } from "node:child_process";
12
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ import { REPO } from "../../workspace/__fixtures__/contract-repo";
17
+ import { hasSshKeygen } from "../../workspace/trust/test-repo";
18
+
19
+ const CHANT = [process.execPath, "--import", pathToFileURL(join(REPO, "node_modules", "tsx", "dist", "loader.mjs")).href, join(REPO, "packages", "core", "src", "cli", "main.ts")];
20
+ const CI_VARS = ["CI", "GITHUB_ACTIONS", "GITHUB_RUN_ID", "GITHUB_SHA", "GITHUB_ACTOR", "ACTIONS_ID_TOKEN_REQUEST_URL", "ACTIONS_ID_TOKEN_REQUEST_TOKEN", "GITLAB_CI", "CI_PIPELINE_ID", "GITLAB_USER_LOGIN", "CHANT_ENV"];
21
+
22
+ function chant(cwd: string, args: string[]): { code: number; stdout: string; stderr: string } {
23
+ const env: NodeJS.ProcessEnv = { ...process.env, USER: "tester" };
24
+ for (const k of CI_VARS) delete env[k];
25
+ const r = spawnSync(CHANT[0]!, [...CHANT.slice(1), ...args], { cwd, encoding: "utf-8", env, timeout: 120_000 });
26
+ return { code: r.status ?? 1, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
27
+ }
28
+
29
+ function git(cwd: string, ...args: string[]): string {
30
+ const r = spawnSync("git", args, { cwd, encoding: "utf-8" });
31
+ if (r.status !== 0) throw new Error(r.stderr);
32
+ return r.stdout.trim();
33
+ }
34
+
35
+ function key(root: string, name: string): { file: string; pub: string } {
36
+ const file = join(root, `key-${name}`);
37
+ execFileSync("ssh-keygen", ["-q", "-t", "ed25519", "-N", "", "-C", name, "-f", file]);
38
+ return { file, pub: readFileSync(`${file}.pub`, "utf-8").trim().split(" ").slice(0, 2).join(" ") };
39
+ }
40
+
41
+ const BUILD = `mkdir -p dist && printf '{"env":"%s"}' "$CHANT_ENV" > dist/api.template.json`;
42
+
43
+ describe("chant release verify", () => {
44
+ test.skipIf(!hasSshKeygen)(
45
+ "passes for a signed release, fails for an unsigned one and for one signed by an unlisted key; a publish refuses both unless --allow-unsigned",
46
+ () => {
47
+ const root = mkdtempSync(join(tmpdir(), "chant-release-verify-"));
48
+ try {
49
+ const alice = key(root, "alice");
50
+ const mallory = key(root, "mallory");
51
+ const dir = join(root, "work");
52
+ const remote = join(root, "origin.git");
53
+ git(root, "init", "-q", "--bare", "-b", "main", remote);
54
+ git(root, "init", "-q", "-b", "main", dir);
55
+ git(dir, "config", "user.email", "t@chant.dev");
56
+ git(dir, "config", "user.name", "T");
57
+ writeFileSync(join(dir, "chant.config.ts"), `export default { environments: ["dev"] };\n`);
58
+ writeFileSync(join(dir, "api.component.ts"), `export const api = { name: "api", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "cfn-deploy", template: "dist/api.template.json" }] }] };\n`);
59
+ writeFileSync(join(dir, ".gitignore"), "dist/\n");
60
+ mkdirSync(join(dir, ".chant"));
61
+ writeFileSync(join(dir, ".chant", "allowed_signers"), `alice ${alice.pub}\n`);
62
+ git(dir, "add", ".");
63
+ git(dir, "commit", "-q", "-m", "init");
64
+ git(dir, "remote", "add", "origin", remote);
65
+ // A green commit pushed to trunk, ready to cut.
66
+ const next = (message?: string) => {
67
+ if (message) git(dir, "commit", "-q", "--allow-empty", "-m", message);
68
+ git(dir, "push", "-q", "origin", "main");
69
+ git(dir, "fetch", "-q", "origin");
70
+ git(dir, "tag", `ci/green/${git(dir, "rev-parse", "HEAD")}`);
71
+ };
72
+ next();
73
+
74
+ // v1: signed with alice's key, which the signers file lists.
75
+ const signed = chant(dir, ["release", "cut", "v1", "--build", BUILD, "--sign", alice.file, "--yes"]);
76
+ expect(signed.code, signed.stderr).toBe(0);
77
+ const ok = chant(dir, ["release", "verify", "v1"]);
78
+ expect(ok.code, ok.stderr).toBe(0);
79
+ expect(ok.stderr).toMatch(/Verified .*v1.*: signed by alice, checked against \.chant\/allowed_signers at [0-9a-f]{12}/);
80
+ expect(JSON.parse(chant(dir, ["release", "verify", "v1", "--json"]).stdout)).toMatchObject({ label: "v1", status: "verified", digestMatches: true, verifiedBy: { actor: "alice" } });
81
+ const pubSigned = chant(dir, ["release", "publish", "v1"]);
82
+ expect(pubSigned.code, pubSigned.stderr).toBe(0);
83
+ expect(pubSigned.stderr).toContain("signed by alice");
84
+
85
+ // v2: not signed.
86
+ next("v2");
87
+ expect(chant(dir, ["release", "cut", "v2", "--build", BUILD, "--yes"]).code).toBe(0);
88
+ const unsigned = chant(dir, ["release", "verify", "v2"]);
89
+ expect(unsigned.code).toBe(1);
90
+ expect(unsigned.stderr).toMatch(/v2.* does not verify: no cut of the release carries a signature \[release-unsigned\]/);
91
+ expect(JSON.parse(chant(dir, ["release", "verify", "v2", "--json"]).stdout)).toMatchObject({ status: "unsigned", error: { code: "release-unsigned" } });
92
+ const pubUnsigned = chant(dir, ["release", "publish", "v2"]);
93
+ expect(pubUnsigned.code).toBe(1);
94
+ expect(pubUnsigned.stderr).toMatch(/\[release-unsigned\]/);
95
+ expect(chant(dir, ["release", "publish", "v2", "--allow-unsigned"]).code).toBe(0);
96
+
97
+ // v3: signed by mallory, whom the signers file does not list.
98
+ next("v3");
99
+ const cut3 = chant(dir, ["release", "cut", "v3", "--build", BUILD, "--sign", mallory.file, "--actor", "mallory", "--yes"]);
100
+ expect(cut3.code, cut3.stderr).toBe(0);
101
+ const unlisted = chant(dir, ["release", "verify", "v3"]);
102
+ expect(unlisted.code).toBe(1);
103
+ expect(unlisted.stderr).toMatch(/mallory has no key in \.chant\/allowed_signers at [0-9a-f]{12}.*\[release-signature-unverified\]/);
104
+ const pubUnlisted = chant(dir, ["release", "publish", "v3"]);
105
+ expect(pubUnlisted.code).toBe(1);
106
+ expect(pubUnlisted.stderr).toMatch(/\[release-signature-unverified\]/);
107
+
108
+ const missing = chant(dir, ["release", "verify", "v9"]);
109
+ expect(missing.code).toBe(1);
110
+ expect(missing.stderr).toMatch(/\[release-not-found\]/);
111
+ } finally {
112
+ rmSync(root, { recursive: true, force: true });
113
+ }
114
+ },
115
+ 240_000,
116
+ );
117
+ });
@@ -0,0 +1,135 @@
1
+ /**
2
+ * #4027 requirement 3: the same command cuts the same release on a
3
+ * workstation and in CI. Two clones of one commit, each with its own temp
4
+ * bare remote, run `chant release cut v1 --yes`, one with a workstation's
5
+ * environment and one with GitHub Actions'. The records are equivalent:
6
+ * the release files are byte-identical, and the cut lines differ only in
7
+ * the run id and its origin, the actor and the timestamp.
8
+ */
9
+
10
+ import { describe, test, expect } from "vitest";
11
+ import { spawnSync } from "node:child_process";
12
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ import { REPO } from "../../workspace/__fixtures__/contract-repo";
17
+
18
+ const CHANT = [process.execPath, "--import", pathToFileURL(join(REPO, "node_modules", "tsx", "dist", "loader.mjs")).href, join(REPO, "packages", "core", "src", "cli", "main.ts")];
19
+
20
+ const CI_VARS = ["CI", "GITHUB_ACTIONS", "GITHUB_RUN_ID", "GITHUB_SHA", "GITHUB_ACTOR", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITLAB_CI", "CI_PIPELINE_ID", "GITLAB_USER_LOGIN", "CHANT_ENV"];
21
+
22
+ function chant(cwd: string, args: string[], extra: Record<string, string>): { code: number; stdout: string; stderr: string } {
23
+ const env: NodeJS.ProcessEnv = { ...process.env };
24
+ for (const k of CI_VARS) delete env[k];
25
+ Object.assign(env, extra);
26
+ const r = spawnSync(CHANT[0], [...CHANT.slice(1), ...args], { cwd, encoding: "utf-8", env, timeout: 120_000 });
27
+ return { code: r.status ?? 1, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
28
+ }
29
+
30
+ function git(cwd: string, ...args: string[]): string {
31
+ const r = spawnSync("git", args, { cwd, encoding: "utf-8" });
32
+ if (r.status !== 0) throw new Error(`git ${args.join(" ")}: ${r.stderr}`);
33
+ return r.stdout.trim();
34
+ }
35
+
36
+ const BUILD = `mkdir -p dist && printf '{"env":"%s"}' "$CHANT_ENV" > dist/api.template.json`;
37
+
38
+ /** Every file under `_releases/` on the clone's chant/lifecycle, by path, as bytes. */
39
+ function releaseFiles(dir: string): Map<string, string> {
40
+ const out = new Map<string, string>();
41
+ for (const path of git(dir, "ls-tree", "-r", "--name-only", "chant/lifecycle", "_releases").split("\n").filter(Boolean)) {
42
+ if (path.endsWith("cuts.jsonl")) continue;
43
+ out.set(path, git(dir, "show", `chant/lifecycle:${path}`));
44
+ }
45
+ return out;
46
+ }
47
+
48
+ describe("a release cut on a workstation and one cut in CI (#4027)", () => {
49
+ test(
50
+ "from the same commit produce the same release files, and cut lines that differ only in run id, run origin, actor and timestamp",
51
+ () => {
52
+ const root = mkdtempSync(join(tmpdir(), "chant-release-equiv-"));
53
+ try {
54
+ const seed = join(root, "seed");
55
+ git(root, "init", "-q", "-b", "main", seed);
56
+ git(seed, "config", "user.email", "seed@chant.dev");
57
+ git(seed, "config", "user.name", "Seed");
58
+ writeFileSync(join(seed, "chant.config.ts"), `export default { environments: ["dev", "prod"] };\n`);
59
+ writeFileSync(
60
+ join(seed, "api.component.ts"),
61
+ `export const api = { name: "api", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "cfn-deploy", template: "dist/api.template.json" }] }] };\n`,
62
+ );
63
+ writeFileSync(join(seed, ".gitignore"), "dist/\n");
64
+ git(seed, "add", ".");
65
+ git(seed, "commit", "-q", "-m", "init");
66
+ const sha = git(seed, "rev-parse", "HEAD");
67
+
68
+ // Each clone pushes to a bare remote of its own, which holds main; the green tag is made locally in each.
69
+ const clone = (name: string, email: string | null): string => {
70
+ const dir = join(root, name);
71
+ git(root, "init", "-q", "--bare", "-b", "main", `${name}.git`);
72
+ git(root, "clone", "-q", seed, dir);
73
+ git(dir, "remote", "set-url", "origin", join(root, `${name}.git`));
74
+ git(dir, "push", "-q", "origin", "main");
75
+ git(dir, "fetch", "-q", "origin");
76
+ if (email) git(dir, "config", "user.email", email);
77
+ git(dir, "tag", `ci/green/${sha}`);
78
+ return dir;
79
+ };
80
+ const laptop = clone("laptop", "alice@example.com");
81
+ const runner = clone("runner", null);
82
+
83
+ const workstation = { USER: "alice" };
84
+ const ci = {
85
+ CI: "true",
86
+ GITHUB_ACTIONS: "true",
87
+ GITHUB_RUN_ID: "4242",
88
+ GITHUB_ACTOR: "release-bot",
89
+ GITHUB_REPOSITORY: "acme/app",
90
+ GITHUB_SERVER_URL: "https://github.com",
91
+ GITHUB_SHA: sha,
92
+ USER: "runner",
93
+ };
94
+ const cut = (dir: string, env: Record<string, string>) => {
95
+ const r = chant(dir, ["release", "cut", "v1", "--build", BUILD, "--yes", "--json"], env);
96
+ expect(r.code, r.stderr).toBe(0);
97
+ return JSON.parse(r.stdout);
98
+ };
99
+ const a = cut(laptop, workstation);
100
+ const b = cut(runner, ci);
101
+
102
+ // The release is the same object, stored as the same bytes.
103
+ expect(b.release).toEqual(a.release);
104
+ const [filesA, filesB] = [releaseFiles(laptop), releaseFiles(runner)];
105
+ expect([...filesA.keys()].sort()).toEqual([...filesB.keys()].sort());
106
+ expect(filesA.size).toBeGreaterThan(0);
107
+ for (const [path, bytes] of filesA) expect(filesB.get(path), path).toBe(bytes);
108
+
109
+ // The cut lines, as stored, are equal apart from the run, the actor and the time.
110
+ const line = (dir: string) => JSON.parse(git(dir, "show", "chant/lifecycle:_releases/cuts.jsonl"));
111
+ const [la, lb] = [line(laptop), line(runner)];
112
+ const rest = ({ runId: _r, runOrigin: _o, actor: _a, timestamp: _t, ...others }: Record<string, unknown>) => others;
113
+ expect(rest(lb)).toEqual(rest(la));
114
+ expect(Object.keys(la).sort()).toEqual(Object.keys(lb).sort());
115
+
116
+ expect(la).toMatchObject({ actor: "alice@example.com", runId: expect.stringMatching(/^local-\d+$/), runOrigin: { forge: "local" }, signature: null });
117
+ expect(lb).toMatchObject({
118
+ actor: "release-bot",
119
+ runId: "4242",
120
+ runOrigin: { forge: "github", repo: "acme/app", url: "https://github.com/acme/app/actions/runs/4242" },
121
+ signature: null,
122
+ });
123
+
124
+ // Both tag the commit the same way; the next command differs by where it ran.
125
+ expect(a.tag).toEqual({ name: "release/v1", created: true });
126
+ expect(b.tag).toEqual({ name: "release/v1", created: true });
127
+ expect(a.next[0]).toBe("git push origin release/v1");
128
+ expect(b.next[0]).toBe("chant release publish v1");
129
+ } finally {
130
+ rmSync(root, { recursive: true, force: true });
131
+ }
132
+ },
133
+ 240_000,
134
+ );
135
+ });
@@ -0,0 +1,199 @@
1
+ /**
2
+ * `chant release cut`, `publish` and `list` end to end (#4026, #4027): the cut
3
+ * compiles each environment in a child chant with CHANT_ENV set, in a temp
4
+ * repo with a temp bare remote, and the list prints the read contract's
5
+ * `releases` document. No cloud is touched: the fixture's deploy is never
6
+ * run, no tag is pushed, and nothing is published: this member declares no
7
+ * publish target (release-publish-targets.e2e.test.ts publishes to stand-ins).
8
+ */
9
+
10
+ import { describe, test, expect } from "vitest";
11
+ import { spawnSync } from "node:child_process";
12
+ import { mkdtempSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ import { contract, REPO } from "../../workspace/__fixtures__/contract-repo";
17
+ import releasesSchema from "../../workspace/releases.schema.json";
18
+ import { contentDigest } from "../../content-digest";
19
+ import { sameWithYes } from "./release";
20
+
21
+ const CHANT = [process.execPath, "--import", pathToFileURL(join(REPO, "node_modules", "tsx", "dist", "loader.mjs")).href, join(REPO, "packages", "core", "src", "cli", "main.ts")];
22
+
23
+ /** The CI variables a run in this suite may inherit, removed so the cut reads as a workstation's unless a test sets them. */
24
+ const CI_VARS = [
25
+ "CI",
26
+ "GITHUB_ACTIONS",
27
+ "GITHUB_RUN_ID",
28
+ "GITHUB_SHA",
29
+ "GITHUB_ACTOR",
30
+ "GITHUB_REPOSITORY",
31
+ "GITHUB_SERVER_URL",
32
+ "ACTIONS_ID_TOKEN_REQUEST_URL",
33
+ "ACTIONS_ID_TOKEN_REQUEST_TOKEN",
34
+ "GITLAB_CI",
35
+ "CI_PIPELINE_ID",
36
+ "GITLAB_USER_LOGIN",
37
+ "CHANT_ENV",
38
+ ];
39
+
40
+ function chant(cwd: string, args: string[], extra: Record<string, string> = {}): { code: number; stdout: string; stderr: string } {
41
+ const env: NodeJS.ProcessEnv = { ...process.env, USER: "tester" };
42
+ for (const k of CI_VARS) delete env[k];
43
+ Object.assign(env, extra);
44
+ const r = spawnSync(CHANT[0], [...CHANT.slice(1), ...args], { cwd, encoding: "utf-8", env, timeout: 120_000 });
45
+ return { code: r.status ?? 1, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
46
+ }
47
+
48
+ function git(cwd: string, ...args: string[]): string {
49
+ const r = spawnSync("git", args, { cwd, encoding: "utf-8" });
50
+ if (r.status !== 0) throw new Error(r.stderr);
51
+ return r.stdout.trim();
52
+ }
53
+
54
+ const BUILD = `mkdir -p dist && printf '{"env":"%s"}' "$CHANT_ENV" > dist/api.template.json`;
55
+
56
+ /** A member at `<root>/work` with one commit on main pushed to `<root>/origin.git`. */
57
+ function project(root: string): { dir: string; sha: string; remote: string } {
58
+ const dir = join(root, "work");
59
+ const remote = join(root, "origin.git");
60
+ git(root, "init", "-q", "--bare", "-b", "main", remote);
61
+ git(root, "init", "-q", "-b", "main", dir);
62
+ git(dir, "config", "user.email", "t@chant.dev");
63
+ git(dir, "config", "user.name", "T");
64
+ writeFileSync(join(dir, "chant.config.ts"), `export default { environments: ["dev", "prod", "pr-*"] };\n`);
65
+ writeFileSync(
66
+ join(dir, "api.component.ts"),
67
+ `export const api = { name: "api", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "cfn-deploy", template: "dist/api.template.json" }] }] };\n`,
68
+ );
69
+ writeFileSync(join(dir, ".gitignore"), "dist/\n");
70
+ git(dir, "add", ".");
71
+ git(dir, "commit", "-q", "-m", "init");
72
+ git(dir, "remote", "add", "origin", remote);
73
+ git(dir, "push", "-q", "origin", "main");
74
+ git(dir, "fetch", "-q", "origin");
75
+ return { dir, sha: git(dir, "rev-parse", "HEAD"), remote };
76
+ }
77
+
78
+ const hasRef = (dir: string, ref: string) => spawnSync("git", ["rev-parse", "--verify", "--quiet", ref], { cwd: dir }).status === 0;
79
+
80
+ describe("chant release cut, publish and list", () => {
81
+ test(
82
+ "refuses a dirty tree, a commit not on trunk or not pushed, and one that isn't green; a dry run writes nothing; --yes cuts, tags and names the next command",
83
+ () => {
84
+ const root = mkdtempSync(join(tmpdir(), "chant-release-cut-"));
85
+ try {
86
+ const { dir, sha, remote } = project(root);
87
+ const cut = (...extra: string[]) => chant(dir, ["release", "cut", "v1", "--build", BUILD, ...extra]);
88
+
89
+ writeFileSync(join(dir, "extra.component.ts"), "export const extra = {};\n");
90
+ expect(cut().stderr).toMatch(/1 untracked file\(s\) such as extra\.component\.ts.*\[release-worktree-dirty\]/);
91
+ unlinkSync(join(dir, "extra.component.ts"));
92
+ writeFileSync(join(dir, "chant.config.ts"), `export default { environments: ["dev"] };\n`);
93
+ expect(cut().stderr).toMatch(/1 tracked file\(s\) with uncommitted changes.*\[release-worktree-dirty\]/);
94
+ git(dir, "checkout", "--", "chant.config.ts");
95
+
96
+ git(dir, "checkout", "-q", "-b", "feature");
97
+ git(dir, "commit", "-q", "--allow-empty", "-m", "feature");
98
+ expect(cut().stderr).toMatch(/is not on origin\/main.*\[release-commit-not-on-trunk\]/);
99
+ git(dir, "checkout", "-q", "main");
100
+ git(dir, "commit", "-q", "--allow-empty", "-m", "unpushed");
101
+ expect(cut().stderr).toMatch(/is on main( \(the branch origin\/HEAD names\))? but not on origin\/main, so it has not been pushed \[release-commit-not-pushed\]/);
102
+ git(dir, "reset", "-q", "--hard", sha);
103
+
104
+ const refused = cut();
105
+ expect(refused.code).toBe(1);
106
+ expect(refused.stderr).toMatch(/has no ci\/green tag.*\[release-commit-not-green\]/);
107
+ git(dir, "tag", `ci/green/${sha}`);
108
+
109
+ // A dry run by default: it compiles and prints the plan, and writes no ledger and no tag.
110
+ const dry = cut();
111
+ expect(dry.code, dry.stderr).toBe(0);
112
+ expect(dry.stdout).toMatch(/^Dry run: cut .*v1.* from commit [0-9a-f]{12} \(on origin\/main, green\)/m);
113
+ expect(dry.stdout).toContain(" actor t@chant.dev (from git user.email)");
114
+ expect(dry.stdout).toContain(" tag release/v1, made here and not pushed");
115
+ expect(dry.stdout).toContain(" dev: 1 template(s)");
116
+ expect(dry.stdout).toContain("chant release publish v1: nothing, since this member declares no publish target (release.publish in chant.config.ts)");
117
+ expect(dry.stderr).toContain(`Dry run: nothing was cut, signed or tagged. Run again with --yes to cut: ${sameWithYes(["release", "cut", "v1", "--build", BUILD])}`);
118
+ const dryJson = JSON.parse(cut("--json").stdout);
119
+ expect(dryJson).toMatchObject({ dryRun: true, label: "v1", commit: sha, actor: "t@chant.dev", actorSource: "git", tag: { name: "release/v1", exists: false }, build: [] });
120
+ expect(dryJson.releaseDigest).toMatch(/^jcs1-sha256:/);
121
+ expect(hasRef(dir, "refs/heads/chant/lifecycle")).toBe(false);
122
+ expect(hasRef(dir, "refs/tags/release/v1")).toBe(false);
123
+
124
+ const done = cut("--yes", "--json");
125
+ expect(done.code, done.stderr).toBe(0);
126
+ const result = JSON.parse(done.stdout);
127
+ expect(result).toMatchObject({ dryRun: false, label: "v1", actor: "t@chant.dev", actorSource: "git", tag: { name: "release/v1", created: true } });
128
+ expect(result.release.releaseDigest).toBe(dryJson.releaseDigest);
129
+ expect(result.release.commit).toBe(sha);
130
+ expect(result.release.targets).toEqual([
131
+ { env: "dev", params: [], templates: [{ component: "api", path: "dist/api.template.json", digest: contentDigest(`{"env":"dev"}`) }] },
132
+ { env: "prod", params: [], templates: [{ component: "api", path: "dist/api.template.json", digest: contentDigest(`{"env":"prod"}`) }] },
133
+ ]);
134
+ expect(result.cut).toMatchObject({ actor: "t@chant.dev", runId: expect.stringMatching(/^local-\d+$/), runOrigin: { forge: "local" }, signature: null });
135
+ expect(result.next).toEqual(["git push origin release/v1", "chant release publish v1", "chant components promote --release v1 --to dev"]);
136
+ expect(git(dir, "rev-parse", "release/v1^{commit}")).toBe(sha);
137
+ // chant pushes its ledger branch to the remote, and never a tag.
138
+ expect(git(root, "ls-remote", "--tags", remote)).toBe("");
139
+
140
+ const again = chant(dir, ["release", "cut", "--build", BUILD, "--yes"]);
141
+ expect(again.code, again.stderr).toBe(0);
142
+ expect(again.stderr).toContain("Already cut as");
143
+ expect(again.stderr).toContain("tag release/v1 (already there), not pushed");
144
+ expect(again.stderr).toContain("Next: git push origin release/v1");
145
+
146
+ const list = chant(dir, ["release", "list", "--json"]);
147
+ expect(list.code, list.stderr).toBe(0);
148
+ const doc = JSON.parse(list.stdout);
149
+ contract(releasesSchema).expectValid(doc);
150
+ expect(doc.releases).toHaveLength(1);
151
+ expect(doc.releases[0]).toMatchObject({ releaseDigest: result.release.releaseDigest, label: "v1", environments: [] });
152
+ expect(doc.releases[0].cuts[0]).toMatchObject({ runId: result.cut.runId, runOrigin: { forge: "local" } });
153
+
154
+ // #4049: the cut is not signed, so a publish refuses it unless --allow-unsigned.
155
+ const unsignedPub = chant(dir, ["release", "publish", "v1"]);
156
+ expect(unsignedPub.code).toBe(1);
157
+ expect(unsignedPub.stderr).toMatch(/v1 has no signed cut.*\[release-unsigned\]/);
158
+ expect(unsignedPub.stderr).toContain("pass --allow-unsigned");
159
+
160
+ // A publish is a dry run without --yes, as a cut is.
161
+ const dryPub = chant(dir, ["release", "publish", "v1", "--allow-unsigned"]);
162
+ expect(dryPub.code, dryPub.stderr).toBe(0);
163
+ expect(dryPub.stderr).toContain("v1 has no signed cut; publishing it anyway under --allow-unsigned");
164
+ expect(dryPub.stdout).toContain("What would be published where:\n nothing: this member declares no publish target (release.publish in chant.config.ts)");
165
+ expect(dryPub.stderr).toContain("Dry run: nothing was published. Run again with --yes to publish: chant release publish v1 --allow-unsigned --yes");
166
+
167
+ // Publish from the workstation: the warning comes before anything else is said about publishing.
168
+ const pub = chant(dir, ["release", "publish", "v1", "--allow-unsigned", "--yes"]);
169
+ expect(pub.code, pub.stderr).toBe(0);
170
+ const warning = pub.stderr.indexOf("this publish runs without OIDC, so what it publishes carries no provenance");
171
+ const nothing = pub.stderr.indexOf("Nothing was published: this member declares no publish target (release.publish in chant.config.ts).");
172
+ expect(warning).toBeGreaterThan(-1);
173
+ expect(nothing).toBeGreaterThan(warning);
174
+ expect(pub.stderr).toContain("chant components promote --release v1 --to dev");
175
+
176
+ // In GitHub Actions with id-token: write there is no warning.
177
+ const oidc = { GITHUB_ACTIONS: "true", ACTIONS_ID_TOKEN_REQUEST_URL: "https://token.example", ACTIONS_ID_TOKEN_REQUEST_TOKEN: "t" };
178
+ const fromCi = chant(dir, ["release", "publish", "v1", "--allow-unsigned", "--json"], oidc);
179
+ expect(fromCi.code, fromCi.stderr).toBe(0);
180
+ expect(fromCi.stderr).not.toContain("without OIDC");
181
+ expect(JSON.parse(fromCi.stdout)).toMatchObject({
182
+ dryRun: true,
183
+ label: "v1",
184
+ provenance: { oidc: true, ci: "github" },
185
+ warnings: ["v1 has no signed cut; publishing it anyway under --allow-unsigned, so chant release verify v1 will fail for it"],
186
+ targets: [],
187
+ published: [],
188
+ });
189
+
190
+ const unknown = chant(dir, ["release", "publish", "v9"]);
191
+ expect(unknown.code).toBe(1);
192
+ expect(unknown.stderr).toMatch(/\[release-not-found\]/);
193
+ } finally {
194
+ rmSync(root, { recursive: true, force: true });
195
+ }
196
+ },
197
+ 240_000,
198
+ );
199
+ });