@intentius/chant 0.124.31 → 0.124.33

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 (509) hide show
  1. package/bin/chant +7 -2
  2. package/dist/ci-jobs.d.ts +4 -0
  3. package/dist/ci-jobs.d.ts.map +1 -1
  4. package/dist/ci-jobs.js +9 -2
  5. package/dist/cli/commands/check-lexicon-plugin.d.ts +7 -4
  6. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  7. package/dist/cli/commands/check-lexicon-plugin.js +10 -7
  8. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  9. package/dist/cli/commands/check-lexicon.js +18 -12
  10. package/dist/cli/commands/import.d.ts +10 -0
  11. package/dist/cli/commands/import.d.ts.map +1 -1
  12. package/dist/cli/commands/import.js +37 -0
  13. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  14. package/dist/cli/commands/init-lexicon/templates/project.js +4 -3
  15. package/dist/cli/commands/onboard.d.ts.map +1 -1
  16. package/dist/cli/commands/onboard.js +8 -4
  17. package/dist/cli/commands/update.d.ts.map +1 -1
  18. package/dist/cli/commands/update.js +2 -1
  19. package/dist/cli/dependencies.d.ts +18 -0
  20. package/dist/cli/dependencies.d.ts.map +1 -0
  21. package/dist/cli/dependencies.js +120 -0
  22. package/dist/cli/handlers/build.d.ts.map +1 -1
  23. package/dist/cli/handlers/build.js +38 -4
  24. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  25. package/dist/cli/handlers/fan-out.js +12 -4
  26. package/dist/cli/handlers/graph.d.ts.map +1 -1
  27. package/dist/cli/handlers/graph.js +16 -6
  28. package/dist/cli/handlers/lifecycle-health.d.ts +16 -0
  29. package/dist/cli/handlers/lifecycle-health.d.ts.map +1 -0
  30. package/dist/cli/handlers/lifecycle-health.js +150 -0
  31. package/dist/cli/handlers/lifecycle.d.ts +26 -0
  32. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  33. package/dist/cli/handlers/lifecycle.js +1 -1
  34. package/dist/cli/handlers/lint.d.ts.map +1 -1
  35. package/dist/cli/handlers/lint.js +6 -0
  36. package/dist/cli/handlers/operator.d.ts +2 -2
  37. package/dist/cli/handlers/operator.js +3 -3
  38. package/dist/cli/handlers/pr.d.ts +16 -0
  39. package/dist/cli/handlers/pr.d.ts.map +1 -1
  40. package/dist/cli/handlers/pr.js +610 -32
  41. package/dist/cli/handlers/promote.d.ts.map +1 -1
  42. package/dist/cli/handlers/promote.js +19 -2
  43. package/dist/cli/handlers/release.d.ts +16 -1
  44. package/dist/cli/handlers/release.d.ts.map +1 -1
  45. package/dist/cli/handlers/release.js +83 -11
  46. package/dist/cli/handlers/run.d.ts +13 -1
  47. package/dist/cli/handlers/run.d.ts.map +1 -1
  48. package/dist/cli/handlers/run.js +38 -15
  49. package/dist/cli/main.d.ts.map +1 -1
  50. package/dist/cli/main.js +121 -33
  51. package/dist/cli/parse-args.d.ts.map +1 -1
  52. package/dist/cli/parse-args.js +37 -0
  53. package/dist/cli/registry.d.ts +29 -6
  54. package/dist/cli/registry.d.ts.map +1 -1
  55. package/dist/cli/registry.js +6 -2
  56. package/dist/codegen/generate-post-synth-barrel.js +2 -2
  57. package/dist/codegen/lexicon-regen.d.ts +4 -0
  58. package/dist/codegen/lexicon-regen.d.ts.map +1 -1
  59. package/dist/codegen/lexicon-regen.js +1 -1
  60. package/dist/codegen/pinned-upgrade.js +2 -2
  61. package/dist/components/capability.d.ts +44 -3
  62. package/dist/components/capability.d.ts.map +1 -1
  63. package/dist/components/capability.js +21 -0
  64. package/dist/components/changed-files.d.ts +7 -1
  65. package/dist/components/changed-files.d.ts.map +1 -1
  66. package/dist/components/changed-files.js +9 -1
  67. package/dist/components/deploy-inputs.d.ts +91 -0
  68. package/dist/components/deploy-inputs.d.ts.map +1 -0
  69. package/dist/components/deploy-inputs.js +184 -0
  70. package/dist/components/driver.d.ts +38 -0
  71. package/dist/components/driver.d.ts.map +1 -1
  72. package/dist/components/driver.js +56 -6
  73. package/dist/components/fan-out-record.d.ts +6 -1
  74. package/dist/components/fan-out-record.d.ts.map +1 -1
  75. package/dist/components/fan-out-record.js +24 -0
  76. package/dist/components/fan-out-run.d.ts +20 -0
  77. package/dist/components/fan-out-run.d.ts.map +1 -1
  78. package/dist/components/fan-out-run.js +21 -1
  79. package/dist/components/gate-plan.d.ts +8 -0
  80. package/dist/components/gate-plan.d.ts.map +1 -1
  81. package/dist/components/gate-plan.js +6 -0
  82. package/dist/components/pr-pipeline.d.ts +98 -12
  83. package/dist/components/pr-pipeline.d.ts.map +1 -1
  84. package/dist/components/pr-pipeline.js +146 -23
  85. package/dist/components/pr-run.d.ts +128 -30
  86. package/dist/components/pr-run.d.ts.map +1 -1
  87. package/dist/components/pr-run.js +290 -70
  88. package/dist/components/release-compile.d.ts +37 -2
  89. package/dist/components/release-compile.d.ts.map +1 -1
  90. package/dist/components/release-compile.js +64 -8
  91. package/dist/components/release-promote.d.ts +17 -3
  92. package/dist/components/release-promote.d.ts.map +1 -1
  93. package/dist/components/release-promote.js +79 -18
  94. package/dist/components/verbs/bom-writer.d.ts +1 -1
  95. package/dist/components/verbs/bom-writer.d.ts.map +1 -1
  96. package/dist/components/verbs/lockfile-sbom-generator.d.ts +20 -0
  97. package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -1
  98. package/dist/components/verbs/lockfile-sbom-generator.js +41 -4
  99. package/dist/components/wave-plan.d.ts +15 -2
  100. package/dist/components/wave-plan.d.ts.map +1 -1
  101. package/dist/components/wave-plan.js +44 -5
  102. package/dist/discovery/fold-import.d.ts.map +1 -1
  103. package/dist/discovery/fold-import.js +16 -6
  104. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  105. package/dist/discovery/sandbox/bundle.js +6 -0
  106. package/dist/discovery/specifier-resolve.d.ts.map +1 -1
  107. package/dist/discovery/specifier-resolve.js +8 -2
  108. package/dist/fold/fold.d.ts.map +1 -1
  109. package/dist/fold/fold.js +68 -1
  110. package/dist/fold/subset.d.ts +37 -0
  111. package/dist/fold/subset.d.ts.map +1 -1
  112. package/dist/fold/subset.js +88 -0
  113. package/dist/graph-detail.d.ts.map +1 -1
  114. package/dist/graph-detail.js +32 -7
  115. package/dist/health.d.ts +110 -0
  116. package/dist/health.d.ts.map +1 -0
  117. package/dist/health.js +105 -0
  118. package/dist/health.schema.json +191 -0
  119. package/dist/lexicon-module.d.ts +10 -0
  120. package/dist/lexicon-module.d.ts.map +1 -1
  121. package/dist/lexicon-module.js +53 -8
  122. package/dist/lexicon-plugin-helpers.d.ts.map +1 -1
  123. package/dist/lexicon-plugin-helpers.js +6 -4
  124. package/dist/lexicon.d.ts +29 -0
  125. package/dist/lexicon.d.ts.map +1 -1
  126. package/dist/lifecycle/affected.d.ts.map +1 -1
  127. package/dist/lifecycle/affected.js +7 -1
  128. package/dist/lifecycle/merge-record.d.ts +104 -0
  129. package/dist/lifecycle/merge-record.d.ts.map +1 -0
  130. package/dist/lifecycle/merge-record.js +102 -0
  131. package/dist/lifecycle/publish-attachments.d.ts +8 -5
  132. package/dist/lifecycle/publish-attachments.d.ts.map +1 -1
  133. package/dist/lifecycle/publish-attachments.js +27 -13
  134. package/dist/lifecycle/publish-npm.d.ts +3 -2
  135. package/dist/lifecycle/publish-npm.d.ts.map +1 -1
  136. package/dist/lifecycle/publish-npm.js +4 -3
  137. package/dist/lifecycle/release-at.d.ts +40 -0
  138. package/dist/lifecycle/release-at.d.ts.map +1 -0
  139. package/dist/lifecycle/release-at.js +83 -0
  140. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  141. package/dist/lifecycle/release-cut.js +23 -12
  142. package/dist/lifecycle/release-ledger.d.ts +21 -0
  143. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  144. package/dist/lifecycle/release-ledger.js +24 -0
  145. package/dist/lifecycle/release-publish.d.ts +28 -12
  146. package/dist/lifecycle/release-publish.d.ts.map +1 -1
  147. package/dist/lifecycle/release-publish.js +29 -17
  148. package/dist/lifecycle/release-store.d.ts +25 -2
  149. package/dist/lifecycle/release-store.d.ts.map +1 -1
  150. package/dist/lifecycle/release-store.js +40 -13
  151. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  152. package/dist/lifecycle/run-ledger.js +1 -0
  153. package/dist/lifecycle/work-dir.d.ts +45 -0
  154. package/dist/lifecycle/work-dir.d.ts.map +1 -0
  155. package/dist/lifecycle/work-dir.js +78 -0
  156. package/dist/lint/discover.d.ts +17 -9
  157. package/dist/lint/discover.d.ts.map +1 -1
  158. package/dist/lint/discover.js +62 -54
  159. package/dist/lint/rules/op/index.d.ts +2 -1
  160. package/dist/lint/rules/op/index.d.ts.map +1 -1
  161. package/dist/lint/rules/op/index.js +4 -2
  162. package/dist/lint/rules/op/ops018-shell-image-digest.d.ts +10 -0
  163. package/dist/lint/rules/op/ops018-shell-image-digest.d.ts.map +1 -0
  164. package/dist/lint/rules/op/ops018-shell-image-digest.js +38 -0
  165. package/dist/module-source.d.ts +57 -0
  166. package/dist/module-source.d.ts.map +1 -0
  167. package/dist/module-source.js +104 -0
  168. package/dist/op/activities/activity-contracts.d.ts +5 -0
  169. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  170. package/dist/op/activities/activity-contracts.js +3 -0
  171. package/dist/op/activities/factory.js +1 -1
  172. package/dist/op/activities/shell.d.ts +38 -0
  173. package/dist/op/activities/shell.d.ts.map +1 -1
  174. package/dist/op/activities/shell.js +89 -3
  175. package/dist/op/builders.d.ts +7 -0
  176. package/dist/op/builders.d.ts.map +1 -1
  177. package/dist/op/builders.js +7 -0
  178. package/dist/op/discover.d.ts.map +1 -1
  179. package/dist/op/discover.js +13 -3
  180. package/dist/op/gate.d.ts.map +1 -1
  181. package/dist/op/gate.js +3 -0
  182. package/dist/op/op-waves-run.d.ts.map +1 -1
  183. package/dist/op/op-waves-run.js +20 -5
  184. package/dist/op/operator.d.ts +2 -2
  185. package/dist/op/operator.js +2 -2
  186. package/dist/op/runtime.d.ts +2 -0
  187. package/dist/op/runtime.d.ts.map +1 -1
  188. package/dist/op/steward.d.ts +6 -4
  189. package/dist/op/steward.d.ts.map +1 -1
  190. package/dist/op/steward.js +5 -3
  191. package/dist/op/work-lease-run.d.ts +20 -7
  192. package/dist/op/work-lease-run.d.ts.map +1 -1
  193. package/dist/op/work-lease-run.js +56 -12
  194. package/dist/pr-forge.d.ts +10 -0
  195. package/dist/pr-forge.d.ts.map +1 -1
  196. package/dist/pr-forge.js +39 -0
  197. package/dist/pr-loop.d.ts +155 -7
  198. package/dist/pr-loop.d.ts.map +1 -1
  199. package/dist/pr-loop.js +137 -11
  200. package/dist/pr-report-url.d.ts +4 -4
  201. package/dist/pr-report-url.d.ts.map +1 -1
  202. package/dist/pr-report-url.js +5 -5
  203. package/dist/runner-start.d.ts +179 -0
  204. package/dist/runner-start.d.ts.map +1 -0
  205. package/dist/runner-start.js +277 -0
  206. package/dist/ts-loader.d.ts +38 -4
  207. package/dist/ts-loader.d.ts.map +1 -1
  208. package/dist/ts-loader.js +190 -16
  209. package/dist/wave-runtime.mjs +238 -231
  210. package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts +34 -0
  211. package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts.map +1 -0
  212. package/dist/workspace/chant-migrations/fountain-retired-kinds.js +176 -0
  213. package/dist/workspace/chant-migrations.d.ts.map +1 -1
  214. package/dist/workspace/chant-migrations.js +2 -0
  215. package/dist/workspace/check.schema.json +70 -2
  216. package/dist/workspace/checks/boxes.d.ts +6 -6
  217. package/dist/workspace/checks/boxes.js +9 -9
  218. package/dist/workspace/checks/security.d.ts +35 -0
  219. package/dist/workspace/checks/security.d.ts.map +1 -0
  220. package/dist/workspace/checks/security.js +305 -0
  221. package/dist/workspace/checks.d.ts +2 -0
  222. package/dist/workspace/checks.d.ts.map +1 -1
  223. package/dist/workspace/checks.js +5 -0
  224. package/dist/workspace/ci-builds.d.ts +163 -0
  225. package/dist/workspace/ci-builds.d.ts.map +1 -0
  226. package/dist/workspace/ci-builds.js +315 -0
  227. package/dist/workspace/ci-green-cli.d.ts +2 -1
  228. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  229. package/dist/workspace/ci-green-cli.js +25 -5
  230. package/dist/workspace/ci-green-forge.d.ts +18 -4
  231. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  232. package/dist/workspace/ci-green-forge.js +12 -0
  233. package/dist/workspace/ci-green-workflow.d.ts +55 -1
  234. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  235. package/dist/workspace/ci-green-workflow.js +128 -1
  236. package/dist/workspace/ci-green.d.ts +117 -16
  237. package/dist/workspace/ci-green.d.ts.map +1 -1
  238. package/dist/workspace/ci-green.js +358 -43
  239. package/dist/workspace/ci-last-green.schema.json +49 -0
  240. package/dist/workspace/ci-list.schema.json +47 -7
  241. package/dist/workspace/ci-report-url.d.ts +18 -0
  242. package/dist/workspace/ci-report-url.d.ts.map +1 -0
  243. package/dist/workspace/ci-report-url.js +33 -0
  244. package/dist/workspace/ci-run-index.d.ts +13 -1
  245. package/dist/workspace/ci-run-index.d.ts.map +1 -1
  246. package/dist/workspace/ci-run-index.js +6 -4
  247. package/dist/workspace/ci-run-index.schema.json +6 -4
  248. package/dist/workspace/ci-run.d.ts +85 -6
  249. package/dist/workspace/ci-run.d.ts.map +1 -1
  250. package/dist/workspace/ci-run.js +262 -64
  251. package/dist/workspace/ci-runner-key.d.ts +16 -3
  252. package/dist/workspace/ci-runner-key.d.ts.map +1 -1
  253. package/dist/workspace/ci-runner-key.js +30 -10
  254. package/dist/workspace/ci-runner-start.d.ts +77 -0
  255. package/dist/workspace/ci-runner-start.d.ts.map +1 -0
  256. package/dist/workspace/ci-runner-start.js +185 -0
  257. package/dist/workspace/ci-serve.d.ts +130 -11
  258. package/dist/workspace/ci-serve.d.ts.map +1 -1
  259. package/dist/workspace/ci-serve.js +323 -40
  260. package/dist/workspace/declaration.d.ts +25 -0
  261. package/dist/workspace/declaration.d.ts.map +1 -1
  262. package/dist/workspace/declaration.js +14 -2
  263. package/dist/workspace/declaration.schema.json +30 -2
  264. package/dist/workspace/export.d.ts +1 -1
  265. package/dist/workspace/export.d.ts.map +1 -1
  266. package/dist/workspace/export.js +7 -3
  267. package/dist/workspace/ls.d.ts +8 -1
  268. package/dist/workspace/ls.d.ts.map +1 -1
  269. package/dist/workspace/ls.js +2 -1
  270. package/dist/workspace/ls.schema.json +9 -2
  271. package/dist/workspace/member-pipeline.d.ts +1 -0
  272. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  273. package/dist/workspace/member-pipeline.js +2 -0
  274. package/dist/workspace/merge-record.schema.json +49 -0
  275. package/dist/workspace/pin-integrity.d.ts.map +1 -1
  276. package/dist/workspace/pin-integrity.js +3 -2
  277. package/dist/workspace/pr-report.schema.json +75 -8
  278. package/dist/workspace/reason-codes.d.ts +18 -1
  279. package/dist/workspace/reason-codes.d.ts.map +1 -1
  280. package/dist/workspace/reason-codes.js +20 -2
  281. package/dist/workspace/release-candidates.d.ts +129 -0
  282. package/dist/workspace/release-candidates.d.ts.map +1 -0
  283. package/dist/workspace/release-candidates.js +233 -0
  284. package/dist/workspace/release-candidates.schema.json +353 -0
  285. package/dist/workspace/run-event.schema.json +3 -1
  286. package/dist/workspace/security.d.ts +40 -0
  287. package/dist/workspace/security.d.ts.map +1 -0
  288. package/dist/workspace/security.js +99 -0
  289. package/dist/workspace/status.schema.json +3 -1
  290. package/dist/workspace/write-scope.d.ts +9 -0
  291. package/dist/workspace/write-scope.d.ts.map +1 -1
  292. package/dist/workspace/write-scope.js +11 -1
  293. package/package.json +8 -1
  294. package/src/__fixtures__/pr-loop/pr-apply-wave-waiting.note.golden.md +48 -0
  295. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +1 -1
  296. package/src/ci-jobs.ts +11 -2
  297. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +3 -3
  298. package/src/cli/commands/audit.test.ts +2 -2
  299. package/src/cli/commands/check-lexicon-plugin.test.ts +9 -0
  300. package/src/cli/commands/check-lexicon-plugin.ts +11 -8
  301. package/src/cli/commands/check-lexicon.test.ts +1 -1
  302. package/src/cli/commands/check-lexicon.ts +16 -11
  303. package/src/cli/commands/import.ts +40 -0
  304. package/src/cli/commands/init-lexicon/templates/project.ts +4 -3
  305. package/src/cli/commands/init-lexicon.test.ts +8 -5
  306. package/src/cli/commands/onboard.test.ts +45 -0
  307. package/src/cli/commands/onboard.ts +8 -4
  308. package/src/cli/commands/update.test.ts +6 -0
  309. package/src/cli/commands/update.ts +4 -1
  310. package/src/cli/compiled-cli.e2e.test.ts +76 -11
  311. package/src/cli/dependencies.e2e.test.ts +101 -0
  312. package/src/cli/dependencies.test.ts +93 -0
  313. package/src/cli/dependencies.ts +122 -0
  314. package/src/cli/handlers/build.test.ts +105 -0
  315. package/src/cli/handlers/build.ts +35 -4
  316. package/src/cli/handlers/fan-out.test.ts +73 -0
  317. package/src/cli/handlers/fan-out.ts +11 -4
  318. package/src/cli/handlers/graph.test.ts +76 -0
  319. package/src/cli/handlers/graph.ts +19 -12
  320. package/src/cli/handlers/lifecycle-health.test.ts +123 -0
  321. package/src/cli/handlers/lifecycle-health.ts +157 -0
  322. package/src/cli/handlers/lifecycle.ts +1 -1
  323. package/src/cli/handlers/lint.test.ts +42 -0
  324. package/src/cli/handlers/lint.ts +6 -0
  325. package/src/cli/handlers/operator.ts +3 -3
  326. package/src/cli/handlers/pr-deploy-inputs.test.ts +209 -0
  327. package/src/cli/handlers/pr-record.test.ts +201 -0
  328. package/src/cli/handlers/pr-waves.test.ts +449 -0
  329. package/src/cli/handlers/pr.test.ts +156 -0
  330. package/src/cli/handlers/pr.ts +648 -33
  331. package/src/cli/handlers/promote.test.ts +43 -1
  332. package/src/cli/handlers/promote.ts +19 -3
  333. package/src/cli/handlers/release-cut-at.e2e.test.ts +115 -0
  334. package/src/cli/handlers/release-publish-targets.e2e.test.ts +2 -2
  335. package/src/cli/handlers/release-verify.e2e.test.ts +12 -10
  336. package/src/cli/handlers/release.e2e.test.ts +19 -28
  337. package/src/cli/handlers/release.ts +81 -11
  338. package/src/cli/handlers/run-components-exit.test.ts +99 -0
  339. package/src/cli/handlers/run-signer.test.ts +79 -0
  340. package/src/cli/handlers/run.ts +34 -16
  341. package/src/cli/main.test.ts +18 -0
  342. package/src/cli/main.ts +120 -33
  343. package/src/cli/parse-args.ts +28 -0
  344. package/src/cli/registry.ts +35 -8
  345. package/src/codegen/generate-post-synth-barrel.ts +2 -2
  346. package/src/codegen/lexicon-regen.ts +1 -1
  347. package/src/codegen/pinned-upgrade.ts +2 -2
  348. package/src/codegen/post-synth-barrel-guards.test.ts +6 -11
  349. package/src/components/capability.ts +51 -3
  350. package/src/components/changed-files.test.ts +16 -1
  351. package/src/components/changed-files.ts +9 -1
  352. package/src/components/deploy-inputs.test.ts +108 -0
  353. package/src/components/deploy-inputs.ts +225 -0
  354. package/src/components/driver.test.ts +36 -1
  355. package/src/components/driver.ts +87 -4
  356. package/src/components/fan-out-record.ts +29 -1
  357. package/src/components/fan-out-run.test.ts +35 -0
  358. package/src/components/fan-out-run.ts +40 -1
  359. package/src/components/gate-plan.ts +9 -0
  360. package/src/components/pr-pipeline.test.ts +100 -0
  361. package/src/components/pr-pipeline.ts +184 -28
  362. package/src/components/pr-run.test.ts +323 -18
  363. package/src/components/pr-run.ts +355 -76
  364. package/src/components/release-compile.test.ts +34 -0
  365. package/src/components/release-compile.ts +89 -8
  366. package/src/components/release-promote.test.ts +55 -2
  367. package/src/components/release-promote.ts +93 -23
  368. package/src/components/verbs/bom-writer.ts +1 -1
  369. package/src/components/verbs/lockfile-sbom-generator.test.ts +36 -0
  370. package/src/components/verbs/lockfile-sbom-generator.ts +43 -5
  371. package/src/components/wave-plan.ts +48 -8
  372. package/src/discovery/fold-host-method.test.ts +87 -0
  373. package/src/discovery/fold-import.ts +15 -5
  374. package/src/discovery/fold-package-composite.test.ts +27 -0
  375. package/src/discovery/fold-specifiers.test.ts +8 -0
  376. package/src/discovery/sandbox/bundle.ts +6 -0
  377. package/src/discovery/specifier-resolve.ts +8 -2
  378. package/src/fold/fold.test.ts +72 -0
  379. package/src/fold/fold.ts +71 -0
  380. package/src/fold/subset.test.ts +31 -0
  381. package/src/fold/subset.ts +99 -0
  382. package/src/graph-detail.test.ts +57 -0
  383. package/src/graph-detail.ts +33 -7
  384. package/src/health.schema.json +191 -0
  385. package/src/health.test.ts +62 -0
  386. package/src/health.ts +178 -0
  387. package/src/lexicon-dist.e2e.test.ts +254 -0
  388. package/src/lexicon-module.test.ts +47 -0
  389. package/src/lexicon-module.ts +49 -7
  390. package/src/lexicon-plugin-helpers.ts +6 -4
  391. package/src/lexicon.ts +43 -1
  392. package/src/lifecycle/affected.test.ts +7 -0
  393. package/src/lifecycle/affected.ts +6 -1
  394. package/src/lifecycle/merge-record.test.ts +111 -0
  395. package/src/lifecycle/merge-record.ts +154 -0
  396. package/src/lifecycle/publish-attachments.ts +25 -13
  397. package/src/lifecycle/publish-npm.ts +4 -3
  398. package/src/lifecycle/publish-targets.test.ts +34 -4
  399. package/src/lifecycle/release-at.test.ts +48 -0
  400. package/src/lifecycle/release-at.ts +100 -0
  401. package/src/lifecycle/release-cut.test.ts +41 -0
  402. package/src/lifecycle/release-cut.ts +22 -11
  403. package/src/lifecycle/release-ledger.ts +34 -0
  404. package/src/lifecycle/release-publish.test.ts +43 -13
  405. package/src/lifecycle/release-publish.ts +38 -18
  406. package/src/lifecycle/release-store.ts +57 -13
  407. package/src/lifecycle/run-ledger.test.ts +13 -0
  408. package/src/lifecycle/run-ledger.ts +1 -0
  409. package/src/lifecycle/work-dir.test.ts +77 -0
  410. package/src/lifecycle/work-dir.ts +82 -0
  411. package/src/lint/discover.test.ts +46 -2
  412. package/src/lint/discover.ts +55 -49
  413. package/src/lint/rules/op/index.ts +4 -2
  414. package/src/lint/rules/op/ops018-shell-image-digest.test.ts +60 -0
  415. package/src/lint/rules/op/ops018-shell-image-digest.ts +48 -0
  416. package/src/module-source.test.ts +85 -0
  417. package/src/module-source.ts +112 -0
  418. package/src/op/activities/activity-contracts.ts +3 -0
  419. package/src/op/activities/factory.ts +1 -1
  420. package/src/op/activities/shell-container.e2e.test.ts +67 -0
  421. package/src/op/activities/shell.test.ts +44 -1
  422. package/src/op/activities/shell.ts +110 -3
  423. package/src/op/builders.ts +7 -0
  424. package/src/op/discover-root.test.ts +31 -2
  425. package/src/op/discover.ts +14 -4
  426. package/src/op/gate.test.ts +30 -0
  427. package/src/op/gate.ts +3 -0
  428. package/src/op/op-waves-run.ts +20 -5
  429. package/src/op/op-waves.test.ts +49 -0
  430. package/src/op/operator.ts +2 -2
  431. package/src/op/runtime.ts +2 -0
  432. package/src/op/step-console.test.ts +4 -2
  433. package/src/op/steward.ts +6 -4
  434. package/src/op/work-lease-run.test.ts +88 -2
  435. package/src/op/work-lease-run.ts +52 -12
  436. package/src/pr-forge-bundle.test.ts +2 -2
  437. package/src/pr-forge.test.ts +42 -0
  438. package/src/pr-forge.ts +40 -0
  439. package/src/pr-loop-bundle.test.ts +2 -1
  440. package/src/pr-loop.test.ts +146 -1
  441. package/src/pr-loop.ts +278 -17
  442. package/src/pr-report-url.ts +7 -7
  443. package/src/runner-start-bundle.test.ts +29 -0
  444. package/src/runner-start.test.ts +179 -0
  445. package/src/runner-start.ts +329 -0
  446. package/src/terraform/__fixtures__/advise.test.ts +21 -2
  447. package/src/ts-loader.test.ts +89 -1
  448. package/src/ts-loader.ts +180 -13
  449. package/src/workspace/changes.test.ts +1 -1
  450. package/src/workspace/chant-migrations/fountain-retired-kinds.test.ts +33 -0
  451. package/src/workspace/chant-migrations/fountain-retired-kinds.ts +190 -0
  452. package/src/workspace/chant-migrations.e2e.test.ts +5 -0
  453. package/src/workspace/chant-migrations.ts +2 -0
  454. package/src/workspace/check-contract.test.ts +3 -2
  455. package/src/workspace/check.schema.json +70 -2
  456. package/src/workspace/checks/boxes.ts +9 -9
  457. package/src/workspace/checks/security.test.ts +138 -0
  458. package/src/workspace/checks/security.ts +305 -0
  459. package/src/workspace/checks.ts +5 -0
  460. package/src/workspace/ci-builds.e2e.test.ts +208 -0
  461. package/src/workspace/ci-builds.test.ts +174 -0
  462. package/src/workspace/ci-builds.ts +385 -0
  463. package/src/workspace/ci-green-builds.test.ts +180 -0
  464. package/src/workspace/ci-green-cli.test.ts +54 -0
  465. package/src/workspace/ci-green-cli.ts +26 -5
  466. package/src/workspace/ci-green-forge.ts +30 -4
  467. package/src/workspace/ci-green-runs.test.ts +53 -11
  468. package/src/workspace/ci-green-workflow.test.ts +84 -1
  469. package/src/workspace/ci-green-workflow.ts +139 -2
  470. package/src/workspace/ci-green.test.ts +6 -3
  471. package/src/workspace/ci-green.ts +408 -48
  472. package/src/workspace/ci-last-green.schema.json +49 -0
  473. package/src/workspace/ci-list.schema.json +47 -7
  474. package/src/workspace/ci-report-url.test.ts +220 -0
  475. package/src/workspace/ci-report-url.ts +33 -0
  476. package/src/workspace/ci-run-index.schema.json +6 -4
  477. package/src/workspace/ci-run-index.test.ts +42 -3
  478. package/src/workspace/ci-run-index.ts +19 -5
  479. package/src/workspace/ci-run.test.ts +203 -8
  480. package/src/workspace/ci-run.ts +295 -63
  481. package/src/workspace/ci-runner-key.test.ts +55 -17
  482. package/src/workspace/ci-runner-key.ts +36 -11
  483. package/src/workspace/ci-runner-start.test.ts +151 -0
  484. package/src/workspace/ci-runner-start.ts +193 -0
  485. package/src/workspace/ci-serve-builds.test.ts +86 -0
  486. package/src/workspace/ci-serve.test.ts +209 -6
  487. package/src/workspace/ci-serve.ts +341 -42
  488. package/src/workspace/declaration.schema.json +30 -2
  489. package/src/workspace/declaration.test.ts +40 -0
  490. package/src/workspace/declaration.ts +40 -3
  491. package/src/workspace/export.ts +6 -3
  492. package/src/workspace/ls.schema.json +9 -2
  493. package/src/workspace/ls.ts +10 -4
  494. package/src/workspace/member-pipeline.ts +2 -1
  495. package/src/workspace/merge-record.schema.json +49 -0
  496. package/src/workspace/pin-integrity.test.ts +5 -0
  497. package/src/workspace/pin-integrity.ts +3 -2
  498. package/src/workspace/pr-report.schema.json +75 -8
  499. package/src/workspace/reason-codes.test.ts +2 -0
  500. package/src/workspace/reason-codes.ts +20 -2
  501. package/src/workspace/release-candidates.schema.json +353 -0
  502. package/src/workspace/release-candidates.test.ts +106 -0
  503. package/src/workspace/release-candidates.ts +315 -0
  504. package/src/workspace/run-event.schema.json +3 -1
  505. package/src/workspace/security.test.ts +70 -0
  506. package/src/workspace/security.ts +118 -0
  507. package/src/workspace/status.schema.json +3 -1
  508. package/src/workspace/write-scope.test.ts +29 -1
  509. package/src/workspace/write-scope.ts +12 -1
@@ -1 +1 @@
1
- {"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/promote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA+CH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAukBlD,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2E/E;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsChF;AAsCD,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BhF"}
1
+ {"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/promote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA+CH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAulBlD,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA2E/E;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsChF;AAsCD,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BhF"}
@@ -34,6 +34,7 @@ import { renderDriverHuman } from "../../components/driver-output.js";
34
34
  import { ndjsonProgressSink } from "../../components/run-progress.js";
35
35
  import { openCliRunEvents, refusesBothStreams } from "../run-events.js";
36
36
  import { parseDigestPins, planPromotion, planRollback, planReleaseRollback, planRedeploy, withoutBuildSteps, runPromotion, promotionRecord, rollbackRecord, redeployRecord, gateApprover, gateAdmission, } from "../../components/promote.js";
37
+ import { failedRunExitCode } from "../../components/driver.js";
37
38
  import { summaryLedgerPrefix, writeGatedRunSummary } from "../../op/gate-summary.js";
38
39
  import { approveCommand, describeGateMismatch, gateIsSealed, gitGateLedgerPort } from "../../op/gate.js";
39
40
  import { resolveCliBuildParams, parseParamFlags } from "../build-params-cli.js";
@@ -246,7 +247,7 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
246
247
  if (under) {
247
248
  const { pinReleaseTemplates } = await import("../../components/release-promote.js");
248
249
  const { readReleaseTemplate } = await import("../../lifecycle/release-store.js");
249
- const pinned = await pinReleaseTemplates(prepared, under.release, under.target, (digest) => readReleaseTemplate(digest));
250
+ const pinned = await pinReleaseTemplates(prepared, under.release, under.target, (digest, encoding) => readReleaseTemplate(digest, undefined, encoding));
250
251
  if ("errors" in pinned) {
251
252
  for (const message of pinned.errors)
252
253
  console.error(formatError({ message }));
@@ -453,7 +454,8 @@ async function deployPlan(ctx, verb, plan, project, actor, record, under) {
453
454
  }
454
455
  if (run.status !== "ok") {
455
456
  console.error(formatError({ message: `${verb} failed at "${run.failedComponent ?? "unknown"}"` }));
456
- return 1;
457
+ // A step that refused a plan that moved since it was approved exits 3 (#3997).
458
+ return failedRunExitCode(run.results);
457
459
  }
458
460
  return 0;
459
461
  }
@@ -524,6 +526,21 @@ async function resolveUnderRelease(ref, env, verb, fix) {
524
526
  console.error(formatError(revokedRefusal({ releaseDigest: found.release.releaseDigest, label: found.label }, revocation, await fix(found.release))));
525
527
  return 1;
526
528
  }
529
+ // #4168: under verified-releases a release deploys only once `chant release verify` passes for it.
530
+ const { securityGroupsAt } = await import("../../workspace/security.js");
531
+ if (securityGroupsAt(process.cwd()).has("verified-releases")) {
532
+ const { verifyRelease, verificationCode } = await import("../../lifecycle/release-verify.js");
533
+ const name = found.label ?? found.release.releaseDigest;
534
+ const v = await verifyRelease({ cwd: process.cwd(), ref: found.release.releaseDigest });
535
+ const code = "error" in v ? v.error.code : verificationCode(v);
536
+ if (code) {
537
+ console.error(formatError({
538
+ message: `${code}: release ${name} does not verify (${"error" in v ? v.error.message : v.reason}), and the workspace opts into verified-releases, so ${verb} deploys only a verified release`,
539
+ hint: `Check it with: chant release verify ${name}`,
540
+ }));
541
+ return 1;
542
+ }
543
+ }
527
544
  return { release: found.release, label: found.label, target: target.target };
528
545
  }
529
546
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * `chant release` (#4026, ws-104): the release is what graduates.
3
3
  *
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]
4
+ * release cut [<label>] [--at <sha>] [--yes] [--build <command>] [--param k=v]... [--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>] [--actor <name>] [--sign [<key file>]] [--json]
5
5
  * a dry run of a cut of this member from the checkout's HEAD, which must be
6
6
  * clean, on trunk and pushed, and green (#4027); `--yes` cuts, records,
7
7
  * and tags the commit `release/<label>` locally;
@@ -17,6 +17,9 @@
17
17
  * release verify <label|digest> [--json]
18
18
  * check the release's signature offline against .chant/allowed_signers
19
19
  * at the release's commit (#4049)
20
+ * release candidates [--env <env>] [--json]
21
+ * the green commits of trunk a release can be cut from, each with what it
22
+ * would ship, and what each environment runs (#4168 4.2)
20
23
  * release list [--json]
21
24
  * every release of this member with its targets, its cuts and where it runs;
22
25
  * `--json` prints the read contract's `releases` document
@@ -49,6 +52,11 @@ export declare function sameWithYes(argv: readonly string[]): string;
49
52
  * would record, build and tag, and what publishes where. With `--yes` it
50
53
  * cuts, signs with `--sign`, records the cut with its actor and run id,
51
54
  * tags the commit locally and prints the next command.
55
+ *
56
+ * `--at <sha>` (#4168 4.2) cuts that commit instead of `HEAD`, from a
57
+ * temporary worktree (../../lifecycle/release-at.ts), so the checkout need
58
+ * not be clean or at the commit. The label reaches every compile and
59
+ * artifact build as `CHANT_RELEASE_LABEL` (decision 5).
52
60
  */
53
61
  export declare function runReleaseCut(ctx: CommandContext): Promise<number>;
54
62
  /**
@@ -76,6 +84,13 @@ export declare function runReleasePublish(ctx: CommandContext): Promise<number>;
76
84
  * verifies and 1 when it does not or can't be checked.
77
85
  */
78
86
  export declare function runReleaseVerify(ctx: CommandContext): Promise<number>;
87
+ /**
88
+ * `release candidates [--env <env>] [--json]` (#4168 4.2): the green commits
89
+ * of trunk a release can be cut from, newest first, each with what it would
90
+ * ship since the previous one, and what each environment runs. `--json`
91
+ * prints the read contract's `release-candidates` document.
92
+ */
93
+ export declare function runReleaseCandidates(ctx: CommandContext): Promise<number>;
79
94
  export declare function runReleaseList(ctx: CommandContext): Promise<number>;
80
95
  /**
81
96
  * `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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
1
+ {"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/release.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAyBlD,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;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAwNxE;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;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiC/E;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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * `chant release` (#4026, ws-104): the release is what graduates.
3
3
  *
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]
4
+ * release cut [<label>] [--at <sha>] [--yes] [--build <command>] [--param k=v]... [--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>] [--actor <name>] [--sign [<key file>]] [--json]
5
5
  * a dry run of a cut of this member from the checkout's HEAD, which must be
6
6
  * clean, on trunk and pushed, and green (#4027); `--yes` cuts, records,
7
7
  * and tags the commit `release/<label>` locally;
@@ -17,6 +17,9 @@
17
17
  * release verify <label|digest> [--json]
18
18
  * check the release's signature offline against .chant/allowed_signers
19
19
  * at the release's commit (#4049)
20
+ * release candidates [--env <env>] [--json]
21
+ * the green commits of trunk a release can be cut from, each with what it
22
+ * would ship, and what each environment runs (#4168 4.2)
20
23
  * release list [--json]
21
24
  * every release of this member with its targets, its cuts and where it runs;
22
25
  * `--json` prints the read contract's `releases` document
@@ -35,12 +38,13 @@ import { existsSync } from "node:fs";
35
38
  import { resolve } from "node:path";
36
39
  import { formatBold, formatError, formatSuccess, formatWarning } from "../format.js";
37
40
  import { parseParamFlags } from "../build-params-cli.js";
38
- const USAGE = "chant release cut [<label>] [--yes] [--build <command>] [--param <k=v>] [--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>] [--actor <name>] [--sign [<key file>]] [--json] | release publish <label|digest> [--yes] [--allow-unsigned] [--require-provenance] [--json] | release verify <label|digest> [--json] | release list [--json] | release export <label|digest> --env <env> [-o <dir>] [--json]";
41
+ const USAGE = "chant release cut [<label>] [--at <sha>] [--yes] [--build <command>] [--param <k=v>] [--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>] [--actor <name>] [--sign [<key file>]] [--json] | release publish <label|digest> [--yes] [--allow-unsigned] [--require-provenance] [--json] | release verify <label|digest> [--json] | release candidates [--env <env>] [--json] | release list [--json] | release export <label|digest> --env <env> [-o <dir>] [--json]";
39
42
  /** The build inputs `release cut` and `release compile` share. */
40
- function compileInputs(ctx, params) {
43
+ function compileInputs(ctx, params, projectDir = resolve("."), releaseLabel) {
41
44
  const { args } = ctx;
42
45
  return {
43
- projectDir: resolve("."),
46
+ projectDir,
47
+ ...(releaseLabel ? { releaseLabel } : {}),
44
48
  ...(args.buildCommand ? { buildCommand: args.buildCommand } : {}),
45
49
  ...(params ? { params } : {}),
46
50
  ...(args.paramsFile ? { paramsFile: args.paramsFile } : {}),
@@ -87,6 +91,11 @@ function describeActorSource(source) {
87
91
  * would record, build and tag, and what publishes where. With `--yes` it
88
92
  * cuts, signs with `--sign`, records the cut with its actor and run id,
89
93
  * tags the commit locally and prints the next command.
94
+ *
95
+ * `--at <sha>` (#4168 4.2) cuts that commit instead of `HEAD`, from a
96
+ * temporary worktree (../../lifecycle/release-at.ts), so the checkout need
97
+ * not be clean or at the commit. The label reaches every compile and
98
+ * artifact build as `CHANT_RELEASE_LABEL` (decision 5).
90
99
  */
91
100
  export async function runReleaseCut(ctx) {
92
101
  const { args } = ctx;
@@ -109,6 +118,8 @@ export async function runReleaseCut(ctx) {
109
118
  console.error(formatError({ message: `${message} [${code}]`, ...(fix ? { hint: fix } : {}) }));
110
119
  return 1;
111
120
  };
121
+ const at = await import("../../lifecycle/release-at.js");
122
+ let checkout = null;
112
123
  try {
113
124
  // The workstation checks come first, in the order #4027 lists them; the
114
125
  // green check and the rest are the cut's own.
@@ -124,9 +135,17 @@ export async function runReleaseCut(ctx) {
124
135
  let trunk = null;
125
136
  let signers = [];
126
137
  let member = null;
138
+ if (args.at !== undefined && !top) {
139
+ return fail("not-a-git-repository", "--at names a commit, and this directory is not in a git repository");
140
+ }
127
141
  if (top) {
128
- commit = await getHeadCommit({ cwd });
129
- ws.checkCleanTree(top, commit);
142
+ if (args.at !== undefined) {
143
+ commit = at.resolveCutCommit(top, args.at);
144
+ }
145
+ else {
146
+ commit = await getHeadCommit({ cwd });
147
+ ws.checkCleanTree(top, commit);
148
+ }
130
149
  const { scopeSource } = await import("../../workspace/write-scope.js");
131
150
  const { releaseRuleFrom } = await import("../../workspace/identity.js");
132
151
  const source = scopeSource(cwd);
@@ -167,8 +186,12 @@ export async function runReleaseCut(ctx) {
167
186
  const tag = label !== null && commit !== null && top ? { name: ws.releaseTagName(member, label), state: ws.checkReleaseTag(top, ws.releaseTagName(member, label), commit) } : null;
168
187
  const ci = resolveCiRun(process.env);
169
188
  const params = parseParamFlags(args.param);
170
- const compiler = spawnTargetCompiler(compileInputs(ctx, params));
171
- const request = { cwd, compiler, label, actor, ...(args.sign !== undefined ? { sign: args.sign } : {}) };
189
+ // --at: the cut reads, compiles and builds the commit's tree, not the checkout's.
190
+ if (args.at !== undefined && top && commit)
191
+ checkout = at.checkoutCommit(top, cwd, commit);
192
+ const cutCwd = checkout?.memberDir ?? cwd;
193
+ const compiler = spawnTargetCompiler(compileInputs(ctx, params, cutCwd, label));
194
+ const request = { cwd: cutCwd, compiler, label, actor, ...(args.sign !== undefined ? { sign: args.sign } : {}) };
172
195
  if (dryRun) {
173
196
  const plan = await planRelease(request);
174
197
  // Under the release gate, a key the signers file at base lists for someone else is refused now, not after the build.
@@ -178,7 +201,7 @@ export async function runReleaseCut(ctx) {
178
201
  const ref = plan.label ?? plan.alreadyCut ?? plan.releaseDigest;
179
202
  const provenance = detectProvenance();
180
203
  // The targets release publish would run, as the config here declares them; their files are read at publish.
181
- const publishTargets = await releasePublishTargets(cwd).then((ts) => ts.map((t) => `${t.name} to ${t.destination}`), (err) => (err instanceof Error ? err : new Error(String(err))));
204
+ const publishTargets = await releasePublishTargets(cutCwd).then((ts) => ts.map((t) => `${t.name} to ${t.destination}`), (err) => (err instanceof Error ? err : new Error(String(err))));
182
205
  const deployRef = plan.label ?? "<label|digest>";
183
206
  const doc = {
184
207
  dryRun: true,
@@ -187,6 +210,7 @@ export async function runReleaseCut(ctx) {
187
210
  actorSource: who.source,
188
211
  run: ci ? { runId: ci.runId, runOrigin: ci.runOrigin } : { runId: null, runOrigin: { forge: "local" } },
189
212
  trunk,
213
+ at: args.at !== undefined ? { ref: args.at, commit } : null,
190
214
  sign: args.sign !== undefined ? { key: publicKey !== null ? publicKey.split(" ")[0] : null, readable: publicKey !== null } : null,
191
215
  tag: tag ? { name: tag.name, exists: tag.state === "present" } : null,
192
216
  publish: { targets: Array.isArray(publishTargets) ? publishTargets : [], provenance },
@@ -286,7 +310,7 @@ export async function runReleaseCut(ctx) {
286
310
  return 0;
287
311
  }
288
312
  catch (err) {
289
- if (err instanceof ws.WorkstationCheckError || err instanceof ReleaseCutError) {
313
+ if (err instanceof ws.WorkstationCheckError || err instanceof ReleaseCutError || err instanceof at.CutAtError) {
290
314
  return fail(err.code, err.message, err.fix);
291
315
  }
292
316
  if (err instanceof ReleaseLabelError)
@@ -297,6 +321,9 @@ export async function runReleaseCut(ctx) {
297
321
  }
298
322
  throw err;
299
323
  }
324
+ finally {
325
+ checkout?.remove();
326
+ }
300
327
  }
301
328
  /**
302
329
  * `release publish <label|digest> [--yes]` (#4027, #4047): publish a cut
@@ -478,6 +505,51 @@ export async function runReleaseVerify(ctx) {
478
505
  console.error(formatSuccess(`Verified ${name}: ${result.reason}`));
479
506
  return 0;
480
507
  }
508
+ /**
509
+ * `release candidates [--env <env>] [--json]` (#4168 4.2): the green commits
510
+ * of trunk a release can be cut from, newest first, each with what it would
511
+ * ship since the previous one, and what each environment runs. `--json`
512
+ * prints the read contract's `release-candidates` document.
513
+ */
514
+ export async function runReleaseCandidates(ctx) {
515
+ const { releaseCandidatesDocument } = await import("../../workspace/release-candidates.js");
516
+ const doc = await releaseCandidatesDocument({ cwd: resolve("."), ...(ctx.args.env ? { env: ctx.args.env } : {}) });
517
+ if (ctx.args.json) {
518
+ console.log(JSON.stringify(doc, null, 2));
519
+ return "error" in doc ? 1 : 0;
520
+ }
521
+ if ("error" in doc) {
522
+ console.error(formatError({ message: `${doc.error.message} [${doc.error.code}]`, hint: USAGE }));
523
+ return 1;
524
+ }
525
+ for (const e of doc.environments) {
526
+ const runs = e.running.map((r) => `${r.label ?? r.releaseDigest.slice(0, 19)}${r.commit ? ` at ${r.commit.slice(0, 12)}` : ""}`).join(", ");
527
+ console.log(`${e.env}: ${runs || "runs no release yet"}`);
528
+ }
529
+ if (!doc.tip) {
530
+ console.error(`No candidates: this clone knows no ${doc.branch}. Fetch it: git fetch origin ${doc.branch} --tags`);
531
+ return 0;
532
+ }
533
+ if (doc.pending.length > 0)
534
+ console.log(`${doc.pending.length} commit(s) on ${doc.branch} after the newest candidate are not green yet`);
535
+ if (doc.candidates.length === 0)
536
+ console.log(`No green commit on ${doc.branch}${doc.since ? ` since ${doc.since.slice(0, 12)}` : ""} to cut from.`);
537
+ for (const c of doc.candidates) {
538
+ const tags = [...(c.newFor.length > 0 ? [`new for ${c.newFor.join(", ")}`] : []), ...(c.cut.length > 0 ? [`cut as ${c.cut.join(", ")}`] : [])];
539
+ console.log(`${c.commit.slice(0, 12)} ${c.subject}${tags.length > 0 ? ` (${tags.join("; ")})` : ""}`);
540
+ for (const ch of c.changes) {
541
+ const links = [...(ch.pr !== null ? [`#${ch.pr}`] : []), ...ch.work.map((w) => `work:${w}`)];
542
+ console.log(` ${ch.commit.slice(0, 12)} ${ch.subject}${links.length > 0 ? ` [${links.join(", ")}]` : ""}`);
543
+ }
544
+ for (const f of c.flags)
545
+ console.log(` flag ${f.id} (${f.member} ${f.param}) changed`);
546
+ }
547
+ for (const sk of doc.skipped)
548
+ console.log(`skipped ${sk.commit.slice(0, 12)} ${sk.subject} (revoked)`);
549
+ if (doc.candidates.length > 0)
550
+ console.error(`Cut one: chant release cut <label> --at <sha>`);
551
+ return 0;
552
+ }
481
553
  export async function runReleaseList(ctx) {
482
554
  const { releasesDocument } = await import("../../workspace/releases.js");
483
555
  const doc = await releasesDocument({ cwd: resolve(".") });
@@ -539,7 +611,7 @@ export async function runReleaseExport(ctx) {
539
611
  console.error(formatError({ message: target.error }));
540
612
  return 1;
541
613
  }
542
- const read = await targetFiles(found.release, target.target, (digest) => readReleaseTemplate(digest));
614
+ const read = await targetFiles(found.release, target.target, (digest, encoding) => readReleaseTemplate(digest, undefined, encoding));
543
615
  if ("errors" in read) {
544
616
  for (const e of read.errors)
545
617
  console.error(formatError({ message: e }));
@@ -1,8 +1,9 @@
1
1
  import { type OpConfig } from "../../op/types.js";
2
2
  import { type StepRecord } from "../../op/local-executor.js";
3
+ import type { OpRunRecord } from "../../op/runtime.js";
3
4
  import type { CommandContext } from "../registry.js";
4
5
  import type { RunEvent } from "../../run-event.js";
5
- import type { DriverComponentResult } from "../../components/driver.js";
6
+ import { type DriverComponentResult } from "../../components/driver.js";
6
7
  import { type ReleaseRecord, type RunOrigin } from "../../lifecycle/release-ledger.js";
7
8
  /**
8
9
  * The exit code a run that stopped at an unapproved gate uses (#2119).
@@ -170,4 +171,15 @@ export declare function resolveRunRelease(ref: string, env: string, cwd: string)
170
171
  */
171
172
  export declare function runOpOnRuntime(ctx: CommandContext): Promise<number>;
172
173
  export declare function runOpUnknown(ctx: CommandContext): Promise<number>;
174
+ /**
175
+ * What signs the run's record (#4044): the runner key `--key` names, or the
176
+ * PEM in `CHANT_RUNNER_KEY`, checked against `.chant/trust.json` at `HEAD`.
177
+ * Undefined when neither is given. Null, after printing why, when `--key`
178
+ * is not a runner key, or either is not an Ed25519 PEM. A `CHANT_RUNNER_KEY`
179
+ * that trust.json does not list leaves the run unsigned (#4156): quietly,
180
+ * with a line under `--verbose`, unless `ci.green.signedSince` asks for
181
+ * signed runs, which warns. The variable may be set for `ci tick` in a job
182
+ * that also runs Ops.
183
+ */
184
+ export declare function runSignerFor(ctx: CommandContext): Promise<((record: OpRunRecord) => NonNullable<OpRunRecord["statement"]>) | undefined | null>;
173
185
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/run.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ import { findStoredRun, readRunEvents } from "../../run-event-store.js";
27
27
  import { openCliRunEvents, refusesBothStreams, stdoutLine } from "../run-events.js";
28
28
  import { maybeRecordAutoRelease } from "../../components/auto-release.js";
29
29
  import { maybePersistBuildManifest } from "../../components/manifest-persistence.js";
30
+ import { failedRunExitCode } from "../../components/driver.js";
30
31
  import { isComponentList } from "../../components/cli-support.js";
31
32
  import { resolveCiRun } from "../../lifecycle/release-ledger.js";
32
33
  import { gateAdmission, gateApprover } from "../../components/promote.js";
@@ -639,9 +640,9 @@ function refusesPolicyGateUnderSandbox(ctx, config, opName) {
639
640
  * `chant run <op>` for an Op a declared steward lists is one of that
640
641
  * steward's turns, not a run beside it (#2750, follow-up to #2731).
641
642
  *
642
- * On fountain, the run belongs on the steward's thread: without `--on
643
+ * On fountain, the run belongs in the steward's conversation: without `--on
643
644
  * fountain` this refuses outright, naming the command that posts it there
644
- * instead (the fountain runtime's own turn already refuses a busy teammate,
645
+ * instead (the fountain runtime's own turn already refuses a busy steward,
645
646
  * unretried — see chant-fountain-ops).
646
647
  *
647
648
  * In the local form, the run takes the steward's turn lease
@@ -679,15 +680,15 @@ async function stewardTurnGate(opName, ctx) {
679
680
  const env = ctx.args.env ?? DEFAULT_STEWARD_ENV;
680
681
  const form = stewardFormFor(owner, env);
681
682
  if (form === "fountain") {
682
- // `run.on: "fountain"` asks for the steward's thread as much as the flag
683
+ // `run.on: "fountain"` asks for the steward's conversation as much as the flag
683
684
  // does (#2523).
684
685
  if ((await chooseOpRuntime(ctx, true))?.on === "fountain")
685
686
  return { ok: true };
686
687
  return {
687
688
  ok: false,
688
689
  message: `Op "${opName}" is one of steward "${owner.name}"'s Ops, which runs on fountain in environment "${env}"`,
689
- hint: `Run \`chant run ${opName} --on fountain\` so it posts to "${owner.name}"'s thread. ` +
690
- `A plain \`chant run ${opName}\` would run it outside that thread, beside the steward instead of one of its turns.`,
690
+ hint: `Run \`chant run ${opName} --on fountain\` so it posts to "${owner.name}"'s conversation. ` +
691
+ `A plain \`chant run ${opName}\` would run it outside that conversation, beside the steward instead of one of its turns.`,
691
692
  };
692
693
  }
693
694
  if (stewardBesideFor(owner, opName))
@@ -1171,7 +1172,11 @@ async function runComponentSelection(ctx) {
1171
1172
  writeFileSync(digestPath, recorded.map((r) => `${r.component}=${r.digest}\n`).join(""));
1172
1173
  }
1173
1174
  }
1174
- return result.success ? 0 : 1;
1175
+ // A step that refused a plan that moved since it was approved exits 3
1176
+ // (#3997). `--gated-exit` doesn't remap it: the run failed.
1177
+ if (result.success)
1178
+ return 0;
1179
+ return result.run ? failedRunExitCode(result.run.results) : 1;
1175
1180
  }
1176
1181
  /**
1177
1182
  * `chant run <name>` on the resolved runtime (#2121) — the built-in `local`
@@ -1239,9 +1244,10 @@ async function runOpOnResolvedRuntime(ctx) {
1239
1244
  await stewardGate?.release?.();
1240
1245
  return 1;
1241
1246
  }
1242
- // #4044: a runner key signs the run's record as it settles, so `ci tick`
1243
- // can count the run. `--key` must be a runner key; the PEM in
1244
- // CHANT_RUNNER_KEY that is not one leaves the run unsigned, with a warning.
1247
+ // #4044: a runner key signs the run's record as it settles, so a reader
1248
+ // can see who ran it. `--key` must be a runner key; the PEM in
1249
+ // CHANT_RUNNER_KEY that trust.json does not list leaves the run unsigned,
1250
+ // with a warning only when ci.green.signedSince asks for signed runs (#4156).
1245
1251
  const signRecord = await runSignerFor(ctx);
1246
1252
  if (signRecord === null) {
1247
1253
  await stewardGate?.release?.();
@@ -1441,10 +1447,13 @@ const RUNNER_KEY_ENV = "CHANT_RUNNER_KEY";
1441
1447
  * What signs the run's record (#4044): the runner key `--key` names, or the
1442
1448
  * PEM in `CHANT_RUNNER_KEY`, checked against `.chant/trust.json` at `HEAD`.
1443
1449
  * Undefined when neither is given. Null, after printing why, when `--key`
1444
- * is not a runner key; an unusable `CHANT_RUNNER_KEY` only warns, since the
1445
- * variable may be set for `ci tick` in a job that also runs Ops.
1450
+ * is not a runner key, or either is not an Ed25519 PEM. A `CHANT_RUNNER_KEY`
1451
+ * that trust.json does not list leaves the run unsigned (#4156): quietly,
1452
+ * with a line under `--verbose`, unless `ci.green.signedSince` asks for
1453
+ * signed runs, which warns. The variable may be set for `ci tick` in a job
1454
+ * that also runs Ops.
1446
1455
  */
1447
- async function runSignerFor(ctx) {
1456
+ export async function runSignerFor(ctx) {
1448
1457
  const fromFlag = ctx.args.key !== undefined;
1449
1458
  let pem;
1450
1459
  try {
@@ -1456,9 +1465,18 @@ async function runSignerFor(ctx) {
1456
1465
  }
1457
1466
  if (pem === undefined)
1458
1467
  return undefined;
1468
+ // Loaded only when a key is given, so a run without one loads no workspace code (level 0, #2525).
1469
+ const { opRunSigner, signedRunsRequired } = await import("../../workspace/ci-green.js");
1470
+ const { loadRunnerKey } = await import("../../workspace/trust/dsse.js");
1471
+ try {
1472
+ loadRunnerKey(pem);
1473
+ }
1474
+ catch (err) {
1475
+ // A key that is there and is not one is an error either way: the caller asked to sign (#4156).
1476
+ console.error(formatError({ message: `${fromFlag ? `--key ${ctx.args.key}` : RUNNER_KEY_ENV} is not an Ed25519 private key in PEM: ${err instanceof Error ? err.message : String(err)}` }));
1477
+ return null;
1478
+ }
1459
1479
  try {
1460
- // Loaded only when a key is given, so a run without one loads no workspace code (level 0, #2525).
1461
- const { opRunSigner } = await import("../../workspace/ci-green.js");
1462
1480
  return opRunSigner(process.cwd(), pem);
1463
1481
  }
1464
1482
  catch (err) {
@@ -1467,7 +1485,12 @@ async function runSignerFor(ctx) {
1467
1485
  console.error(formatError({ message: `the run would not be signed: ${message}` }));
1468
1486
  return null;
1469
1487
  }
1470
- console.error(formatWarning({ message: `${RUNNER_KEY_ENV} is set, and the run will not be signed: ${message}` }));
1488
+ // #4156: signing is opt-in, so a key trust.json does not list warns only when ci.green.signedSince asks for signed runs.
1489
+ const required = signedRunsRequired(process.cwd());
1490
+ if (required)
1491
+ console.error(formatWarning({ message: `${RUNNER_KEY_ENV} is set, and the run will not be signed, so ci.green.signedSince (${required}) will not count it: ${message}` }));
1492
+ else if (ctx.args.verbose)
1493
+ console.error(`${RUNNER_KEY_ENV} is set, and the run is not signed: ${message}`);
1471
1494
  return undefined;
1472
1495
  }
1473
1496
  }
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAkB,KAAK,UAAU,EAAmB,MAAM,YAAY,CAAC;AAa9E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAgB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;AA6uCzC;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBzE;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,EAsMvC,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAkB,KAAK,UAAU,EAAmB,MAAM,YAAY,CAAC;AAa9E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAgB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;AAuzCzC;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBzE;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,EA4MvC,CAAC"}