@intentius/chant 0.124.27 → 0.124.28

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 (450) 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/change-set-graph.d.ts +56 -0
  20. package/dist/change-set-graph.d.ts.map +1 -0
  21. package/dist/change-set-graph.js +128 -0
  22. package/dist/change-set.d.ts +52 -3
  23. package/dist/change-set.d.ts.map +1 -1
  24. package/dist/change-set.js +35 -4
  25. package/dist/chant-version.d.ts +9 -0
  26. package/dist/chant-version.d.ts.map +1 -0
  27. package/dist/chant-version.js +16 -0
  28. package/dist/cli/commands/build.d.ts +8 -0
  29. package/dist/cli/commands/build.d.ts.map +1 -1
  30. package/dist/cli/commands/build.js +9 -8
  31. package/dist/cli/commands/check-lexicon-docs.d.ts.map +1 -1
  32. package/dist/cli/commands/check-lexicon-docs.js +30 -2
  33. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  34. package/dist/cli/commands/check-lexicon.js +13 -2
  35. package/dist/cli/commands/init-lexicon/templates/docs.d.ts +4 -1
  36. package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -1
  37. package/dist/cli/commands/init-lexicon/templates/docs.js +6 -6
  38. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  39. package/dist/cli/commands/init-lexicon.js +17 -8
  40. package/dist/cli/handlers/approve.d.ts.map +1 -1
  41. package/dist/cli/handlers/approve.js +19 -4
  42. package/dist/cli/handlers/build.d.ts.map +1 -1
  43. package/dist/cli/handlers/build.js +28 -0
  44. package/dist/cli/handlers/change-set.d.ts +10 -0
  45. package/dist/cli/handlers/change-set.d.ts.map +1 -1
  46. package/dist/cli/handlers/change-set.js +51 -1
  47. package/dist/cli/handlers/fan-out.d.ts +1 -1
  48. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  49. package/dist/cli/handlers/fan-out.js +14 -3
  50. package/dist/cli/handlers/pr.d.ts +8 -2
  51. package/dist/cli/handlers/pr.d.ts.map +1 -1
  52. package/dist/cli/handlers/pr.js +148 -24
  53. package/dist/cli/handlers/promote.d.ts.map +1 -1
  54. package/dist/cli/handlers/promote.js +256 -21
  55. package/dist/cli/handlers/release.d.ts +34 -0
  56. package/dist/cli/handlers/release.d.ts.map +1 -0
  57. package/dist/cli/handlers/release.js +203 -0
  58. package/dist/cli/handlers/run.d.ts +28 -2
  59. package/dist/cli/handlers/run.d.ts.map +1 -1
  60. package/dist/cli/handlers/run.js +170 -13
  61. package/dist/cli/main.d.ts.map +1 -1
  62. package/dist/cli/main.js +88 -13
  63. package/dist/cli/mcp/workspace-tools.js +1 -1
  64. package/dist/cli/parse-args.d.ts.map +1 -1
  65. package/dist/cli/parse-args.js +49 -3
  66. package/dist/cli/registry.d.ts +29 -3
  67. package/dist/cli/registry.d.ts.map +1 -1
  68. package/dist/cli/run-events.d.ts +29 -0
  69. package/dist/cli/run-events.d.ts.map +1 -0
  70. package/dist/cli/run-events.js +47 -0
  71. package/dist/cli/version.d.ts +3 -5
  72. package/dist/cli/version.d.ts.map +1 -1
  73. package/dist/cli/version.js +3 -13
  74. package/dist/codegen/docs-in-site.d.ts +71 -0
  75. package/dist/codegen/docs-in-site.d.ts.map +1 -0
  76. package/dist/codegen/docs-in-site.js +177 -0
  77. package/dist/codegen/docs-types.d.ts +14 -1
  78. package/dist/codegen/docs-types.d.ts.map +1 -1
  79. package/dist/codegen/docs.d.ts +18 -1
  80. package/dist/codegen/docs.d.ts.map +1 -1
  81. package/dist/codegen/docs.js +40 -7
  82. package/dist/codegen/rehype-base-url.mjs +15 -9
  83. package/dist/components/auto-release.d.ts +4 -1
  84. package/dist/components/auto-release.d.ts.map +1 -1
  85. package/dist/components/auto-release.js +2 -0
  86. package/dist/components/cli-support.d.ts +6 -0
  87. package/dist/components/cli-support.d.ts.map +1 -1
  88. package/dist/components/cli-support.js +10 -9
  89. package/dist/components/driver.d.ts +42 -9
  90. package/dist/components/driver.d.ts.map +1 -1
  91. package/dist/components/driver.js +81 -54
  92. package/dist/components/fan-out-run.d.ts +7 -0
  93. package/dist/components/fan-out-run.d.ts.map +1 -1
  94. package/dist/components/fan-out-run.js +35 -26
  95. package/dist/components/pr-run.d.ts +11 -0
  96. package/dist/components/pr-run.d.ts.map +1 -1
  97. package/dist/components/pr-run.js +20 -1
  98. package/dist/components/promote-order.d.ts +38 -0
  99. package/dist/components/promote-order.d.ts.map +1 -0
  100. package/dist/components/promote-order.js +62 -0
  101. package/dist/components/promote.d.ts +15 -2
  102. package/dist/components/promote.d.ts.map +1 -1
  103. package/dist/components/promote.js +17 -0
  104. package/dist/components/release-compile.d.ts +133 -0
  105. package/dist/components/release-compile.d.ts.map +1 -0
  106. package/dist/components/release-compile.js +376 -0
  107. package/dist/components/release-gate.d.ts +125 -0
  108. package/dist/components/release-gate.d.ts.map +1 -0
  109. package/dist/components/release-gate.js +282 -0
  110. package/dist/components/release-promote.d.ts +96 -0
  111. package/dist/components/release-promote.d.ts.map +1 -0
  112. package/dist/components/release-promote.js +204 -0
  113. package/dist/components/run-progress.d.ts +7 -0
  114. package/dist/components/run-progress.d.ts.map +1 -1
  115. package/dist/components/wave-plan.d.ts +3 -1
  116. package/dist/components/wave-plan.d.ts.map +1 -1
  117. package/dist/components/wave-plan.js +1 -1
  118. package/dist/config.d.ts +7 -0
  119. package/dist/config.d.ts.map +1 -1
  120. package/dist/config.js +1 -0
  121. package/dist/index.d.ts +1 -0
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +2 -0
  124. package/dist/lifecycle/change-set-store.d.ts +67 -0
  125. package/dist/lifecycle/change-set-store.d.ts.map +1 -0
  126. package/dist/lifecycle/change-set-store.js +96 -0
  127. package/dist/lifecycle/commit-sha.d.ts +13 -0
  128. package/dist/lifecycle/commit-sha.d.ts.map +1 -0
  129. package/dist/lifecycle/commit-sha.js +21 -0
  130. package/dist/lifecycle/gate-change-set.d.ts +69 -0
  131. package/dist/lifecycle/gate-change-set.d.ts.map +1 -0
  132. package/dist/lifecycle/gate-change-set.js +106 -0
  133. package/dist/lifecycle/gate-ledger.d.ts +49 -1
  134. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  135. package/dist/lifecycle/gate-ledger.js +18 -0
  136. package/dist/lifecycle/release-cut.d.ts +107 -0
  137. package/dist/lifecycle/release-cut.d.ts.map +1 -0
  138. package/dist/lifecycle/release-cut.js +273 -0
  139. package/dist/lifecycle/release-ledger.d.ts +54 -0
  140. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  141. package/dist/lifecycle/release-ledger.js +53 -20
  142. package/dist/lifecycle/release-store.d.ts +190 -0
  143. package/dist/lifecycle/release-store.d.ts.map +1 -0
  144. package/dist/lifecycle/release-store.js +318 -0
  145. package/dist/lifecycle/run-ledger.d.ts +4 -0
  146. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  147. package/dist/lifecycle/run-ledger.js +2 -0
  148. package/dist/op/activities/change-coverage.d.ts.map +1 -1
  149. package/dist/op/activities/change-coverage.js +4 -2
  150. package/dist/op/activities/source-release.d.ts.map +1 -1
  151. package/dist/op/activities/source-release.js +7 -3
  152. package/dist/op/activities/source-rollback.d.ts.map +1 -1
  153. package/dist/op/activities/source-rollback.js +7 -3
  154. package/dist/op/gate-name.d.ts +11 -2
  155. package/dist/op/gate-name.d.ts.map +1 -1
  156. package/dist/op/gate-name.js +12 -3
  157. package/dist/op/gate-run-locator.d.ts +22 -0
  158. package/dist/op/gate-run-locator.d.ts.map +1 -1
  159. package/dist/op/gate-run-locator.js +31 -0
  160. package/dist/op/gate.d.ts +27 -3
  161. package/dist/op/gate.d.ts.map +1 -1
  162. package/dist/op/gate.js +57 -3
  163. package/dist/op/local-executor.d.ts +36 -1
  164. package/dist/op/local-executor.d.ts.map +1 -1
  165. package/dist/op/local-executor.js +158 -52
  166. package/dist/op/op-waves-run.d.ts.map +1 -1
  167. package/dist/op/op-waves-run.js +4 -0
  168. package/dist/op/run-live.d.ts +2 -0
  169. package/dist/op/run-live.d.ts.map +1 -1
  170. package/dist/op/run-live.js +1 -1
  171. package/dist/op/runtime.d.ts +46 -0
  172. package/dist/op/runtime.d.ts.map +1 -1
  173. package/dist/op/runtimes/local.d.ts.map +1 -1
  174. package/dist/op/runtimes/local.js +8 -0
  175. package/dist/point-decision.d.ts +2 -0
  176. package/dist/point-decision.d.ts.map +1 -1
  177. package/dist/point-decision.js +9 -2
  178. package/dist/run-event-store.d.ts +77 -0
  179. package/dist/run-event-store.d.ts.map +1 -0
  180. package/dist/run-event-store.js +204 -0
  181. package/dist/run-event-stream.d.ts +132 -0
  182. package/dist/run-event-stream.d.ts.map +1 -0
  183. package/dist/run-event-stream.js +238 -0
  184. package/dist/run-event.d.ts +267 -0
  185. package/dist/run-event.d.ts.map +1 -0
  186. package/dist/run-event.js +207 -0
  187. package/dist/wave-runtime.mjs +204 -199
  188. package/dist/workspace/__fixtures__/run-event-check.d.ts +19 -0
  189. package/dist/workspace/__fixtures__/run-event-check.d.ts.map +1 -0
  190. package/dist/workspace/__fixtures__/run-event-check.js +59 -0
  191. package/dist/workspace/change-set-show.d.ts +56 -0
  192. package/dist/workspace/change-set-show.d.ts.map +1 -0
  193. package/dist/workspace/change-set-show.js +54 -0
  194. package/dist/workspace/change-set-show.schema.json +102 -0
  195. package/dist/workspace/change-set.schema.json +28 -1
  196. package/dist/workspace/changes-cli.d.ts.map +1 -1
  197. package/dist/workspace/changes-cli.js +10 -1
  198. package/dist/workspace/changes.d.ts +37 -0
  199. package/dist/workspace/changes.d.ts.map +1 -1
  200. package/dist/workspace/changes.js +49 -2
  201. package/dist/workspace/changes.schema.json +135 -0
  202. package/dist/workspace/ci-green-cli.d.ts +19 -4
  203. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  204. package/dist/workspace/ci-green-cli.js +75 -12
  205. package/dist/workspace/ci-green-forge.d.ts +20 -3
  206. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  207. package/dist/workspace/ci-green-forge.js +6 -4
  208. package/dist/workspace/ci-green-workflow.d.ts +11 -0
  209. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  210. package/dist/workspace/ci-green-workflow.js +6 -0
  211. package/dist/workspace/ci-green.d.ts +273 -13
  212. package/dist/workspace/ci-green.d.ts.map +1 -1
  213. package/dist/workspace/ci-green.js +449 -38
  214. package/dist/workspace/ci-last-green.schema.json +32 -2
  215. package/dist/workspace/ci-list.schema.json +525 -0
  216. package/dist/workspace/commit-links.d.ts +85 -0
  217. package/dist/workspace/commit-links.d.ts.map +1 -0
  218. package/dist/workspace/commit-links.js +163 -0
  219. package/dist/workspace/declaration.d.ts +19 -0
  220. package/dist/workspace/declaration.d.ts.map +1 -1
  221. package/dist/workspace/declaration.js +1 -1
  222. package/dist/workspace/declaration.schema.json +12 -0
  223. package/dist/workspace/identity-gate-rule.d.ts +37 -0
  224. package/dist/workspace/identity-gate-rule.d.ts.map +1 -1
  225. package/dist/workspace/identity-gate-rule.js +72 -7
  226. package/dist/workspace/identity.d.ts +12 -0
  227. package/dist/workspace/identity.d.ts.map +1 -1
  228. package/dist/workspace/identity.js +13 -1
  229. package/dist/workspace/intent.d.ts +6 -1
  230. package/dist/workspace/intent.d.ts.map +1 -1
  231. package/dist/workspace/intent.js +51 -1
  232. package/dist/workspace/ls.d.ts +4 -0
  233. package/dist/workspace/ls.d.ts.map +1 -1
  234. package/dist/workspace/ls.js +2 -0
  235. package/dist/workspace/ls.schema.json +3 -1
  236. package/dist/workspace/member-pipeline.d.ts +6 -0
  237. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  238. package/dist/workspace/member-pipeline.js +6 -0
  239. package/dist/workspace/promotion-order.d.ts +41 -0
  240. package/dist/workspace/promotion-order.d.ts.map +1 -0
  241. package/dist/workspace/promotion-order.js +95 -0
  242. package/dist/workspace/reason-codes.d.ts +2 -0
  243. package/dist/workspace/reason-codes.d.ts.map +1 -1
  244. package/dist/workspace/reason-codes.js +4 -1
  245. package/dist/workspace/releases.d.ts +72 -0
  246. package/dist/workspace/releases.d.ts.map +1 -0
  247. package/dist/workspace/releases.js +94 -0
  248. package/dist/workspace/releases.schema.json +391 -0
  249. package/dist/workspace/run-event.schema.json +288 -0
  250. package/dist/workspace/status-gates.d.ts +26 -1
  251. package/dist/workspace/status-gates.d.ts.map +1 -1
  252. package/dist/workspace/status-gates.js +31 -2
  253. package/dist/workspace/status-stewards.d.ts +4 -0
  254. package/dist/workspace/status-stewards.d.ts.map +1 -1
  255. package/dist/workspace/status-stewards.js +2 -0
  256. package/dist/workspace/status.d.ts +39 -0
  257. package/dist/workspace/status.d.ts.map +1 -1
  258. package/dist/workspace/status.js +48 -1
  259. package/dist/workspace/status.schema.json +70 -1
  260. package/dist/workspace/trust/ci-tag-statement.d.ts +102 -0
  261. package/dist/workspace/trust/ci-tag-statement.d.ts.map +1 -0
  262. package/dist/workspace/trust/ci-tag-statement.js +123 -0
  263. package/dist/workspace/trust/op-run-statement.d.ts +91 -0
  264. package/dist/workspace/trust/op-run-statement.d.ts.map +1 -0
  265. package/dist/workspace/trust/op-run-statement.js +143 -0
  266. package/dist/workspace/trust/rotation.d.ts +18 -2
  267. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  268. package/dist/workspace/trust/rotation.js +65 -16
  269. package/dist/workspace/trust/seal.d.ts +11 -0
  270. package/dist/workspace/trust/seal.d.ts.map +1 -1
  271. package/dist/workspace/trust/seal.js +9 -0
  272. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
  273. package/dist/workspace/trust/ssh-commit.js +10 -10
  274. package/package.json +1 -1
  275. package/src/__golden__/wave-loop/fan-out-gated.json +8 -0
  276. package/src/__golden__/wave-loop/fan-out-no-members.json +4 -0
  277. package/src/__golden__/wave-loop/fan-out-only.json +6 -0
  278. package/src/__golden__/wave-loop/op-by-apply-hold.json +2 -0
  279. package/src/__golden__/wave-loop/op-cost-member.json +3 -0
  280. package/src/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
  281. package/src/__golden__/wave-loop/op-held-on.json +2 -0
  282. package/src/__golden__/wave-loop/op-hooks-held.json +2 -0
  283. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
  284. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
  285. package/src/__golden__/wave-loop/op-hooks-share.json +3 -0
  286. package/src/__golden__/wave-loop/op-per-run.json +7 -0
  287. package/src/__golden__/wave-loop/op-pr-review.json +7 -0
  288. package/src/__golden__/wave-loop/op-sealed.json +3 -0
  289. package/src/__golden__/wave-loop/op-spend.json +3 -0
  290. package/src/__golden__/wave-loop/op-wave-commands.json +7 -0
  291. package/src/__golden__/wave-loop/op-wide-waiting.json +4 -0
  292. package/src/change-set-graph.test.ts +72 -0
  293. package/src/change-set-graph.ts +133 -0
  294. package/src/change-set.ts +76 -6
  295. package/src/chant-version.ts +16 -0
  296. package/src/cli/commands/build.ts +19 -8
  297. package/src/cli/commands/check-lexicon-docs.test.ts +51 -0
  298. package/src/cli/commands/check-lexicon-docs.ts +39 -2
  299. package/src/cli/commands/check-lexicon.ts +14 -2
  300. package/src/cli/commands/init-lexicon/templates/docs.ts +7 -6
  301. package/src/cli/commands/init-lexicon.test.ts +25 -0
  302. package/src/cli/commands/init-lexicon.ts +18 -8
  303. package/src/cli/handlers/approve-release.test.ts +80 -0
  304. package/src/cli/handlers/approve.ts +18 -2
  305. package/src/cli/handlers/build.test.ts +52 -0
  306. package/src/cli/handlers/build.ts +29 -0
  307. package/src/cli/handlers/change-set.ts +49 -1
  308. package/src/cli/handlers/fan-out.test.ts +48 -0
  309. package/src/cli/handlers/fan-out.ts +15 -3
  310. package/src/cli/handlers/operator.test.ts +37 -0
  311. package/src/cli/handlers/pr.test.ts +194 -0
  312. package/src/cli/handlers/pr.ts +168 -34
  313. package/src/cli/handlers/promote.test.ts +389 -5
  314. package/src/cli/handlers/promote.ts +279 -20
  315. package/src/cli/handlers/release-implicit.e2e.test.ts +153 -0
  316. package/src/cli/handlers/release.e2e.test.ts +85 -0
  317. package/src/cli/handlers/release.ts +206 -0
  318. package/src/cli/handlers/run-auto-release.test.ts +71 -0
  319. package/src/cli/handlers/run-events-cmd.test.ts +92 -0
  320. package/src/cli/handlers/run.test.ts +30 -0
  321. package/src/cli/handlers/run.ts +176 -15
  322. package/src/cli/main.test.ts +7 -0
  323. package/src/cli/main.ts +88 -13
  324. package/src/cli/mcp/never-over-mcp.test.ts +2 -0
  325. package/src/cli/mcp/workspace-tools.ts +1 -1
  326. package/src/cli/parse-args.ts +37 -3
  327. package/src/cli/registry.ts +29 -3
  328. package/src/cli/run-events.ts +54 -0
  329. package/src/cli/version.ts +3 -13
  330. package/src/codegen/docs-in-site.test.ts +166 -0
  331. package/src/codegen/docs-in-site.ts +182 -0
  332. package/src/codegen/docs-site/AgentPrompt.astro +26 -1
  333. package/src/codegen/docs-types.ts +14 -1
  334. package/src/codegen/docs.ts +60 -7
  335. package/src/codegen/rehype-base-url.d.mts +3 -1
  336. package/src/codegen/rehype-base-url.mjs +15 -9
  337. package/src/codegen/rehype-base-url.test.ts +34 -0
  338. package/src/components/auto-release.test.ts +21 -0
  339. package/src/components/auto-release.ts +6 -1
  340. package/src/components/cli-support.test.ts +82 -0
  341. package/src/components/cli-support.ts +16 -9
  342. package/src/components/driver.ts +129 -56
  343. package/src/components/fan-out-run.ts +56 -35
  344. package/src/components/pr-run.ts +30 -1
  345. package/src/components/promote-order.test.ts +90 -0
  346. package/src/components/promote-order.ts +75 -0
  347. package/src/components/promote.test.ts +10 -1
  348. package/src/components/promote.ts +26 -1
  349. package/src/components/release-compile.test.ts +147 -0
  350. package/src/components/release-compile.ts +445 -0
  351. package/src/components/release-gate.test.ts +215 -0
  352. package/src/components/release-gate.ts +341 -0
  353. package/src/components/release-promote.test.ts +159 -0
  354. package/src/components/release-promote.ts +232 -0
  355. package/src/components/run-progress.ts +7 -0
  356. package/src/components/wave-plan.ts +1 -1
  357. package/src/config.ts +7 -1
  358. package/src/index.ts +2 -0
  359. package/src/lifecycle/change-set-store.test.ts +217 -0
  360. package/src/lifecycle/change-set-store.ts +112 -0
  361. package/src/lifecycle/commit-sha.ts +23 -0
  362. package/src/lifecycle/gate-change-set.e2e.test.ts +122 -0
  363. package/src/lifecycle/gate-change-set.ts +133 -0
  364. package/src/lifecycle/gate-ledger.test.ts +33 -0
  365. package/src/lifecycle/gate-ledger.ts +66 -1
  366. package/src/lifecycle/release-cut-signed.test.ts +180 -0
  367. package/src/lifecycle/release-cut.test.ts +411 -0
  368. package/src/lifecycle/release-cut.ts +367 -0
  369. package/src/lifecycle/release-ledger.test.ts +14 -0
  370. package/src/lifecycle/release-ledger.ts +85 -17
  371. package/src/lifecycle/release-store.ts +423 -0
  372. package/src/lifecycle/run-ledger.test.ts +10 -0
  373. package/src/lifecycle/run-ledger.ts +6 -0
  374. package/src/op/activities/change-coverage.ts +4 -1
  375. package/src/op/activities/source-release.ts +8 -3
  376. package/src/op/activities/source-rollback.ts +8 -4
  377. package/src/op/commit-run-gate-deploy-join.test.ts +117 -0
  378. package/src/op/gate-name.ts +13 -3
  379. package/src/op/gate-release.test.ts +126 -0
  380. package/src/op/gate-run-locator.test.ts +110 -0
  381. package/src/op/gate-run-locator.ts +35 -0
  382. package/src/op/gate.ts +88 -6
  383. package/src/op/local-executor.ts +207 -52
  384. package/src/op/op-waves-run.ts +4 -0
  385. package/src/op/run-events.test.ts +166 -0
  386. package/src/op/run-live.ts +1 -1
  387. package/src/op/runtime.ts +39 -0
  388. package/src/op/runtimes/local.test.ts +16 -0
  389. package/src/op/runtimes/local.ts +9 -0
  390. package/src/point-decision.ts +12 -2
  391. package/src/run-event-store.test.ts +144 -0
  392. package/src/run-event-store.ts +213 -0
  393. package/src/run-event-stream.test.ts +175 -0
  394. package/src/run-event-stream.ts +306 -0
  395. package/src/run-event.test.ts +277 -0
  396. package/src/run-event.ts +451 -0
  397. package/src/wave-loop-golden.test.ts +9 -0
  398. package/src/workspace/__fixtures__/run-event-check.ts +58 -0
  399. package/src/workspace/ancestry-index.test.ts +93 -0
  400. package/src/workspace/change-set-show.schema.json +102 -0
  401. package/src/workspace/change-set-show.ts +72 -0
  402. package/src/workspace/change-set.schema.json +28 -1
  403. package/src/workspace/changes-cli.ts +10 -1
  404. package/src/workspace/changes.schema.json +135 -0
  405. package/src/workspace/changes.test.ts +1 -1
  406. package/src/workspace/changes.ts +84 -2
  407. package/src/workspace/ci-green-cli.ts +75 -13
  408. package/src/workspace/ci-green-forge.ts +24 -4
  409. package/src/workspace/ci-green-runs.test.ts +242 -0
  410. package/src/workspace/ci-green-signed.test.ts +302 -0
  411. package/src/workspace/ci-green-workflow.test.ts +16 -0
  412. package/src/workspace/ci-green-workflow.ts +12 -0
  413. package/src/workspace/ci-green.test.ts +131 -2
  414. package/src/workspace/ci-green.ts +624 -42
  415. package/src/workspace/ci-last-green.schema.json +32 -2
  416. package/src/workspace/ci-list.schema.json +525 -0
  417. package/src/workspace/commit-links.test.ts +279 -0
  418. package/src/workspace/commit-links.ts +183 -0
  419. package/src/workspace/declaration.schema.json +12 -0
  420. package/src/workspace/declaration.ts +22 -2
  421. package/src/workspace/identity-gate-rule.ts +91 -7
  422. package/src/workspace/identity.ts +14 -1
  423. package/src/workspace/intent.ts +48 -1
  424. package/src/workspace/ls.schema.json +3 -1
  425. package/src/workspace/ls.ts +6 -0
  426. package/src/workspace/member-pipeline.test.ts +17 -0
  427. package/src/workspace/member-pipeline.ts +9 -0
  428. package/src/workspace/promotion-order.ts +97 -0
  429. package/src/workspace/read-contract.e2e.test.ts +4 -1
  430. package/src/workspace/reason-codes.test.ts +2 -1
  431. package/src/workspace/reason-codes.ts +4 -1
  432. package/src/workspace/releases.schema.json +391 -0
  433. package/src/workspace/releases.test.ts +108 -0
  434. package/src/workspace/releases.ts +122 -0
  435. package/src/workspace/run-event.schema.json +288 -0
  436. package/src/workspace/status-contract.test.ts +52 -1
  437. package/src/workspace/status-gates.ts +56 -1
  438. package/src/workspace/status-stewards.ts +6 -0
  439. package/src/workspace/status.schema.json +70 -1
  440. package/src/workspace/status.ts +80 -1
  441. package/src/workspace/trust/ci-tag-statement.ts +151 -0
  442. package/src/workspace/trust/op-run-statement.ts +148 -0
  443. package/src/workspace/trust/rotation.ts +61 -14
  444. package/src/workspace/trust/seal.ts +10 -0
  445. package/src/workspace/trust/ssh-commit.ts +10 -9
  446. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +0 -14
  447. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +0 -16
  448. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +0 -8
  449. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +0 -15
  450. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +0 -10
@@ -0,0 +1,19 @@
1
+ /**
2
+ * What every emitter's test checks about a run's stream (#4041): each line
3
+ * passes `run-event.schema.json`, the stream opens with `run-start` and ends
4
+ * with one `run-settle`, `seq` counts from 0, every line names the same run,
5
+ * and every step that starts settles after its start, under the same step id.
6
+ */
7
+ import type { RunEvent } from "../../run-event.js";
8
+ /** A step's id in the stream: its component, phase, name and place. */
9
+ export declare function stepKey(e: {
10
+ component: string | null;
11
+ phase: string;
12
+ step: string;
13
+ index?: number;
14
+ }): string;
15
+ /** Check a stream's lines and hand back its events. */
16
+ export declare function checkRunEventLines(lines: string[]): RunEvent[];
17
+ /** The step events of a stream, as `[type, step, status]`, for a compact assertion. */
18
+ export declare function stepTrail(events: RunEvent[]): Array<[string, string, string?]>;
19
+ //# sourceMappingURL=run-event-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-event-check.d.ts","sourceRoot":"","sources":["../../../src/workspace/__fixtures__/run-event-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE5G;AAED,uDAAuD;AACvD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CA0B9D;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAQ9E"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * What every emitter's test checks about a run's stream (#4041): each line
3
+ * passes `run-event.schema.json`, the stream opens with `run-start` and ends
4
+ * with one `run-settle`, `seq` counts from 0, every line names the same run,
5
+ * and every step that starts settles after its start, under the same step id.
6
+ */
7
+ import { expect } from "vitest";
8
+ import { contract } from "./contract-repo.js";
9
+ import schema from "../run-event.schema.json";
10
+ const { expectValid } = contract(schema);
11
+ /** A step's id in the stream: its component, phase, name and place. */
12
+ export function stepKey(e) {
13
+ return JSON.stringify([e.component, e.phase, e.step, e.index ?? null]);
14
+ }
15
+ /** Check a stream's lines and hand back its events. */
16
+ export function checkRunEventLines(lines) {
17
+ for (const line of lines)
18
+ expect(line.endsWith("\n")).toBe(true);
19
+ const events = lines.map((l) => JSON.parse(l));
20
+ for (const event of events)
21
+ expectValid(event);
22
+ expect(events.map((e) => e.seq)).toEqual(events.map((_, i) => i));
23
+ expect(events[0]?.type).toBe("run-start");
24
+ expect(events.at(-1)?.type).toBe("run-settle");
25
+ expect(events.filter((e) => e.type === "run-settle")).toHaveLength(1);
26
+ const runs = new Set(events.map((e) => JSON.stringify([e.runId, e.kind, e.name, e.gitSha, e.runtime, e.runOrigin])));
27
+ expect(runs.size).toBe(1);
28
+ const open = new Map();
29
+ for (const e of events) {
30
+ if (e.type === "step-start") {
31
+ const key = stepKey(e);
32
+ expect(open.has(key), `${key} started twice`).toBe(false);
33
+ open.set(key, e.seq);
34
+ }
35
+ else if (e.type === "step-settle") {
36
+ const key = stepKey(e);
37
+ if (open.has(key))
38
+ open.delete(key);
39
+ // Only a step that never ran settles without a start.
40
+ else
41
+ expect(e.status, `${key} settled ${e.status} with no step-start`).toBe("skipped");
42
+ }
43
+ }
44
+ expect([...open.keys()], "steps that started and never settled").toEqual([]);
45
+ return events;
46
+ }
47
+ /** The step events of a stream, as `[type, step, status]`, for a compact assertion. */
48
+ export function stepTrail(events) {
49
+ const out = [];
50
+ for (const e of events) {
51
+ if (e.type === "step-start")
52
+ out.push([e.type, e.step]);
53
+ else if (e.type === "step-settle")
54
+ out.push([e.type, e.step, e.skip ? `${e.status}:${e.skip}` : e.status]);
55
+ else if (e.type === "gate-waiting" || e.type === "gate-resolved")
56
+ out.push([e.type, e.step]);
57
+ }
58
+ return out;
59
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The stored change-set read (#4022): `chant change-set show <digest> --json`.
3
+ *
4
+ * Prints the change-set document a gate bound, as `components pr-apply`
5
+ * stored it, or as a release gate stores it with #4045
6
+ * (`../lifecycle/change-set-store.ts`). Each entry carries the graph `node`
7
+ * it changes, as `chant workspace graph` names nodes. It reads the local
8
+ * `chant/lifecycle` branch and never fetches.
9
+ *
10
+ * A digest with nothing stored under it is a result with `changeSet: null`,
11
+ * since a component gate binds a lifecycle-plan digest and stores no
12
+ * document. A stored file that is not the document its digest names is also
13
+ * `changeSet: null`, with the reason `ledger-malformed`. A read that fails
14
+ * outright is the failure `ledger-unreadable`.
15
+ */
16
+ import type { ChangeSetDocument } from "../change-set.js";
17
+ export declare const CHANGE_SET_SHOW_CONTRACT_VERSION = 1;
18
+ export declare const CHANGE_SET_SHOW_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/change-set-show/v1/change-set-show.schema.json";
19
+ /** Why the read stopped. Closed; each code is in `reason-codes.ts`. */
20
+ export declare const CHANGE_SET_SHOW_ERROR_CODES: readonly ["not-a-git-repository", "ledger-unreadable"];
21
+ /** Why a stored file was not shown. */
22
+ export declare const CHANGE_SET_SHOW_REASON_CODES: readonly ["ledger-malformed"];
23
+ /** What a change-set digest looks like: a plan digest's form. */
24
+ export declare const CHANGE_SET_DIGEST_PATTERN: RegExp;
25
+ export type ChangeSetShowDocument = {
26
+ $schema: string;
27
+ contract: number;
28
+ chant: string;
29
+ /** The member whose ledger was read, its path of names joined with `/`, or null outside a workspace. */
30
+ member: string | null;
31
+ digest: string;
32
+ /** The stored document, or null when none is stored under the digest. */
33
+ changeSet: ChangeSetDocument | null;
34
+ reason: {
35
+ code: (typeof CHANGE_SET_SHOW_REASON_CODES)[number];
36
+ message: string;
37
+ } | null;
38
+ } | {
39
+ $schema: string;
40
+ contract: number;
41
+ chant: string;
42
+ error: {
43
+ code: (typeof CHANGE_SET_SHOW_ERROR_CODES)[number];
44
+ message: string;
45
+ };
46
+ };
47
+ /**
48
+ * Read the change set stored under `digest` in the ledger of the member at
49
+ * `cwd`, or of `member` (its path of names, outermost first) when given.
50
+ */
51
+ export declare function changeSetShowDocument(req: {
52
+ cwd: string;
53
+ digest: string;
54
+ member?: readonly string[];
55
+ }): Promise<ChangeSetShowDocument>;
56
+ //# sourceMappingURL=change-set-show.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-set-show.d.ts","sourceRoot":"","sources":["../../src/workspace/change-set-show.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAKvD,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,eAAO,MAAM,yBAAyB,gGAAgG,CAAC;AAEvI,uEAAuE;AACvE,eAAO,MAAM,2BAA2B,YAAI,sBAAsB,EAAE,mBAAmB,CAAU,CAAC;AAClG,uCAAuC;AACvC,eAAO,MAAM,4BAA4B,YAAI,kBAAkB,CAAU,CAAC;AAE1E,iEAAiE;AACjE,eAAO,MAAM,yBAAyB,QAAoC,CAAC;AAE3E,MAAM,MAAM,qBAAqB,GAC7B;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,wGAAwG;IACxG,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACzF,GACD;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEzI;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAoB5I"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The stored change-set read (#4022): `chant change-set show <digest> --json`.
3
+ *
4
+ * Prints the change-set document a gate bound, as `components pr-apply`
5
+ * stored it, or as a release gate stores it with #4045
6
+ * (`../lifecycle/change-set-store.ts`). Each entry carries the graph `node`
7
+ * it changes, as `chant workspace graph` names nodes. It reads the local
8
+ * `chant/lifecycle` branch and never fetches.
9
+ *
10
+ * A digest with nothing stored under it is a result with `changeSet: null`,
11
+ * since a component gate binds a lifecycle-plan digest and stores no
12
+ * document. A stored file that is not the document its digest names is also
13
+ * `changeSet: null`, with the reason `ledger-malformed`. A read that fails
14
+ * outright is the failure `ledger-unreadable`.
15
+ */
16
+ import { execFileSync } from "node:child_process";
17
+ import { readStoredChangeSet } from "../lifecycle/change-set-store.js";
18
+ import { resolveMemberLedger } from "../lifecycle/member-ledger.js";
19
+ import { readerVersion } from "./declaration.js";
20
+ export const CHANGE_SET_SHOW_CONTRACT_VERSION = 1;
21
+ export const CHANGE_SET_SHOW_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/change-set-show/v1/change-set-show.schema.json";
22
+ /** Why the read stopped. Closed; each code is in `reason-codes.ts`. */
23
+ export const CHANGE_SET_SHOW_ERROR_CODES = ["not-a-git-repository", "ledger-unreadable"];
24
+ /** Why a stored file was not shown. */
25
+ export const CHANGE_SET_SHOW_REASON_CODES = ["ledger-malformed"];
26
+ /** What a change-set digest looks like: a plan digest's form. */
27
+ export const CHANGE_SET_DIGEST_PATTERN = /^(?:jcs1-)?sha256:[0-9a-f]{64}$/;
28
+ /**
29
+ * Read the change set stored under `digest` in the ledger of the member at
30
+ * `cwd`, or of `member` (its path of names, outermost first) when given.
31
+ */
32
+ export async function changeSetShowDocument(req) {
33
+ const head = { $schema: CHANGE_SET_SHOW_SCHEMA_ID, contract: CHANGE_SET_SHOW_CONTRACT_VERSION, chant: readerVersion() };
34
+ try {
35
+ execFileSync("git", ["rev-parse", "--git-dir"], { cwd: req.cwd, stdio: "ignore" });
36
+ }
37
+ catch {
38
+ return { ...head, error: { code: "not-a-git-repository", message: "change sets are read from the chant/lifecycle branch, and this directory is not in a git repository" } };
39
+ }
40
+ try {
41
+ const members = req.member ? [...req.member] : (await resolveMemberLedger(req.cwd)).members;
42
+ const read = await readStoredChangeSet(req.digest, { cwd: req.cwd, member: members });
43
+ return {
44
+ ...head,
45
+ member: members.length > 0 ? members.join("/") : null,
46
+ digest: req.digest,
47
+ changeSet: read.status === "found" ? read.document : null,
48
+ reason: read.status === "malformed" ? { code: "ledger-malformed", message: read.message } : null,
49
+ };
50
+ }
51
+ catch (err) {
52
+ return { ...head, error: { code: "ledger-unreadable", message: `reading the change set failed: ${err instanceof Error ? err.message : String(err)}` } };
53
+ }
54
+ }
@@ -0,0 +1,102 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://intentius.io/chant/schemas/workspace/change-set-show/v1/change-set-show.schema.json",
4
+ "title": "chant change-set show output",
5
+ "description": "What `chant change-set show <digest> --json` prints (#4022): the change-set document a gate bound, stored on chant/lifecycle under its digest (_change-sets/<digest>.json, under _members/<member>/ for a workspace member). A pull-request gate's apply stores it, and chant components promote --release stores a release gate's (#4045), which names the release and environment it was planned for. Each entry carries the graph node it changes. It reads the local chant/lifecycle branch and never fetches. Version 1 of the read contract. Readers ignore fields they do not know; a field is only ever added within a version. The codes are a closed list, each in the one closed list of `reason-codes.ts`. Contract version 1 of this document is written by chant 0.124.28 and newer; the read contract as a whole by chant 0.81.0 and newer.",
6
+ "oneOf": [{ "$ref": "#/$defs/result" }, { "$ref": "#/$defs/failure" }],
7
+ "$defs": {
8
+ "result": {
9
+ "type": "object",
10
+ "description": "The ledger was read. Exit code 0 when a change set is shown, 1 when changeSet is null.",
11
+ "required": ["$schema", "contract", "chant", "member", "digest", "changeSet", "reason"],
12
+ "properties": {
13
+ "$schema": { "const": "https://intentius.io/chant/schemas/workspace/change-set-show/v1/change-set-show.schema.json" },
14
+ "contract": { "const": 1 },
15
+ "chant": { "type": "string" },
16
+ "error": false,
17
+ "member": {
18
+ "type": ["string", "null"],
19
+ "description": "The member whose ledger was read, its path of names joined with / when nested, or null for a project outside a workspace."
20
+ },
21
+ "digest": {
22
+ "type": "string",
23
+ "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$",
24
+ "description": "The digest asked for: a gate's planDigest."
25
+ },
26
+ "changeSet": {
27
+ "description": "The stored change-set document (change-set.schema.json), whose digest equals digest. Each entry has node, the graph node it changes as chant workspace graph names it (<member>/<id> in a workspace), or null when the graph holds no node for its address. Its graph says which member's graph that was and the commit it was read at, or is null when no graph could be read. Null when nothing is stored under digest, as for a component gate, which binds a lifecycle-plan digest, and when reason is ledger-malformed.",
28
+ "oneOf": [
29
+ { "type": "null" },
30
+ {
31
+ "type": "object",
32
+ "required": ["$schema", "contract", "digest", "members", "entries", "summary"],
33
+ "properties": {
34
+ "$schema": { "const": "https://intentius.io/chant/schemas/workspace/change-set/v1/change-set.schema.json" },
35
+ "contract": { "const": 1 },
36
+ "digest": { "type": "string" },
37
+ "releaseDigest": { "type": "string", "description": "Added in contract 1 by #4045, written by chant 0.124.28 and newer: the release a release gate's change set was planned for. Absent on a pull request's." },
38
+ "environment": { "type": "string", "description": "Added in contract 1 by #4045, written by chant 0.124.28 and newer: the environment a release gate's change set was planned for. Absent on a pull request's." },
39
+ "members": { "type": "array" },
40
+ "entries": {
41
+ "type": "array",
42
+ "items": {
43
+ "type": "object",
44
+ "required": ["member", "address", "action", "node"],
45
+ "properties": {
46
+ "node": { "type": ["string", "null"] }
47
+ }
48
+ }
49
+ },
50
+ "graph": {
51
+ "oneOf": [
52
+ { "type": "null" },
53
+ {
54
+ "type": "object",
55
+ "required": ["member", "at"],
56
+ "properties": {
57
+ "member": { "type": ["string", "null"] },
58
+ "at": { "type": ["string", "null"] }
59
+ }
60
+ }
61
+ ]
62
+ }
63
+ }
64
+ }
65
+ ]
66
+ },
67
+ "reason": {
68
+ "description": "Null when the file was read, or when none is stored. ledger-malformed when a file is stored under digest and it is not a change-set document whose content hashes to digest.",
69
+ "oneOf": [
70
+ { "type": "null" },
71
+ {
72
+ "type": "object",
73
+ "required": ["code", "message"],
74
+ "properties": {
75
+ "code": { "enum": ["ledger-malformed"] },
76
+ "message": { "type": "string" }
77
+ }
78
+ }
79
+ ]
80
+ }
81
+ }
82
+ },
83
+ "failure": {
84
+ "type": "object",
85
+ "description": "Nothing was read. Exit code 1.",
86
+ "required": ["$schema", "contract", "chant", "error"],
87
+ "properties": {
88
+ "$schema": { "const": "https://intentius.io/chant/schemas/workspace/change-set-show/v1/change-set-show.schema.json" },
89
+ "contract": { "const": 1 },
90
+ "chant": { "type": "string" },
91
+ "error": {
92
+ "type": "object",
93
+ "required": ["code", "message"],
94
+ "properties": {
95
+ "code": { "enum": ["not-a-git-repository", "ledger-unreadable"] },
96
+ "message": { "type": "string" }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
@@ -26,7 +26,16 @@
26
26
  "digest": {
27
27
  "type": "string",
28
28
  "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$",
29
- "description": "computePlanDigest(\"change-set-document\", \u2026) over the set digest (computePlanDigest(\"change-set\", \u2026) over the members' { member, planDigest } pairs sorted by member), each member's member, status and holes, the entries and the side effects, provisional members and their entries left out. What a gate over the whole run binds."
29
+ "description": "computePlanDigest(\"change-set-document\", \u2026) over the set digest (computePlanDigest(\"change-set\", \u2026) over the members' { member, planDigest } pairs sorted by member), each member's member, status and holes, the entries without their node, the side effects, and on a release gate's document its releaseDigest and environment, provisional members and their entries left out. What a gate over the whole run binds."
30
+ },
31
+ "releaseDigest": {
32
+ "type": "string",
33
+ "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$",
34
+ "description": "Added in contract 1 by #4045, written by chant 0.124.28 and newer. The release a release gate's change set was planned for: the releaseDigest of the release chant components promote --release deploys. Set with environment, and absent on every other change set. Part of digest, so a stored change set names the one release its gate bound."
35
+ },
36
+ "environment": {
37
+ "type": "string",
38
+ "description": "Added in contract 1 by #4045, written by chant 0.124.28 and newer. The environment a release gate's change set was planned for, set with releaseDigest. Part of digest."
30
39
  },
31
40
  "members": {
32
41
  "type": "array",
@@ -59,6 +68,20 @@
59
68
  },
60
69
  "summary": {
61
70
  "$ref": "#/$defs/summary"
71
+ },
72
+ "graph": {
73
+ "description": "Added in contract 1 by #4022, written by chant 0.124.28 and newer on a stored change set. The graph the entries' node ids come from: the workspace member whose graph it is (null outside a workspace) and the commit it was read at (null when unknown). Null when no graph could be read, so every node is null. Absent on a document never mapped. Not part of digest.",
74
+ "oneOf": [
75
+ { "type": "null" },
76
+ {
77
+ "type": "object",
78
+ "required": ["member", "at"],
79
+ "properties": {
80
+ "member": { "type": ["string", "null"] },
81
+ "at": { "type": ["string", "null"] }
82
+ }
83
+ }
84
+ ]
62
85
  }
63
86
  },
64
87
  "$defs": {
@@ -244,6 +267,10 @@
244
267
  "items": {
245
268
  "$ref": "#/$defs/attribute"
246
269
  }
270
+ },
271
+ "node": {
272
+ "type": ["string", "null"],
273
+ "description": "Added in contract 1 by #4022, written by chant 0.124.28 and newer on a stored change set (chant change-set show). The graph node the entry changes, as chant graph --format ir names it, with the member in front (<member>/<id>) inside a workspace, as chant workspace graph names it. A chant entry's node is its address; a terraform-family entry's is <root>/<block key>, where the block key is each module call as module.<name>/ and then the block's address with no index. Null when the graph holds no node for the address, such as a delete of a block the source no longer declares. Absent on a document never mapped onto a graph. Not part of digest."
247
274
  }
248
275
  }
249
276
  },
@@ -1 +1 @@
1
- {"version":3,"file":"changes-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/changes-cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAKlF,KAAK,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAE3D,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAwBjD;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB3F"}
1
+ {"version":3,"file":"changes-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/changes-cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAKlF,KAAK,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAE3D,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiCjD;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB3F"}
@@ -25,6 +25,15 @@ export function formatChanges(doc) {
25
25
  }
26
26
  for (const f of doc.findings)
27
27
  out.push(`${f.severity === "fail" ? "error " : "warning"} ${f.code}: ${f.message}`);
28
+ if (doc.links) {
29
+ const l = doc.links;
30
+ const n = (state) => l.commits.filter((c) => c.state === state).length;
31
+ out.push(`links ${l.commits.length} commits: ${n("linked")} name a work item, ${n("unlinked")} do not, ${n("wrong")} name one that is not there; work kinds: ${l.kinds.join(", ")}`);
32
+ for (const f of l.findings) {
33
+ out.push(`${f.severity === "fail" ? "error " : "warning"} ${f.code}: ${f.message}`);
34
+ out.push(` fix: ${f.fix}`);
35
+ }
36
+ }
28
37
  if (doc.scope) {
29
38
  const sc = doc.scope;
30
39
  out.push(`scope ${sc.commits.length} commits judged against the declaration at ${sc.base.slice(0, 8)}; restricted: ${sc.restricted.join(", ") || "none"}`);
@@ -32,7 +41,7 @@ export function formatChanges(doc) {
32
41
  out.push(`error ${f.code}: ${f.message}`);
33
42
  }
34
43
  const s = doc.summary;
35
- out.push(`${s.paths} changed paths: ${s.covered} covered, ${s.uncovered} uncovered, ${s.outOfScope} out of scope, ${s.ignored} ignored, ${s.records} records; ${doc.findings.length} findings`);
44
+ out.push(`${s.paths} changed paths: ${s.covered} covered, ${s.uncovered} uncovered, ${s.outOfScope} out of scope, ${s.ignored} ignored, ${s.records} records; ${doc.findings.length} findings${doc.links ? `, ${doc.links.findings.length} commit link findings` : ""}`);
36
45
  return out.join("\n");
37
46
  }
38
47
  export async function runWorkspaceChanges(ctx, cwd) {
@@ -36,6 +36,7 @@
36
36
  * network.
37
37
  */
38
38
  import { type ChangeSeverity } from "./declaration.js";
39
+ import { type CommitLink } from "./commit-links.js";
39
40
  import { type ScopeReport } from "./write-scope.js";
40
41
  /** The version of the `changes` document this chant writes. */
41
42
  export declare const CHANGES_CONTRACT_VERSION = 1;
@@ -44,6 +45,36 @@ export declare const CHANGES_OUTPUT_SCHEMA_ID = "https://intentius.io/chant/sche
44
45
  /** The finding codes. Closed: a reader may switch on them. */
45
46
  export declare const CHANGES_FINDING_CODES: readonly ["change-uncovered", "change-out-of-scope"];
46
47
  export type ChangesFindingCode = (typeof CHANGES_FINDING_CODES)[number];
48
+ /** The codes of a finding on a commit rather than a path (#4029). Closed. */
49
+ export declare const COMMIT_LINK_FINDING_CODES: readonly ["commit-unlinked", "commit-wrongly-linked"];
50
+ export type CommitLinkFindingCode = (typeof COMMIT_LINK_FINDING_CODES)[number];
51
+ /** One non-merge first-parent commit of the range, with whether it names a work item. */
52
+ export interface LinkCommit {
53
+ commit: string;
54
+ subject: string;
55
+ state: Exclude<CommitLink["state"], "merge">;
56
+ /** The work records its trailers name, as `<kind>:<id>`. */
57
+ ids: string[];
58
+ /** The trailers that do not link it, when `state` is `wrong`. */
59
+ problems: CommitLink["problems"];
60
+ }
61
+ export interface LinkFinding {
62
+ /** `finding:<code>:<commit>`. */
63
+ id: string;
64
+ code: CommitLinkFindingCode;
65
+ commit: string;
66
+ message: string;
67
+ /** What to change so the commit names its work item. */
68
+ fix: string;
69
+ severity: "warn" | "fail";
70
+ }
71
+ /** Whether the range's commits name their work items (#4029). */
72
+ export interface LinkReport {
73
+ /** The work kinds read, by name. */
74
+ kinds: string[];
75
+ commits: LinkCommit[];
76
+ findings: LinkFinding[];
77
+ }
47
78
  /** Why the check failed as a whole: the declaration's codes, the record kind's, or a `--work` item no record has. */
48
79
  export declare const CHANGES_ERROR_CODES: readonly ["declaration-missing", "declaration-ambiguous", "declaration-unparseable", "declaration-invalid", "placement-invalid", "reader-too-old", "root-chant-required", "not-a-git-repository", "revision-unknown", "kind-unreadable", "kind-invalid", "schema-unreadable", "schema-id-mismatch", "schema-invalid", "location-missing", "work-item-unknown"];
49
80
  export type ChangesErrorCode = (typeof CHANGES_ERROR_CODES)[number];
@@ -152,6 +183,12 @@ export type ChangesDocument = (Head & {
152
183
  * or null when that declaration restricts no one.
153
184
  */
154
185
  scope: ScopeReport | null;
186
+ /**
187
+ * Whether each trunk commit of the range names the work item it belongs
188
+ * to (#4029), or null when no work kind was read. Findings follow the
189
+ * severity, like `findings`.
190
+ */
191
+ links: LinkReport | null;
155
192
  /** False when severity is fail and there are findings, or when a commit writes outside its writer's scope. */
156
193
  ok: boolean;
157
194
  }) | (Head & {
@@ -1 +1 @@
1
- {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/workspace/changes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/workspace/changes.ts"],"names":[],"mappings":"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"}
@@ -41,8 +41,9 @@ import { relative, resolve, sep } from "node:path";
41
41
  import picomatch from "picomatch";
42
42
  import { declaredRecordKinds, readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError } from "./declaration.js";
43
43
  import { declaredKindFile } from "./declared-kinds.js";
44
+ import { COMMIT_UNLINKED_FIX, hasLeaseLedger, judgeCommits, mergeCommits } from "./commit-links.js";
44
45
  import { isGeneratedPath } from "./generated-files.js";
45
- import { parseRegion } from "./intent.js";
46
+ import { commitDetails, parseRegion } from "./intent.js";
46
47
  import { loadClassRegistry } from "./principal-classes.js";
47
48
  import { constraintCovers, isWorkspacePath, memberHolding } from "./record-assets.js";
48
49
  import { loadRecordKind, RecordReadError } from "./records.js";
@@ -62,6 +63,13 @@ export const CHANGES_FINDING_CODES = [
62
63
  /** A record in hand for the change lists a changed path in its out_of_scope. */
63
64
  "change-out-of-scope",
64
65
  ];
66
+ /** The codes of a finding on a commit rather than a path (#4029). Closed. */
67
+ export const COMMIT_LINK_FINDING_CODES = [
68
+ /** A trunk commit in the range names no work item: no Chant-Record of a work kind and no Chant-Lease. */
69
+ "commit-unlinked",
70
+ /** A trunk commit in the range names a work item that is not there: a record id no work kind has, a record of another kind, or a lease that resolves to nothing. */
71
+ "commit-wrongly-linked",
72
+ ];
65
73
  /** Why the check failed as a whole: the declaration's codes, the record kind's, or a `--work` item no record has. */
66
74
  export const CHANGES_ERROR_CODES = [
67
75
  ...WORKSPACE_ERROR_CODES,
@@ -345,6 +353,7 @@ async function run(query, head) {
345
353
  }
346
354
  const count = (s) => paths.filter((p) => p.status === s).length;
347
355
  const scope = await writeScopeAtBase(query, top, range, workspacePrefix);
356
+ const links = commitLinks(top, range, kinds, severity);
348
357
  return {
349
358
  ...head,
350
359
  workspace: { name: declaration.name, root: located.root },
@@ -357,9 +366,47 @@ async function run(query, head) {
357
366
  findings,
358
367
  summary: { paths: paths.length, covered: count("covered"), uncovered: count("uncovered"), outOfScope: count("out-of-scope"), ignored: count("ignored"), records: count("record") },
359
368
  scope,
360
- ok: !(severity === "fail" && findings.length > 0) && (scope === null || scope.findings.length === 0),
369
+ links,
370
+ ok: !(severity === "fail" && (findings.length > 0 || (links?.findings.length ?? 0) > 0)) && (scope === null || scope.findings.length === 0),
361
371
  };
362
372
  }
373
+ /**
374
+ * Whether each trunk commit of the range, first-parent and merges left out,
375
+ * names a work item (#4029). Records are read at the head, as the paths are.
376
+ * Null when no work kind was read.
377
+ */
378
+ function commitLinks(top, range, kinds, severity) {
379
+ const work = kinds.filter((k) => k.role === "work");
380
+ if (work.length === 0)
381
+ return null;
382
+ const index = {
383
+ kinds: new Map(work.map((k) => [k.loaded.kind.name, new Set(k.records.flatMap((r) => (r.id === null ? [] : [r.id])))])),
384
+ ledger: hasLeaseLedger(top),
385
+ };
386
+ const shas = git(top, ["rev-list", "--first-parent", "--reverse", `${range.base}..${range.head}`]).split("\n").filter(Boolean);
387
+ const judged = judgeCommits(top, shas, index, mergeCommits(top, shas));
388
+ const details = commitDetails(top, shas);
389
+ const commits = [];
390
+ const findings = [];
391
+ for (const sha of shas) {
392
+ const link = judged.get(sha);
393
+ if (link.state === "merge")
394
+ continue;
395
+ const subject = details.get(sha)?.subject ?? "";
396
+ commits.push({ commit: sha, subject, state: link.state, ids: link.ids, problems: link.problems });
397
+ if (link.state === "linked" || severity === "off")
398
+ continue;
399
+ const short = sha.slice(0, 8);
400
+ if (link.state === "unlinked") {
401
+ findings.push({ id: `finding:commit-unlinked:${sha}`, code: "commit-unlinked", commit: sha, severity, message: `${short} "${subject}" carries no Chant-Record trailer of a work kind and no Chant-Lease trailer, so it names no work item`, fix: COMMIT_UNLINKED_FIX });
402
+ }
403
+ else {
404
+ const named = link.problems.map((p) => `${p.trailer} (${p.message})`).join("; ");
405
+ findings.push({ id: `finding:commit-wrongly-linked:${sha}`, code: "commit-wrongly-linked", commit: sha, severity, message: `${short} "${subject}" names no work item that exists: ${named}`, fix: `correct the trailer to name an existing work record, \`Chant-Record: ${[...index.kinds.keys()][0]}:<id>\`, or a lease taken on one` });
406
+ }
407
+ }
408
+ return { kinds: [...index.kinds.keys()], commits, findings };
409
+ }
363
410
  /**
364
411
  * The write scope check over the range (#2548), with the declaration, its
365
412
  * record kinds and the trust policy read at the range's base, so a change