@intentius/chant 0.124.27 → 0.124.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (681) hide show
  1. package/README.md +1 -1
  2. package/dist/__golden__/wave-loop/fan-out-gated.json +8 -0
  3. package/dist/__golden__/wave-loop/fan-out-no-members.json +4 -0
  4. package/dist/__golden__/wave-loop/fan-out-only.json +6 -0
  5. package/dist/__golden__/wave-loop/op-by-apply-hold.json +2 -0
  6. package/dist/__golden__/wave-loop/op-cost-member.json +3 -0
  7. package/dist/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
  8. package/dist/__golden__/wave-loop/op-held-on.json +2 -0
  9. package/dist/__golden__/wave-loop/op-hooks-held.json +2 -0
  10. package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
  11. package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
  12. package/dist/__golden__/wave-loop/op-hooks-share.json +3 -0
  13. package/dist/__golden__/wave-loop/op-per-run.json +7 -0
  14. package/dist/__golden__/wave-loop/op-pr-review.json +7 -0
  15. package/dist/__golden__/wave-loop/op-sealed.json +3 -0
  16. package/dist/__golden__/wave-loop/op-spend.json +3 -0
  17. package/dist/__golden__/wave-loop/op-wave-commands.json +7 -0
  18. package/dist/__golden__/wave-loop/op-wide-waiting.json +4 -0
  19. package/dist/build-params.d.ts +34 -1
  20. package/dist/build-params.d.ts.map +1 -1
  21. package/dist/build-params.js +31 -1
  22. package/dist/change-set-graph.d.ts +63 -0
  23. package/dist/change-set-graph.d.ts.map +1 -0
  24. package/dist/change-set-graph.js +130 -0
  25. package/dist/change-set.d.ts +62 -3
  26. package/dist/change-set.d.ts.map +1 -1
  27. package/dist/change-set.js +36 -4
  28. package/dist/chant-version.d.ts +9 -0
  29. package/dist/chant-version.d.ts.map +1 -0
  30. package/dist/chant-version.js +16 -0
  31. package/dist/cli/build-params-cli.d.ts +7 -1
  32. package/dist/cli/build-params-cli.d.ts.map +1 -1
  33. package/dist/cli/build-params-cli.js +17 -8
  34. package/dist/cli/commands/build.d.ts +8 -0
  35. package/dist/cli/commands/build.d.ts.map +1 -1
  36. package/dist/cli/commands/build.js +15 -11
  37. package/dist/cli/commands/check-lexicon-docs.d.ts.map +1 -1
  38. package/dist/cli/commands/check-lexicon-docs.js +30 -2
  39. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  40. package/dist/cli/commands/check-lexicon.js +13 -2
  41. package/dist/cli/commands/init-lexicon/templates/docs.d.ts +4 -1
  42. package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -1
  43. package/dist/cli/commands/init-lexicon/templates/docs.js +6 -6
  44. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  45. package/dist/cli/commands/init-lexicon.js +17 -8
  46. package/dist/cli/handlers/approve.d.ts.map +1 -1
  47. package/dist/cli/handlers/approve.js +64 -4
  48. package/dist/cli/handlers/build.d.ts.map +1 -1
  49. package/dist/cli/handlers/build.js +43 -4
  50. package/dist/cli/handlers/change-set.d.ts +10 -0
  51. package/dist/cli/handlers/change-set.d.ts.map +1 -1
  52. package/dist/cli/handlers/change-set.js +51 -1
  53. package/dist/cli/handlers/fan-out.d.ts +10 -1
  54. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  55. package/dist/cli/handlers/fan-out.js +54 -6
  56. package/dist/cli/handlers/lifecycle-gc.d.ts +19 -0
  57. package/dist/cli/handlers/lifecycle-gc.d.ts.map +1 -0
  58. package/dist/cli/handlers/lifecycle-gc.js +143 -0
  59. package/dist/cli/handlers/pr.d.ts +16 -2
  60. package/dist/cli/handlers/pr.d.ts.map +1 -1
  61. package/dist/cli/handlers/pr.js +269 -37
  62. package/dist/cli/handlers/promote.d.ts +7 -0
  63. package/dist/cli/handlers/promote.d.ts.map +1 -1
  64. package/dist/cli/handlers/promote.js +440 -28
  65. package/dist/cli/handlers/release.d.ts +91 -0
  66. package/dist/cli/handlers/release.d.ts.map +1 -0
  67. package/dist/cli/handlers/release.js +589 -0
  68. package/dist/cli/handlers/run.d.ts +38 -2
  69. package/dist/cli/handlers/run.d.ts.map +1 -1
  70. package/dist/cli/handlers/run.js +234 -16
  71. package/dist/cli/main.d.ts.map +1 -1
  72. package/dist/cli/main.js +143 -17
  73. package/dist/cli/mcp/workspace-tools.js +1 -1
  74. package/dist/cli/parse-args.d.ts.map +1 -1
  75. package/dist/cli/parse-args.js +73 -5
  76. package/dist/cli/registry.d.ts +43 -5
  77. package/dist/cli/registry.d.ts.map +1 -1
  78. package/dist/cli/run-events.d.ts +30 -0
  79. package/dist/cli/run-events.d.ts.map +1 -0
  80. package/dist/cli/run-events.js +49 -0
  81. package/dist/cli/version.d.ts +3 -5
  82. package/dist/cli/version.d.ts.map +1 -1
  83. package/dist/cli/version.js +3 -13
  84. package/dist/codegen/docs-in-site.d.ts +71 -0
  85. package/dist/codegen/docs-in-site.d.ts.map +1 -0
  86. package/dist/codegen/docs-in-site.js +177 -0
  87. package/dist/codegen/docs-types.d.ts +14 -1
  88. package/dist/codegen/docs-types.d.ts.map +1 -1
  89. package/dist/codegen/docs.d.ts +18 -1
  90. package/dist/codegen/docs.d.ts.map +1 -1
  91. package/dist/codegen/docs.js +40 -7
  92. package/dist/codegen/rehype-base-url.mjs +15 -9
  93. package/dist/components/auto-release.d.ts +6 -1
  94. package/dist/components/auto-release.d.ts.map +1 -1
  95. package/dist/components/auto-release.js +3 -0
  96. package/dist/components/capability.d.ts +9 -0
  97. package/dist/components/capability.d.ts.map +1 -1
  98. package/dist/components/cli-support.d.ts +6 -0
  99. package/dist/components/cli-support.d.ts.map +1 -1
  100. package/dist/components/cli-support.js +10 -9
  101. package/dist/components/driver.d.ts +50 -9
  102. package/dist/components/driver.d.ts.map +1 -1
  103. package/dist/components/driver.js +116 -54
  104. package/dist/components/fan-out-inputs.d.ts +69 -0
  105. package/dist/components/fan-out-inputs.d.ts.map +1 -0
  106. package/dist/components/fan-out-inputs.js +169 -0
  107. package/dist/components/fan-out-record.d.ts +13 -0
  108. package/dist/components/fan-out-record.d.ts.map +1 -1
  109. package/dist/components/fan-out-record.js +16 -0
  110. package/dist/components/fan-out-run.d.ts +7 -0
  111. package/dist/components/fan-out-run.d.ts.map +1 -1
  112. package/dist/components/fan-out-run.js +85 -26
  113. package/dist/components/fan-out.d.ts +4 -0
  114. package/dist/components/fan-out.d.ts.map +1 -1
  115. package/dist/components/pr-pipeline.d.ts +25 -0
  116. package/dist/components/pr-pipeline.d.ts.map +1 -1
  117. package/dist/components/pr-pipeline.js +22 -4
  118. package/dist/components/pr-run.d.ts +11 -0
  119. package/dist/components/pr-run.d.ts.map +1 -1
  120. package/dist/components/pr-run.js +20 -1
  121. package/dist/components/promote-order.d.ts +38 -0
  122. package/dist/components/promote-order.d.ts.map +1 -0
  123. package/dist/components/promote-order.js +62 -0
  124. package/dist/components/promote.d.ts +38 -2
  125. package/dist/components/promote.d.ts.map +1 -1
  126. package/dist/components/promote.js +77 -2
  127. package/dist/components/release-compile.d.ts +142 -0
  128. package/dist/components/release-compile.d.ts.map +1 -0
  129. package/dist/components/release-compile.js +382 -0
  130. package/dist/components/release-gate.d.ts +135 -0
  131. package/dist/components/release-gate.d.ts.map +1 -0
  132. package/dist/components/release-gate.js +288 -0
  133. package/dist/components/release-promote.d.ts +96 -0
  134. package/dist/components/release-promote.d.ts.map +1 -0
  135. package/dist/components/release-promote.js +204 -0
  136. package/dist/components/run-progress.d.ts +7 -0
  137. package/dist/components/run-progress.d.ts.map +1 -1
  138. package/dist/components/wave-plan.d.ts +8 -1
  139. package/dist/components/wave-plan.d.ts.map +1 -1
  140. package/dist/components/wave-plan.js +11 -3
  141. package/dist/config.d.ts +45 -0
  142. package/dist/config.d.ts.map +1 -1
  143. package/dist/config.js +3 -0
  144. package/dist/flag-params.d.ts +54 -0
  145. package/dist/flag-params.d.ts.map +1 -0
  146. package/dist/flag-params.js +130 -0
  147. package/dist/index.d.ts +1 -0
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +2 -0
  150. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts +120 -0
  151. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -0
  152. package/dist/lifecycle/__fixtures__/publish-fakes.js +304 -0
  153. package/dist/lifecycle/change-set-store.d.ts +68 -0
  154. package/dist/lifecycle/change-set-store.d.ts.map +1 -0
  155. package/dist/lifecycle/change-set-store.js +97 -0
  156. package/dist/lifecycle/commit-sha.d.ts +13 -0
  157. package/dist/lifecycle/commit-sha.d.ts.map +1 -0
  158. package/dist/lifecycle/commit-sha.js +21 -0
  159. package/dist/lifecycle/delivery-metrics.d.ts +139 -0
  160. package/dist/lifecycle/delivery-metrics.d.ts.map +1 -0
  161. package/dist/lifecycle/delivery-metrics.js +145 -0
  162. package/dist/lifecycle/deploy-outcome.d.ts +81 -0
  163. package/dist/lifecycle/deploy-outcome.d.ts.map +1 -0
  164. package/dist/lifecycle/deploy-outcome.js +101 -0
  165. package/dist/lifecycle/gate-change-set.d.ts +78 -0
  166. package/dist/lifecycle/gate-change-set.d.ts.map +1 -0
  167. package/dist/lifecycle/gate-change-set.js +138 -0
  168. package/dist/lifecycle/gate-ledger.d.ts +51 -4
  169. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  170. package/dist/lifecycle/gate-ledger.js +18 -0
  171. package/dist/lifecycle/git.d.ts +30 -1
  172. package/dist/lifecycle/git.d.ts.map +1 -1
  173. package/dist/lifecycle/git.js +31 -5
  174. package/dist/lifecycle/index.d.ts +4 -0
  175. package/dist/lifecycle/index.d.ts.map +1 -1
  176. package/dist/lifecycle/index.js +4 -0
  177. package/dist/lifecycle/mixed-environment.d.ts +95 -0
  178. package/dist/lifecycle/mixed-environment.d.ts.map +1 -0
  179. package/dist/lifecycle/mixed-environment.js +154 -0
  180. package/dist/lifecycle/publish-attachments.d.ts +79 -0
  181. package/dist/lifecycle/publish-attachments.d.ts.map +1 -0
  182. package/dist/lifecycle/publish-attachments.js +179 -0
  183. package/dist/lifecycle/publish-credentials.d.ts +37 -0
  184. package/dist/lifecycle/publish-credentials.d.ts.map +1 -0
  185. package/dist/lifecycle/publish-credentials.js +69 -0
  186. package/dist/lifecycle/publish-declaration.d.ts +97 -0
  187. package/dist/lifecycle/publish-declaration.d.ts.map +1 -0
  188. package/dist/lifecycle/publish-declaration.js +83 -0
  189. package/dist/lifecycle/publish-forge.d.ts +53 -0
  190. package/dist/lifecycle/publish-forge.d.ts.map +1 -0
  191. package/dist/lifecycle/publish-forge.js +298 -0
  192. package/dist/lifecycle/publish-npm.d.ts +61 -0
  193. package/dist/lifecycle/publish-npm.d.ts.map +1 -0
  194. package/dist/lifecycle/publish-npm.js +242 -0
  195. package/dist/lifecycle/publish-oci.d.ts +64 -0
  196. package/dist/lifecycle/publish-oci.d.ts.map +1 -0
  197. package/dist/lifecycle/publish-oci.js +383 -0
  198. package/dist/lifecycle/publish-record.d.ts +66 -0
  199. package/dist/lifecycle/publish-record.d.ts.map +1 -0
  200. package/dist/lifecycle/publish-record.js +84 -0
  201. package/dist/lifecycle/publish-targets.d.ts +45 -0
  202. package/dist/lifecycle/publish-targets.d.ts.map +1 -0
  203. package/dist/lifecycle/publish-targets.js +85 -0
  204. package/dist/lifecycle/release-cut.d.ts +154 -0
  205. package/dist/lifecycle/release-cut.d.ts.map +1 -0
  206. package/dist/lifecycle/release-cut.js +366 -0
  207. package/dist/lifecycle/release-join.d.ts +95 -0
  208. package/dist/lifecycle/release-join.d.ts.map +1 -0
  209. package/dist/lifecycle/release-join.js +139 -0
  210. package/dist/lifecycle/release-ledger.d.ts +54 -0
  211. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  212. package/dist/lifecycle/release-ledger.js +53 -20
  213. package/dist/lifecycle/release-publish.d.ts +312 -0
  214. package/dist/lifecycle/release-publish.d.ts.map +1 -0
  215. package/dist/lifecycle/release-publish.js +335 -0
  216. package/dist/lifecycle/release-revocation.d.ts +80 -0
  217. package/dist/lifecycle/release-revocation.d.ts.map +1 -0
  218. package/dist/lifecycle/release-revocation.js +123 -0
  219. package/dist/lifecycle/release-store.d.ts +200 -0
  220. package/dist/lifecycle/release-store.d.ts.map +1 -0
  221. package/dist/lifecycle/release-store.js +320 -0
  222. package/dist/lifecycle/release-verify.d.ts +61 -0
  223. package/dist/lifecycle/release-verify.d.ts.map +1 -0
  224. package/dist/lifecycle/release-verify.js +92 -0
  225. package/dist/lifecycle/release-workstation.d.ts +91 -0
  226. package/dist/lifecycle/release-workstation.d.ts.map +1 -0
  227. package/dist/lifecycle/release-workstation.js +180 -0
  228. package/dist/lifecycle/retention-policy.d.ts +45 -0
  229. package/dist/lifecycle/retention-policy.d.ts.map +1 -0
  230. package/dist/lifecycle/retention-policy.js +43 -0
  231. package/dist/lifecycle/retention.d.ts +185 -0
  232. package/dist/lifecycle/retention.d.ts.map +1 -0
  233. package/dist/lifecycle/retention.js +400 -0
  234. package/dist/lifecycle/run-ledger.d.ts +4 -0
  235. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  236. package/dist/lifecycle/run-ledger.js +2 -0
  237. package/dist/op/activities/change-coverage.d.ts.map +1 -1
  238. package/dist/op/activities/change-coverage.js +4 -2
  239. package/dist/op/activities/source-release.d.ts.map +1 -1
  240. package/dist/op/activities/source-release.js +7 -3
  241. package/dist/op/activities/source-rollback.d.ts.map +1 -1
  242. package/dist/op/activities/source-rollback.js +7 -3
  243. package/dist/op/gate-name.d.ts +11 -2
  244. package/dist/op/gate-name.d.ts.map +1 -1
  245. package/dist/op/gate-name.js +12 -3
  246. package/dist/op/gate-run-locator.d.ts +22 -0
  247. package/dist/op/gate-run-locator.d.ts.map +1 -1
  248. package/dist/op/gate-run-locator.js +31 -0
  249. package/dist/op/gate.d.ts +27 -3
  250. package/dist/op/gate.d.ts.map +1 -1
  251. package/dist/op/gate.js +57 -3
  252. package/dist/op/local-executor.d.ts +36 -1
  253. package/dist/op/local-executor.d.ts.map +1 -1
  254. package/dist/op/local-executor.js +158 -52
  255. package/dist/op/op-waves-run.d.ts.map +1 -1
  256. package/dist/op/op-waves-run.js +4 -0
  257. package/dist/op/run-live.d.ts +2 -0
  258. package/dist/op/run-live.d.ts.map +1 -1
  259. package/dist/op/run-live.js +1 -1
  260. package/dist/op/runtime.d.ts +46 -0
  261. package/dist/op/runtime.d.ts.map +1 -1
  262. package/dist/op/runtimes/local.d.ts.map +1 -1
  263. package/dist/op/runtimes/local.js +8 -0
  264. package/dist/plan-summary.d.ts.map +1 -1
  265. package/dist/plan-summary.js +8 -2
  266. package/dist/point-decision.d.ts +2 -0
  267. package/dist/point-decision.d.ts.map +1 -1
  268. package/dist/point-decision.js +9 -2
  269. package/dist/pr-loop.d.ts +7 -0
  270. package/dist/pr-loop.d.ts.map +1 -1
  271. package/dist/pr-loop.js +23 -4
  272. package/dist/pr-report-url.d.ts +82 -0
  273. package/dist/pr-report-url.d.ts.map +1 -0
  274. package/dist/pr-report-url.js +174 -0
  275. package/dist/provenance.d.ts +2 -2
  276. package/dist/provenance.d.ts.map +1 -1
  277. package/dist/run-event-store.d.ts +104 -0
  278. package/dist/run-event-store.d.ts.map +1 -0
  279. package/dist/run-event-store.js +251 -0
  280. package/dist/run-event-stream.d.ts +133 -0
  281. package/dist/run-event-stream.d.ts.map +1 -0
  282. package/dist/run-event-stream.js +242 -0
  283. package/dist/run-event.d.ts +285 -0
  284. package/dist/run-event.d.ts.map +1 -0
  285. package/dist/run-event.js +209 -0
  286. package/dist/wave-runtime.mjs +262 -226
  287. package/dist/workspace/__fixtures__/flag-workspace.d.ts +31 -0
  288. package/dist/workspace/__fixtures__/flag-workspace.d.ts.map +1 -0
  289. package/dist/workspace/__fixtures__/flag-workspace.js +114 -0
  290. package/dist/workspace/__fixtures__/run-event-check.d.ts +19 -0
  291. package/dist/workspace/__fixtures__/run-event-check.d.ts.map +1 -0
  292. package/dist/workspace/__fixtures__/run-event-check.js +59 -0
  293. package/dist/workspace/change-set-show.d.ts +56 -0
  294. package/dist/workspace/change-set-show.d.ts.map +1 -0
  295. package/dist/workspace/change-set-show.js +54 -0
  296. package/dist/workspace/change-set-show.schema.json +102 -0
  297. package/dist/workspace/change-set.schema.json +32 -1
  298. package/dist/workspace/changes-cli.d.ts.map +1 -1
  299. package/dist/workspace/changes-cli.js +10 -1
  300. package/dist/workspace/changes.d.ts +37 -0
  301. package/dist/workspace/changes.d.ts.map +1 -1
  302. package/dist/workspace/changes.js +49 -2
  303. package/dist/workspace/changes.schema.json +135 -0
  304. package/dist/workspace/check.schema.json +4 -2
  305. package/dist/workspace/checks/records.d.ts +9 -1
  306. package/dist/workspace/checks/records.d.ts.map +1 -1
  307. package/dist/workspace/checks/records.js +35 -1
  308. package/dist/workspace/checks.d.ts +1 -0
  309. package/dist/workspace/checks.d.ts.map +1 -1
  310. package/dist/workspace/checks.js +2 -1
  311. package/dist/workspace/ci-green-cli.d.ts +19 -4
  312. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  313. package/dist/workspace/ci-green-cli.js +75 -12
  314. package/dist/workspace/ci-green-forge.d.ts +20 -3
  315. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  316. package/dist/workspace/ci-green-forge.js +6 -4
  317. package/dist/workspace/ci-green-workflow.d.ts +11 -0
  318. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  319. package/dist/workspace/ci-green-workflow.js +6 -0
  320. package/dist/workspace/ci-green.d.ts +281 -13
  321. package/dist/workspace/ci-green.d.ts.map +1 -1
  322. package/dist/workspace/ci-green.js +456 -38
  323. package/dist/workspace/ci-last-green.schema.json +32 -2
  324. package/dist/workspace/ci-list.schema.json +525 -0
  325. package/dist/workspace/commit-links.d.ts +85 -0
  326. package/dist/workspace/commit-links.d.ts.map +1 -0
  327. package/dist/workspace/commit-links.js +163 -0
  328. package/dist/workspace/declaration.d.ts +35 -0
  329. package/dist/workspace/declaration.d.ts.map +1 -1
  330. package/dist/workspace/declaration.js +27 -1
  331. package/dist/workspace/declaration.schema.json +76 -0
  332. package/dist/workspace/declared-kinds.d.ts +16 -0
  333. package/dist/workspace/declared-kinds.d.ts.map +1 -1
  334. package/dist/workspace/declared-kinds.js +25 -0
  335. package/dist/workspace/delivery-metrics.d.ts +91 -0
  336. package/dist/workspace/delivery-metrics.d.ts.map +1 -0
  337. package/dist/workspace/delivery-metrics.js +217 -0
  338. package/dist/workspace/delivery-metrics.schema.json +519 -0
  339. package/dist/workspace/flags-read.d.ts +37 -0
  340. package/dist/workspace/flags-read.d.ts.map +1 -0
  341. package/dist/workspace/flags-read.js +103 -0
  342. package/dist/workspace/flags.d.ts +100 -0
  343. package/dist/workspace/flags.d.ts.map +1 -0
  344. package/dist/workspace/flags.js +98 -0
  345. package/dist/workspace/graph-cli.js +1 -1
  346. package/dist/workspace/identity-gate-rule.d.ts +37 -0
  347. package/dist/workspace/identity-gate-rule.d.ts.map +1 -1
  348. package/dist/workspace/identity-gate-rule.js +72 -7
  349. package/dist/workspace/identity.d.ts +12 -0
  350. package/dist/workspace/identity.d.ts.map +1 -1
  351. package/dist/workspace/identity.js +13 -1
  352. package/dist/workspace/intent-cli.d.ts +11 -2
  353. package/dist/workspace/intent-cli.d.ts.map +1 -1
  354. package/dist/workspace/intent-cli.js +54 -5
  355. package/dist/workspace/intent-trace.d.ts +219 -0
  356. package/dist/workspace/intent-trace.d.ts.map +1 -0
  357. package/dist/workspace/intent-trace.js +314 -0
  358. package/dist/workspace/intent.d.ts +36 -7
  359. package/dist/workspace/intent.d.ts.map +1 -1
  360. package/dist/workspace/intent.js +192 -22
  361. package/dist/workspace/intent.schema.json +702 -6
  362. package/dist/workspace/ls.d.ts +4 -0
  363. package/dist/workspace/ls.d.ts.map +1 -1
  364. package/dist/workspace/ls.js +2 -0
  365. package/dist/workspace/ls.schema.json +3 -1
  366. package/dist/workspace/member-pipeline.d.ts +6 -0
  367. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  368. package/dist/workspace/member-pipeline.js +6 -0
  369. package/dist/workspace/overlap.d.ts +146 -0
  370. package/dist/workspace/overlap.d.ts.map +1 -0
  371. package/dist/workspace/overlap.js +276 -0
  372. package/dist/workspace/promotion-order.d.ts +41 -0
  373. package/dist/workspace/promotion-order.d.ts.map +1 -0
  374. package/dist/workspace/promotion-order.js +95 -0
  375. package/dist/workspace/reason-codes.d.ts +4 -0
  376. package/dist/workspace/reason-codes.d.ts.map +1 -1
  377. package/dist/workspace/reason-codes.js +7 -1
  378. package/dist/workspace/records.d.ts +15 -2
  379. package/dist/workspace/records.d.ts.map +1 -1
  380. package/dist/workspace/records.js +32 -0
  381. package/dist/workspace/records.schema.json +21 -2
  382. package/dist/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  383. package/dist/workspace/reference-kinds/flag/flag.schema.json +53 -0
  384. package/dist/workspace/releases.d.ts +81 -0
  385. package/dist/workspace/releases.d.ts.map +1 -0
  386. package/dist/workspace/releases.js +103 -0
  387. package/dist/workspace/releases.schema.json +513 -0
  388. package/dist/workspace/run-event.schema.json +295 -0
  389. package/dist/workspace/status-gates.d.ts +34 -1
  390. package/dist/workspace/status-gates.d.ts.map +1 -1
  391. package/dist/workspace/status-gates.js +31 -2
  392. package/dist/workspace/status-stewards.d.ts +4 -0
  393. package/dist/workspace/status-stewards.d.ts.map +1 -1
  394. package/dist/workspace/status-stewards.js +2 -0
  395. package/dist/workspace/status.d.ts +117 -0
  396. package/dist/workspace/status.d.ts.map +1 -1
  397. package/dist/workspace/status.js +218 -4
  398. package/dist/workspace/status.schema.json +268 -2
  399. package/dist/workspace/trust/ci-tag-statement.d.ts +102 -0
  400. package/dist/workspace/trust/ci-tag-statement.d.ts.map +1 -0
  401. package/dist/workspace/trust/ci-tag-statement.js +123 -0
  402. package/dist/workspace/trust/op-run-statement.d.ts +91 -0
  403. package/dist/workspace/trust/op-run-statement.d.ts.map +1 -0
  404. package/dist/workspace/trust/op-run-statement.js +143 -0
  405. package/dist/workspace/trust/rotation.d.ts +18 -2
  406. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  407. package/dist/workspace/trust/rotation.js +65 -16
  408. package/dist/workspace/trust/seal.d.ts +11 -0
  409. package/dist/workspace/trust/seal.d.ts.map +1 -1
  410. package/dist/workspace/trust/seal.js +9 -0
  411. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
  412. package/dist/workspace/trust/ssh-commit.js +10 -10
  413. package/dist/workspace/wip.d.ts.map +1 -1
  414. package/dist/workspace/wip.js +11 -3
  415. package/package.json +1 -1
  416. package/src/__golden__/wave-loop/fan-out-gated.json +8 -0
  417. package/src/__golden__/wave-loop/fan-out-no-members.json +4 -0
  418. package/src/__golden__/wave-loop/fan-out-only.json +6 -0
  419. package/src/__golden__/wave-loop/op-by-apply-hold.json +2 -0
  420. package/src/__golden__/wave-loop/op-cost-member.json +3 -0
  421. package/src/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
  422. package/src/__golden__/wave-loop/op-held-on.json +2 -0
  423. package/src/__golden__/wave-loop/op-hooks-held.json +2 -0
  424. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
  425. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
  426. package/src/__golden__/wave-loop/op-hooks-share.json +3 -0
  427. package/src/__golden__/wave-loop/op-per-run.json +7 -0
  428. package/src/__golden__/wave-loop/op-pr-review.json +7 -0
  429. package/src/__golden__/wave-loop/op-sealed.json +3 -0
  430. package/src/__golden__/wave-loop/op-spend.json +3 -0
  431. package/src/__golden__/wave-loop/op-wave-commands.json +7 -0
  432. package/src/__golden__/wave-loop/op-wide-waiting.json +4 -0
  433. package/src/build-params.test.ts +46 -0
  434. package/src/build-params.ts +55 -1
  435. package/src/change-set-graph.test.ts +72 -0
  436. package/src/change-set-graph.ts +141 -0
  437. package/src/change-set.ts +87 -6
  438. package/src/chant-version.ts +16 -0
  439. package/src/cli/build-params-cli.ts +22 -9
  440. package/src/cli/commands/build.ts +25 -11
  441. package/src/cli/commands/check-lexicon-docs.test.ts +51 -0
  442. package/src/cli/commands/check-lexicon-docs.ts +39 -2
  443. package/src/cli/commands/check-lexicon.ts +14 -2
  444. package/src/cli/commands/init-lexicon/templates/docs.ts +7 -6
  445. package/src/cli/commands/init-lexicon.test.ts +25 -0
  446. package/src/cli/commands/init-lexicon.ts +18 -8
  447. package/src/cli/handlers/approve-release.test.ts +84 -0
  448. package/src/cli/handlers/approve-revoked.test.ts +155 -0
  449. package/src/cli/handlers/approve.ts +65 -2
  450. package/src/cli/handlers/build.test.ts +67 -0
  451. package/src/cli/handlers/build.ts +46 -4
  452. package/src/cli/handlers/change-set.ts +49 -1
  453. package/src/cli/handlers/fan-out.test.ts +228 -1
  454. package/src/cli/handlers/fan-out.ts +53 -6
  455. package/src/cli/handlers/intent-trace.e2e.test.ts +201 -0
  456. package/src/cli/handlers/lifecycle-gc.test.ts +126 -0
  457. package/src/cli/handlers/lifecycle-gc.ts +146 -0
  458. package/src/cli/handlers/operator.test.ts +37 -0
  459. package/src/cli/handlers/pr.test.ts +341 -0
  460. package/src/cli/handlers/pr.ts +292 -47
  461. package/src/cli/handlers/promote.test.ts +669 -7
  462. package/src/cli/handlers/promote.ts +464 -29
  463. package/src/cli/handlers/release-implicit.e2e.test.ts +161 -0
  464. package/src/cli/handlers/release-join.e2e.test.ts +185 -0
  465. package/src/cli/handlers/release-publish-targets.e2e.test.ts +295 -0
  466. package/src/cli/handlers/release-verify.e2e.test.ts +117 -0
  467. package/src/cli/handlers/release-workstation-ci.e2e.test.ts +135 -0
  468. package/src/cli/handlers/release.e2e.test.ts +199 -0
  469. package/src/cli/handlers/release.ts +593 -0
  470. package/src/cli/handlers/run-auto-release.test.ts +80 -0
  471. package/src/cli/handlers/run-events-cmd.test.ts +92 -0
  472. package/src/cli/handlers/run-release.test.ts +55 -0
  473. package/src/cli/handlers/run.test.ts +30 -0
  474. package/src/cli/handlers/run.ts +243 -18
  475. package/src/cli/main.test.ts +8 -0
  476. package/src/cli/main.ts +143 -17
  477. package/src/cli/mcp/never-over-mcp.test.ts +2 -0
  478. package/src/cli/mcp/workspace-tools.ts +1 -1
  479. package/src/cli/parse-args.ts +56 -5
  480. package/src/cli/registry.ts +43 -5
  481. package/src/cli/run-events.ts +57 -0
  482. package/src/cli/version.ts +3 -13
  483. package/src/codegen/docs-in-site.test.ts +166 -0
  484. package/src/codegen/docs-in-site.ts +182 -0
  485. package/src/codegen/docs-site/AgentPrompt.astro +26 -1
  486. package/src/codegen/docs-types.ts +14 -1
  487. package/src/codegen/docs.ts +60 -7
  488. package/src/codegen/rehype-base-url.d.mts +3 -1
  489. package/src/codegen/rehype-base-url.mjs +15 -9
  490. package/src/codegen/rehype-base-url.test.ts +34 -0
  491. package/src/components/auto-release.test.ts +30 -0
  492. package/src/components/auto-release.ts +9 -1
  493. package/src/components/capability.ts +9 -0
  494. package/src/components/cli-support.test.ts +82 -0
  495. package/src/components/cli-support.ts +16 -9
  496. package/src/components/driver.test.ts +24 -0
  497. package/src/components/driver.ts +165 -56
  498. package/src/components/fan-out-inputs.test.ts +85 -0
  499. package/src/components/fan-out-inputs.ts +192 -0
  500. package/src/components/fan-out-record.test.ts +10 -0
  501. package/src/components/fan-out-record.ts +19 -0
  502. package/src/components/fan-out-run.ts +104 -35
  503. package/src/components/fan-out.ts +4 -0
  504. package/src/components/pr-pipeline.ts +35 -4
  505. package/src/components/pr-run.ts +30 -1
  506. package/src/components/promote-order.test.ts +90 -0
  507. package/src/components/promote-order.ts +75 -0
  508. package/src/components/promote.test.ts +10 -1
  509. package/src/components/promote.ts +94 -3
  510. package/src/components/release-compile.test.ts +147 -0
  511. package/src/components/release-compile.ts +459 -0
  512. package/src/components/release-gate.test.ts +215 -0
  513. package/src/components/release-gate.ts +355 -0
  514. package/src/components/release-promote.test.ts +159 -0
  515. package/src/components/release-promote.ts +232 -0
  516. package/src/components/run-progress.ts +7 -0
  517. package/src/components/wave-plan.ts +16 -3
  518. package/src/config.ts +15 -1
  519. package/src/flag-params.test.ts +144 -0
  520. package/src/flag-params.ts +134 -0
  521. package/src/index.ts +2 -0
  522. package/src/lifecycle/__fixtures__/publish-fakes.ts +351 -0
  523. package/src/lifecycle/change-set-store.test.ts +217 -0
  524. package/src/lifecycle/change-set-store.ts +113 -0
  525. package/src/lifecycle/commit-sha.ts +23 -0
  526. package/src/lifecycle/delivery-metrics.ts +263 -0
  527. package/src/lifecycle/deploy-outcome.ts +147 -0
  528. package/src/lifecycle/gate-change-set.e2e.test.ts +122 -0
  529. package/src/lifecycle/gate-change-set.ts +164 -0
  530. package/src/lifecycle/gate-ledger.test.ts +33 -0
  531. package/src/lifecycle/gate-ledger.ts +68 -3
  532. package/src/lifecycle/git.ts +61 -8
  533. package/src/lifecycle/index.ts +4 -0
  534. package/src/lifecycle/mixed-environment.test.ts +97 -0
  535. package/src/lifecycle/mixed-environment.ts +204 -0
  536. package/src/lifecycle/publish-attachments.ts +196 -0
  537. package/src/lifecycle/publish-credentials.ts +84 -0
  538. package/src/lifecycle/publish-declaration.ts +95 -0
  539. package/src/lifecycle/publish-forge.ts +325 -0
  540. package/src/lifecycle/publish-npm.ts +259 -0
  541. package/src/lifecycle/publish-oci.ts +396 -0
  542. package/src/lifecycle/publish-record.ts +113 -0
  543. package/src/lifecycle/publish-resume.test.ts +168 -0
  544. package/src/lifecycle/publish-targets.test.ts +494 -0
  545. package/src/lifecycle/publish-targets.ts +100 -0
  546. package/src/lifecycle/release-cut-signed.test.ts +180 -0
  547. package/src/lifecycle/release-cut.test.ts +483 -0
  548. package/src/lifecycle/release-cut.ts +503 -0
  549. package/src/lifecycle/release-flag.test.ts +112 -0
  550. package/src/lifecycle/release-join.test.ts +68 -0
  551. package/src/lifecycle/release-join.ts +182 -0
  552. package/src/lifecycle/release-ledger.test.ts +14 -0
  553. package/src/lifecycle/release-ledger.ts +85 -17
  554. package/src/lifecycle/release-publish.test.ts +225 -0
  555. package/src/lifecycle/release-publish.ts +568 -0
  556. package/src/lifecycle/release-revocation.ts +147 -0
  557. package/src/lifecycle/release-store.ts +434 -0
  558. package/src/lifecycle/release-verify.test.ts +110 -0
  559. package/src/lifecycle/release-verify.ts +120 -0
  560. package/src/lifecycle/release-workstation.test.ts +204 -0
  561. package/src/lifecycle/release-workstation.ts +216 -0
  562. package/src/lifecycle/retention-growth.e2e.test.ts +279 -0
  563. package/src/lifecycle/retention-policy.ts +63 -0
  564. package/src/lifecycle/retention.test.ts +363 -0
  565. package/src/lifecycle/retention.ts +508 -0
  566. package/src/lifecycle/run-ledger.test.ts +10 -0
  567. package/src/lifecycle/run-ledger.ts +6 -0
  568. package/src/op/activities/change-coverage.ts +4 -1
  569. package/src/op/activities/source-release.ts +8 -3
  570. package/src/op/activities/source-rollback.ts +8 -4
  571. package/src/op/commit-run-gate-deploy-join.test.ts +117 -0
  572. package/src/op/gate-name.ts +13 -3
  573. package/src/op/gate-release.test.ts +126 -0
  574. package/src/op/gate-run-locator.test.ts +110 -0
  575. package/src/op/gate-run-locator.ts +35 -0
  576. package/src/op/gate.ts +88 -6
  577. package/src/op/local-executor.ts +207 -52
  578. package/src/op/op-waves-run.ts +4 -0
  579. package/src/op/run-events.test.ts +166 -0
  580. package/src/op/run-live.ts +1 -1
  581. package/src/op/runtime.ts +39 -0
  582. package/src/op/runtimes/local.test.ts +16 -0
  583. package/src/op/runtimes/local.ts +9 -0
  584. package/src/plan-summary.test.ts +20 -0
  585. package/src/plan-summary.ts +8 -1
  586. package/src/point-decision.ts +12 -2
  587. package/src/pr-loop.ts +25 -4
  588. package/src/pr-report-url.test.ts +131 -0
  589. package/src/pr-report-url.ts +209 -0
  590. package/src/provenance.ts +2 -2
  591. package/src/run-event-store.test.ts +144 -0
  592. package/src/run-event-store.ts +273 -0
  593. package/src/run-event-stream.test.ts +175 -0
  594. package/src/run-event-stream.ts +309 -0
  595. package/src/run-event.test.ts +277 -0
  596. package/src/run-event.ts +471 -0
  597. package/src/wave-loop-golden.test.ts +9 -0
  598. package/src/workspace/__fixtures__/flag-workspace.ts +132 -0
  599. package/src/workspace/__fixtures__/older-records/change-set-984534ea9.json +100 -0
  600. package/src/workspace/__fixtures__/older-records/older-records.json +326 -0
  601. package/src/workspace/__fixtures__/run-event-check.ts +58 -0
  602. package/src/workspace/ancestry-index.test.ts +93 -0
  603. package/src/workspace/change-set-show.schema.json +102 -0
  604. package/src/workspace/change-set-show.ts +72 -0
  605. package/src/workspace/change-set.schema.json +32 -1
  606. package/src/workspace/changes-cli.ts +10 -1
  607. package/src/workspace/changes.schema.json +135 -0
  608. package/src/workspace/changes.test.ts +1 -1
  609. package/src/workspace/changes.ts +84 -2
  610. package/src/workspace/check.schema.json +4 -2
  611. package/src/workspace/checks/records.ts +35 -1
  612. package/src/workspace/checks.ts +2 -1
  613. package/src/workspace/ci-green-cli.ts +75 -13
  614. package/src/workspace/ci-green-forge.ts +24 -4
  615. package/src/workspace/ci-green-runs.test.ts +242 -0
  616. package/src/workspace/ci-green-signed.test.ts +302 -0
  617. package/src/workspace/ci-green-workflow.test.ts +16 -0
  618. package/src/workspace/ci-green-workflow.ts +12 -0
  619. package/src/workspace/ci-green.test.ts +131 -2
  620. package/src/workspace/ci-green.ts +635 -42
  621. package/src/workspace/ci-last-green.schema.json +32 -2
  622. package/src/workspace/ci-list.schema.json +525 -0
  623. package/src/workspace/commit-links.test.ts +279 -0
  624. package/src/workspace/commit-links.ts +183 -0
  625. package/src/workspace/declaration.schema.json +76 -0
  626. package/src/workspace/declaration.test.ts +28 -0
  627. package/src/workspace/declaration.ts +60 -2
  628. package/src/workspace/declared-kinds.ts +40 -1
  629. package/src/workspace/delivery-metrics.schema.json +519 -0
  630. package/src/workspace/delivery-metrics.test.ts +236 -0
  631. package/src/workspace/delivery-metrics.ts +286 -0
  632. package/src/workspace/flags-read.ts +121 -0
  633. package/src/workspace/flags.test.ts +141 -0
  634. package/src/workspace/flags.ts +157 -0
  635. package/src/workspace/graph-cli.ts +1 -1
  636. package/src/workspace/identity-gate-rule.ts +91 -7
  637. package/src/workspace/identity.ts +14 -1
  638. package/src/workspace/intent-cli.ts +46 -5
  639. package/src/workspace/intent-trace.test.ts +173 -0
  640. package/src/workspace/intent-trace.ts +484 -0
  641. package/src/workspace/intent.schema.json +702 -6
  642. package/src/workspace/intent.ts +196 -26
  643. package/src/workspace/ls.schema.json +3 -1
  644. package/src/workspace/ls.ts +6 -0
  645. package/src/workspace/member-pipeline.test.ts +17 -0
  646. package/src/workspace/member-pipeline.ts +9 -0
  647. package/src/workspace/older-records.test.ts +412 -0
  648. package/src/workspace/overlap.test.ts +165 -0
  649. package/src/workspace/overlap.ts +340 -0
  650. package/src/workspace/promotion-order.ts +97 -0
  651. package/src/workspace/read-contract.e2e.test.ts +5 -1
  652. package/src/workspace/reason-codes.test.ts +7 -1
  653. package/src/workspace/reason-codes.ts +7 -1
  654. package/src/workspace/record-assets.test.ts +2 -1
  655. package/src/workspace/records-contract.e2e.test.ts +2 -1
  656. package/src/workspace/records.schema.json +21 -2
  657. package/src/workspace/records.ts +36 -2
  658. package/src/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  659. package/src/workspace/reference-kinds/flag/flag.schema.json +53 -0
  660. package/src/workspace/releases.schema.json +513 -0
  661. package/src/workspace/releases.test.ts +108 -0
  662. package/src/workspace/releases.ts +133 -0
  663. package/src/workspace/run-event.schema.json +295 -0
  664. package/src/workspace/status-contract.test.ts +81 -1
  665. package/src/workspace/status-gates.ts +64 -1
  666. package/src/workspace/status-mixed.test.ts +152 -0
  667. package/src/workspace/status-revoked.test.ts +153 -0
  668. package/src/workspace/status-stewards.ts +6 -0
  669. package/src/workspace/status.schema.json +268 -2
  670. package/src/workspace/status.ts +334 -4
  671. package/src/workspace/trust/ci-tag-statement.ts +151 -0
  672. package/src/workspace/trust/op-run-statement.ts +148 -0
  673. package/src/workspace/trust/rotation.ts +61 -14
  674. package/src/workspace/trust/seal.ts +10 -0
  675. package/src/workspace/trust/ssh-commit.ts +10 -9
  676. package/src/workspace/wip.ts +11 -2
  677. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +0 -14
  678. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +0 -16
  679. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +0 -8
  680. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +0 -15
  681. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +0 -10
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Overlap between in-flight work items (#4025, policy from #4016).
3
+ *
4
+ * A work lease locks one item, and nothing compares two items with each
5
+ * other. This report does, after the fact: it says which in-flight work items
6
+ * changed the same files, and which entries of a planned change set more than
7
+ * one of them reaches. It never blocks anything. Two people or agents read it
8
+ * and sort the overlap out between them.
9
+ *
10
+ * ## In flight
11
+ *
12
+ * A work item is a current record of a declared work kind. It is in flight
13
+ * unless it implements at least one decision and every decision it implements
14
+ * is confirmed, as #4024 defines confirmed ({@link decisionConfirmed}: in one
15
+ * of the decision kind's closed states and superseded by nothing). The item's
16
+ * own state does not matter: work marked done whose decision is not settled
17
+ * can still collide.
18
+ *
19
+ * ## Linked commits
20
+ *
21
+ * The commits of a work item are the commits linked to it as #4029 defines
22
+ * linked ({@link judgeCommits}): a `Chant-Record: <work kind>:<id>` trailer,
23
+ * or a `Chant-Lease` trailer that resolves to the item. A window match does
24
+ * not link. The walk covers every local branch, every remote-tracking branch
25
+ * and HEAD, so work pushed to a branch and fetched shows before it is merged.
26
+ * The ledger branches under `chant/` hold no work and are left out. Merge
27
+ * commits carry no work of their own and are skipped. Nothing is fetched.
28
+ *
29
+ * ## Files
30
+ *
31
+ * An item's files are the paths its linked commits add, change or delete,
32
+ * from the repository root, with renames read as a delete and an add. Two
33
+ * items overlap by file when both touch one path.
34
+ *
35
+ * ## Change-set entries
36
+ *
37
+ * A change set is planned from many commits, and a release bundles many work
38
+ * items, so an entry belongs to no single item on its face. An entry is
39
+ * attributed to a work item when:
40
+ *
41
+ * 1. the entry has a `source`: the file that declares its graph node, from
42
+ * the repository root, recorded when the change set was stored
43
+ * (`../change-set-graph.ts`);
44
+ * 2. a commit linked to the item changed that file; and
45
+ * 3. that commit is in the history the change set was planned from: an
46
+ * ancestor of (or equal to) the commit its graph was read at, else the
47
+ * commit the gate was reached at. When neither is known, or the commit is
48
+ * not in this repository, the third test is skipped.
49
+ *
50
+ * An entry can be attributed to several items, and two items overlap by
51
+ * address when one entry is attributed to both. An entry with no `source`
52
+ * (stored by an older chant, mapped onto no node, or a node with no source
53
+ * location) is attributed to none and counted in `unattributed`.
54
+ *
55
+ * The change sets read are the ones `workspace status` lists on a gate that
56
+ * is pending or approved: the plans still waiting to apply.
57
+ */
58
+
59
+ import { execFileSync } from "node:child_process";
60
+ import { dirname } from "node:path";
61
+ import type { ChangeSetDocument } from "../change-set";
62
+ import { judgeCommits, hasLeaseLedger, type WorkIndex } from "./commit-links";
63
+ import { declaredRecordKinds, type Declaration } from "./declaration";
64
+ import { declaredKindFile } from "./declared-kinds";
65
+ import { decisionConfirmed } from "./flags";
66
+ import { loadRecordKind } from "./records";
67
+ import { readRecordsFor } from "./records-cli";
68
+ import { LEASE_TRAILER, RECORD_TRAILER } from "./trailers";
69
+
70
+ /** One in-flight work item with at least one linked commit. */
71
+ export interface OverlapItem {
72
+ /** `<work kind>:<id>`, as a `Chant-Record` trailer names it. */
73
+ item: string;
74
+ /** The work record file, from the repository root. */
75
+ path: string;
76
+ state: string | null;
77
+ /** The commits linked to the item, newest first. */
78
+ commits: string[];
79
+ }
80
+
81
+ /** One change-set entry two items both reach. */
82
+ export interface OverlapAddress {
83
+ /** The change set's digest, as `chant change-set show` takes it. */
84
+ changeSet: string;
85
+ /** The workspace member whose ledger stores the change set, or null for the flat ledger. */
86
+ ledgerMember: string | null;
87
+ /** The entry's change-set member and planner address. */
88
+ member: string;
89
+ address: string;
90
+ /** The entry's graph node, or null. */
91
+ node: string | null;
92
+ /** The source file the attribution went through, from the repository root. */
93
+ source: string;
94
+ }
95
+
96
+ /** Two in-flight work items that changed the same thing. */
97
+ export interface OverlapPair {
98
+ /** The two items, `<work kind>:<id>`, in sorted order. */
99
+ items: [string, string];
100
+ /** The files both items' linked commits touch, sorted. */
101
+ files: string[];
102
+ /** The change-set entries attributed to both items, by change set then address. */
103
+ addresses: OverlapAddress[];
104
+ }
105
+
106
+ /** What `workspace status` reports as `overlap`. */
107
+ export interface OverlapReport {
108
+ /** The in-flight work items with a linked commit, by item. */
109
+ items: OverlapItem[];
110
+ /** Each pair of items that share a file or an entry, by the first item then the second. */
111
+ pairs: OverlapPair[];
112
+ /** The digests of the change sets read, sorted. */
113
+ changeSets: string[];
114
+ /** Entries of those change sets with no `source`, so attributed to no item. */
115
+ unattributed: number;
116
+ }
117
+
118
+ /** A change set to attribute: one a pending or approved gate binds. */
119
+ export interface OverlapChangeSetRef {
120
+ digest: string;
121
+ /** A directory whose ledger stores it: the member's directory. */
122
+ cwd: string;
123
+ ledgerMember: string | null;
124
+ /** The commit the gate was reached at, when the pending fact records one. */
125
+ gitSha: string | null;
126
+ }
127
+
128
+ /** Reads a stored change set; the lifecycle store unless a test swaps it. */
129
+ export type StoredChangeSetReader = (digest: string, cwd: string) => Promise<ChangeSetDocument | null>;
130
+
131
+ const defaultReadChangeSet: StoredChangeSetReader = async (digest, cwd) => {
132
+ const { readStoredChangeSet } = await import("../lifecycle/change-set-store");
133
+ const read = await readStoredChangeSet(digest, { cwd });
134
+ return read.status === "found" ? read.document : null;
135
+ };
136
+
137
+ function git(top: string, args: string[], input?: string): string {
138
+ return execFileSync("git", ["-c", "core.quotepath=off", ...args], {
139
+ cwd: top,
140
+ encoding: "utf-8",
141
+ stdio: [input === undefined ? "ignore" : "pipe", "pipe", "ignore"],
142
+ maxBuffer: 512 * 1024 * 1024,
143
+ ...(input !== undefined ? { input } : {}),
144
+ });
145
+ }
146
+
147
+ /** The work items of every declared work kind, with the index commits are judged against and the ones in flight. */
148
+ async function readWorkItems(declaration: Declaration, root: string, top: string): Promise<{ index: WorkIndex; inFlight: Map<string, { path: string; state: string | null }> } | null> {
149
+ const kinds = new Map<string, Set<string>>();
150
+ const inFlight = new Map<string, { path: string; state: string | null }>();
151
+ for (const d of declaredRecordKinds(declaration)) {
152
+ const file = declaredKindFile(d, root);
153
+ const loaded = await loadRecordKind(file, root);
154
+ if (!loaded.kind.work) continue;
155
+ const decisionKind = await loadRecordKind(loaded.kind.work.decisions, dirname(loaded.file));
156
+ const closed = new Set(decisionKind.kind.closedStates ?? []);
157
+ const read = await readRecordsFor({ kind: file, cwd: root });
158
+ const decisions = new Map((read.result.decisions ?? []).map((x) => [x.id, x]));
159
+ const ids = kinds.get(loaded.kind.name) ?? new Set<string>();
160
+ for (const r of read.result.records) {
161
+ if (r.id === null) continue;
162
+ ids.add(r.id);
163
+ if (r.supersededBy !== null) continue;
164
+ const implemented = r.implements ?? [];
165
+ const settled = implemented.length > 0 && implemented.every((x) => decisionConfirmed(decisions.get(x.id), closed));
166
+ const key = `${loaded.kind.name}:${r.id}`;
167
+ if (!settled && !inFlight.has(key)) inFlight.set(key, { path: r.path, state: r.state });
168
+ }
169
+ kinds.set(loaded.kind.name, ids);
170
+ }
171
+ if (kinds.size === 0) return null;
172
+ return { index: { kinds, ledger: hasLeaseLedger(top) }, inFlight };
173
+ }
174
+
175
+ /**
176
+ * The non-merge commits on every local and remote-tracking branch and HEAD
177
+ * that carry a `Chant-Record` or `Chant-Lease` trailer, newest first. The
178
+ * ledger branches under `chant/` are left out.
179
+ */
180
+ export function trailerCommits(top: string): string[] {
181
+ let text: string;
182
+ try {
183
+ text = git(top, [
184
+ "log",
185
+ "--no-merges",
186
+ `--format=%H%x1f%(trailers:key=${RECORD_TRAILER},key=${LEASE_TRAILER},valueonly,separator=%x1e)%x1d`,
187
+ "--exclude=chant/*",
188
+ "--branches",
189
+ "--exclude=*/chant/*",
190
+ "--remotes",
191
+ "HEAD",
192
+ "--",
193
+ ]);
194
+ } catch {
195
+ // An unborn HEAD has no history to read.
196
+ return [];
197
+ }
198
+ const out: string[] = [];
199
+ for (const chunk of text.split("\x1d")) {
200
+ const [sha, trailers] = chunk.trim().split("\x1f");
201
+ if (sha && trailers && trailers.trim() !== "") out.push(sha);
202
+ }
203
+ return out;
204
+ }
205
+
206
+ /** The paths each commit adds, changes or deletes, from the repository root, renames read as a delete and an add. */
207
+ export function commitFiles(top: string, shas: string[]): Map<string, string[]> {
208
+ const out = new Map<string, string[]>();
209
+ if (shas.length === 0) return out;
210
+ const text = git(top, ["log", "--no-walk=unsorted", "--stdin", "--no-renames", "--name-only", "--format=%x1e%H"], `${shas.join("\n")}\n`);
211
+ for (const block of text.split("\x1e")) {
212
+ const lines = block.split("\n").map((l) => l.trim()).filter(Boolean);
213
+ if (lines.length === 0) continue;
214
+ out.set(lines[0], lines.slice(1));
215
+ }
216
+ return out;
217
+ }
218
+
219
+ /** Every commit reachable from `rev`, or null when `rev` is not in the repository. */
220
+ function reachable(top: string, rev: string): Set<string> | null {
221
+ try {
222
+ return new Set(git(top, ["rev-list", rev, "--"]).split("\n").filter(Boolean));
223
+ } catch {
224
+ return null;
225
+ }
226
+ }
227
+
228
+ const byString = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);
229
+
230
+ /**
231
+ * The work items a change-set entry is attributed to, sorted: each item with
232
+ * a linked commit that changed the entry's `source` and is in `within`, the
233
+ * history the change set was planned from (null when that is unknown, so
234
+ * every linked commit counts). An entry with no source has none.
235
+ *
236
+ * `commitsOf` maps each in-flight item to its linked commits, and `files`
237
+ * each commit to the paths it touches.
238
+ */
239
+ export function attributeEntry(
240
+ source: string | undefined,
241
+ commitsOf: ReadonlyMap<string, readonly string[]>,
242
+ files: ReadonlyMap<string, readonly string[]>,
243
+ within: ReadonlySet<string> | null,
244
+ ): string[] {
245
+ if (source === undefined) return [];
246
+ const out: string[] = [];
247
+ for (const [item, commits] of commitsOf) {
248
+ if (commits.some((sha) => (files.get(sha) ?? []).includes(source) && (within === null || within.has(sha)))) out.push(item);
249
+ }
250
+ return out.sort(byString);
251
+ }
252
+
253
+ /**
254
+ * The overlap report for the workspace declared at `root` in the repository
255
+ * at `top`. Null when the declaration names no work kind. Throws when a work
256
+ * kind or its records can't be read, or git fails; `workspace status` writes
257
+ * null then.
258
+ */
259
+ export async function readOverlap(input: {
260
+ declaration: Declaration;
261
+ root: string;
262
+ top: string;
263
+ changeSets: OverlapChangeSetRef[];
264
+ readChangeSet?: StoredChangeSetReader;
265
+ }): Promise<OverlapReport | null> {
266
+ const { top } = input;
267
+ const work = await readWorkItems(input.declaration, input.root, top);
268
+ if (work === null) return null;
269
+
270
+ // The commits of each in-flight item, newest first.
271
+ const commitsOf = new Map<string, string[]>();
272
+ if (work.inFlight.size > 0) {
273
+ const candidates = trailerCommits(top);
274
+ const links = judgeCommits(top, candidates, work.index);
275
+ for (const sha of candidates) {
276
+ for (const id of links.get(sha)?.ids ?? []) {
277
+ if (!work.inFlight.has(id)) continue;
278
+ const list = commitsOf.get(id) ?? [];
279
+ if (!list.includes(sha)) list.push(sha);
280
+ commitsOf.set(id, list);
281
+ }
282
+ }
283
+ }
284
+ const items = [...commitsOf.keys()].sort(byString);
285
+ const files = commitFiles(top, [...new Set([...commitsOf.values()].flat())]);
286
+ const filesOf = new Map(items.map((id) => [id, new Set(commitsOf.get(id)!.flatMap((sha) => files.get(sha) ?? []))]));
287
+
288
+ // Each change-set entry with a source, attributed to the items whose linked commits changed it within the change set's history.
289
+ const read = input.readChangeSet ?? defaultReadChangeSet;
290
+ const seen = new Set<string>();
291
+ const changeSets: string[] = [];
292
+ let unattributed = 0;
293
+ const addressesOf = new Map<string, OverlapAddress[]>();
294
+ const history = new Map<string, Set<string> | null>();
295
+ for (const ref of input.changeSets) {
296
+ const key = `${ref.ledgerMember ?? ""}\0${ref.digest}`;
297
+ if (seen.has(key)) continue;
298
+ seen.add(key);
299
+ const doc = await read(ref.digest, ref.cwd);
300
+ if (doc === null) continue;
301
+ if (!changeSets.includes(doc.digest)) changeSets.push(doc.digest);
302
+ const at = doc.graph?.at ?? ref.gitSha;
303
+ for (const e of doc.entries) {
304
+ if (e.source === undefined) {
305
+ unattributed++;
306
+ continue;
307
+ }
308
+ // Only an entry two items could share needs the change set's history.
309
+ if (attributeEntry(e.source, commitsOf, files, null).length < 2) continue;
310
+ if (at && !history.has(at)) history.set(at, reachable(top, at));
311
+ const owners = attributeEntry(e.source, commitsOf, files, at ? history.get(at)! : null);
312
+ if (owners.length < 2) continue;
313
+ const address: OverlapAddress = { changeSet: doc.digest, ledgerMember: ref.ledgerMember, member: e.member, address: e.address, node: e.node ?? null, source: e.source };
314
+ for (const id of owners) addressesOf.set(id, [...(addressesOf.get(id) ?? []), address]);
315
+ }
316
+ }
317
+ changeSets.sort(byString);
318
+
319
+ const pairs: OverlapPair[] = [];
320
+ for (let i = 0; i < items.length; i++) {
321
+ for (let j = i + 1; j < items.length; j++) {
322
+ const a = items[i];
323
+ const b = items[j];
324
+ const fb = filesOf.get(b)!;
325
+ const shared = [...filesOf.get(a)!].filter((f) => fb.has(f)).sort(byString);
326
+ const ab = addressesOf.get(b) ?? [];
327
+ const addresses = (addressesOf.get(a) ?? [])
328
+ .filter((x) => ab.includes(x))
329
+ .sort((x, y) => byString(x.changeSet, y.changeSet) || byString(x.member, y.member) || byString(x.address, y.address));
330
+ if (shared.length > 0 || addresses.length > 0) pairs.push({ items: [a, b], files: shared, addresses });
331
+ }
332
+ }
333
+
334
+ return {
335
+ items: items.map((id) => ({ item: id, path: work.inFlight.get(id)!.path, state: work.inFlight.get(id)!.state, commits: commitsOf.get(id)! })),
336
+ pairs,
337
+ changeSets,
338
+ unattributed,
339
+ };
340
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * A member's promotion order (#4030): the literal entries of the `environments`
3
+ * array in its `chant.config.ts`, in the order written. A release moves from
4
+ * each environment to the next, so `chant components promote --to <env>` can
5
+ * default `--from` to the step before, and `chant workspace status --json`
6
+ * lists the order for a reader such as behold's lane.
7
+ *
8
+ * A pattern entry such as `pr-*` names no environment, so it is not a step.
9
+ * A component's own `environments` (`component.schema.json`) say where its
10
+ * release is hosted in each environment and never set the order.
11
+ *
12
+ * `canary` marks a step as the canary step. It is declared and surfaced only:
13
+ * no chant command acts on it yet.
14
+ */
15
+
16
+ import { existsSync, readFileSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ import { environmentName, isEnvironmentPattern, type EnvironmentDeclaration } from "../config";
19
+
20
+ /** One step of a member's promotion order. */
21
+ export interface PromotionStep {
22
+ name: string;
23
+ /** True when the entry sets `canary: true`. */
24
+ canary: boolean;
25
+ }
26
+
27
+ /** The member's promotion order from its config's `environments`; `[]` when it declares none. A repeated name keeps its first place. */
28
+ export function promotionOrder(declared: readonly EnvironmentDeclaration[] | null | undefined): PromotionStep[] {
29
+ const out: PromotionStep[] = [];
30
+ for (const entry of declared ?? []) {
31
+ const name = environmentName(entry);
32
+ if (isEnvironmentPattern(name) || out.some((s) => s.name === name)) continue;
33
+ out.push({ name, canary: typeof entry !== "string" && entry.canary === true });
34
+ }
35
+ return out;
36
+ }
37
+
38
+ const STRING = String.raw`(?:"[^"\\\n\[\]{}]*"|'[^'\\\n\[\]{}]*')`;
39
+ const PROP = String.raw`(?:(?:name|endpoint)\s*:\s*${STRING}|canary\s*:\s*(?:true|false))`;
40
+ const ENTRY = String.raw`(?:${STRING}|\{\s*(?:${PROP}\s*,?\s*)*\})`;
41
+ const ARRAY = new RegExp(String.raw`^\[\s*(?:${ENTRY}\s*,?\s*)*\]$`);
42
+
43
+ /**
44
+ * The promotion order a `chant.config.ts` writes as literals, read from its
45
+ * text without running it, or `undefined` when the text is not that simple.
46
+ * Evaluating a TypeScript config loads tsx, and `workspace status` reads every
47
+ * member without that cost (#3976), so the plain cases are read here and the
48
+ * rest fall back to loading the config. The plain cases are a config with no
49
+ * `environments` and no spread, and one whose only `environments` is an array
50
+ * of string entries and `{ name, endpoint, canary }` entries with literal values.
51
+ */
52
+ export function staticPromotionOrder(source: string): PromotionStep[] | undefined {
53
+ const text = source.replace(/("(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|`(?:[^`\\]|\\.)*`)|\/\*[\s\S]*?\*\/|\/\/[^\n]*/g, "$1");
54
+ const mentions = text.match(/\benvironments\b/g)?.length ?? 0;
55
+ if (mentions === 0) return /export\s+default\s*\{/.test(text) && !text.includes("...") ? [] : undefined;
56
+ if (mentions > 1 || text.includes("...")) return undefined;
57
+ const start = text.match(/\benvironments\s*:\s*(\[)/);
58
+ if (!start || start.index === undefined) return undefined;
59
+ const open = start.index + start[0].length - 1;
60
+ const close = text.indexOf("]", open);
61
+ if (close < 0) return undefined;
62
+ const array = text.slice(open, close + 1);
63
+ if (!ARRAY.test(array)) return undefined;
64
+ const entries: EnvironmentDeclaration[] = [];
65
+ for (const m of array.matchAll(new RegExp(`${STRING}|\\{[^}]*\\}`, "g"))) {
66
+ const raw = m[0];
67
+ if (raw.startsWith("{")) {
68
+ const name = raw.match(/\bname\s*:\s*(?:"([^"]*)"|'([^']*)')/);
69
+ if (!name) return undefined;
70
+ entries.push({ name: name[1] ?? name[2], canary: /\bcanary\s*:\s*true\b/.test(raw) });
71
+ } else {
72
+ entries.push(raw.slice(1, -1));
73
+ }
74
+ }
75
+ return promotionOrder(entries);
76
+ }
77
+
78
+ /**
79
+ * One member's promotion order from its directory's config: `[]` when it has
80
+ * none or declares no environments, and null when the config can't be read.
81
+ * A TypeScript config is read as text when it is plain ({@link staticPromotionOrder}),
82
+ * and loaded otherwise.
83
+ */
84
+ export async function readMemberPromotionOrder(dir: string): Promise<PromotionStep[] | null> {
85
+ try {
86
+ const ts = join(dir, "chant.config.ts");
87
+ if (existsSync(ts)) {
88
+ const plain = staticPromotionOrder(readFileSync(ts, "utf-8"));
89
+ if (plain) return plain;
90
+ }
91
+ const { loadChantConfig } = await import("../config");
92
+ const { config } = await loadChantConfig(dir);
93
+ return promotionOrder(config.environments);
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
@@ -22,6 +22,7 @@ import { describe, expect, test } from "vitest";
22
22
  import { contract, git, REPO, validSchema } from "./__fixtures__/contract-repo";
23
23
  import checkSchema from "./check.schema.json";
24
24
  import ciLastGreenSchema from "./ci-last-green.schema.json";
25
+ import ciListSchema from "./ci-list.schema.json";
25
26
  import { workspaceComposites } from "./composites";
26
27
  import compositesSchema from "./composites.schema.json";
27
28
  import { workspaceGraph } from "./graph-cli";
@@ -43,13 +44,16 @@ import { queryRecordsSince } from "./records-since";
43
44
  import recordsSinceSchema from "./records-since.schema.json";
44
45
  import { workspacePoints } from "./points-cli";
45
46
  import pointsSchema from "./points.schema.json";
47
+ import releasesSchema from "./releases.schema.json";
48
+ import changeSetShowSchema from "./change-set-show.schema.json";
49
+ import deliveryMetricsSchema from "./delivery-metrics.schema.json";
46
50
  import { workspaceStatus } from "./status";
47
51
  import statusSchema from "./status.schema.json";
48
52
 
49
53
  const FIXTURE = join(REPO, "reference-workspace");
50
54
  const TIMEOUT = 240_000;
51
55
 
52
- const SCHEMAS = { ls: lsSchema, graph: graphSchema, check: checkSchema, status: statusSchema, records: recordsSchema, "records-since": recordsSinceSchema, intent: intentSchema, "intent-record": intentRecordSchema, composites: compositesSchema, points: pointsSchema, patch: patchSchema, "ci-last-green": ciLastGreenSchema };
56
+ const SCHEMAS = { ls: lsSchema, graph: graphSchema, check: checkSchema, status: statusSchema, records: recordsSchema, "records-since": recordsSinceSchema, intent: intentSchema, "intent-record": intentRecordSchema, composites: compositesSchema, points: pointsSchema, patch: patchSchema, "ci-last-green": ciLastGreenSchema, "ci-list": ciListSchema, releases: releasesSchema, "change-set-show": changeSetShowSchema, "delivery-metrics": deliveryMetricsSchema };
53
57
 
54
58
  /** This checkout's chant, started the way the CLI starts it, for members with no toolchain of their own. */
55
59
  const reader: Toolchain = {
@@ -9,7 +9,7 @@ import { readdirSync, readFileSync } from "node:fs";
9
9
  import { join } from "node:path";
10
10
  import { describe, expect, test } from "vitest";
11
11
  import { REPO } from "./__fixtures__/contract-repo";
12
- import { CHANGES_ERROR_CODES, CHANGES_FINDING_CODES } from "./changes";
12
+ import { CHANGES_ERROR_CODES, CHANGES_FINDING_CODES, COMMIT_LINK_FINDING_CODES } from "./changes";
13
13
  import { MEMBER_RUN_REASON_CODES } from "./compose-graph";
14
14
  import { COMPOSITES_ENVIRONMENT_REASON_CODES, COMPOSITES_ERROR_CODES, COMPOSITES_REASON_CODES, COMPOSITES_RUNTIME_REASON_CODES } from "./composites";
15
15
  import { WORKSPACE_ERROR_CODES } from "./declaration";
@@ -34,6 +34,7 @@ import { RUN_STATEMENT_FAILURE_CODES } from "./trust/run-statement";
34
34
  import { WORK_EVIDENCE_ERROR_CODES } from "./work-evidence";
35
35
  import { RECORD_FINDING_CODES } from "./checks/records";
36
36
  import { ANSWER_WARNING_CODES } from "./points";
37
+ import { FLAG_WARNING_CODES } from "./flags";
37
38
  import { POINTS_ERROR_CODES, POINTS_SOURCE_REASON_CODES } from "./points-cli";
38
39
  import { POINTS_WRITE_ERROR_CODES } from "./decide";
39
40
  import { PATCH_ERROR_CODES } from "./patch";
@@ -50,6 +51,7 @@ import { CI_GREEN_ERROR_CODES } from "./ci-green";
50
51
  import { ROTATION_REFUSAL_CODES } from "./trust/rotation";
51
52
  import { SIGNERS_ERROR_CODES } from "./trust/signers-cli";
52
53
  import { EVIDENCE_ERROR_CODES } from "./trust/evidence";
54
+ import { METRICS_ERROR_CODES, METRICS_REASON_CODES } from "./delivery-metrics";
53
55
 
54
56
  const HERE = import.meta.dirname;
55
57
 
@@ -85,6 +87,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
85
87
  INTENT_REASON_CODES,
86
88
  INTENT_WHY_CODES,
87
89
  CHANGES_FINDING_CODES,
90
+ COMMIT_LINK_FINDING_CODES,
88
91
  CHANGES_ERROR_CODES,
89
92
  COMPOSITES_ERROR_CODES,
90
93
  COMPOSITES_REASON_CODES,
@@ -100,6 +103,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
100
103
  RUN_STATEMENT_FAILURE_CODES,
101
104
  WORK_EVIDENCE_ERROR_CODES,
102
105
  RECORD_FINDING_CODES,
106
+ FLAG_WARNING_CODES,
103
107
  ANSWER_WARNING_CODES,
104
108
  POINTS_ERROR_CODES,
105
109
  POINTS_SOURCE_REASON_CODES,
@@ -120,6 +124,8 @@ const PER_COMMAND: Record<string, readonly string[]> = {
120
124
  ROTATION_REFUSAL_CODES,
121
125
  SIGNERS_ERROR_CODES,
122
126
  EVIDENCE_ERROR_CODES,
127
+ METRICS_ERROR_CODES,
128
+ METRICS_REASON_CODES,
123
129
  };
124
130
 
125
131
  /** Every string in an `enum` under a property named `code`, anywhere in a schema. */
@@ -95,6 +95,9 @@ export const REASONS = {
95
95
  "work-contract-unknown": "A work record names a contract that no record of its kind's contract kind has.",
96
96
  "work-contract-undecided": "A work record names a contract whose state is not approved, such as a draft.",
97
97
  "work-tier-unknown": "A work record names a builder tier that its kind's work.tier.tiers does not list.",
98
+ // A feature flag that is valid but warned about (records, check, #4024).
99
+ "flag-work-unknown": "A flag record names a work item that no record of its kind's work kind has.",
100
+ "flag-stale": "Every decision a flag's work item implements is confirmed, so the flag is due for removal. check reports it (WSP118).",
98
101
  // An answer to a decision point that is valid but warned about (records, points, ws-058, #2739).
99
102
  "answer-points-unreadable": "The points file the answer kind names can't be read, or is not valid.",
100
103
  "answer-point-unknown": "The answer's point is not declared in the points file the answer kind names.",
@@ -205,6 +208,9 @@ export const REASONS = {
205
208
  // The forward coverage check (check --changes, #2773): findings, one per changed path.
206
209
  "change-uncovered": "A path the diff changes is covered by no current decided record and no open work item, by path or by its member.",
207
210
  "change-out-of-scope": "A record in hand for the change, such as the work item it is for or a decision that item implements, lists a path the diff changes in its out_of_scope.",
211
+ // The commit link check (check --changes, #4029): findings, one per trunk commit.
212
+ "commit-unlinked": "A trunk commit in the range names no work item: it has no Chant-Record trailer of a work kind and no Chant-Lease trailer.",
213
+ "commit-wrongly-linked": "A trunk commit in the range names a work item that is not there: a Chant-Record whose id no work kind has or whose kind is not a work kind, a malformed Chant-Record, or a Chant-Lease that resolves to no work item, and no other trailer links it.",
208
214
  // The patch read (workspace patch): a read that fails.
209
215
  "patch-path-invalid": "workspace patch --path names a path that is not relative and inside the workspace.",
210
216
  // Composite instances joined to components (graph --composites, #2662): why the list is empty or has no component.
@@ -283,7 +289,7 @@ export const REASONS = {
283
289
  "wip-race": "Another writer moved refs/chant/wip/<branch> between this command's read and its write.",
284
290
  "wip-policy-none": "wip push or wip fetch was run, and no box block declares replicate, so there is no remote.",
285
291
  "wip-remote-unknown": "The replicate policy names a git remote the checkout does not have; the host adds it, with its credential, before chant pushes.",
286
- // Which commits passed CI (ci last-green and ci tick, #3573): why nothing was read.
292
+ // Which commits passed CI (ci last-green, ci list and ci tick, #3573): why nothing was read.
287
293
  "ci-green-undeclared": "The declaration has no ci.green block, so chant does not know which check runs make a commit green.",
288
294
  "ci-branch-unknown": "The checkout has no ref for the branch ci.green names: neither the remote-tracking branch nor a local one.",
289
295
  // A box whose isolation fails (check, #2727). Each is also a WSP finding.
@@ -19,6 +19,7 @@ import { pinFile, queryRecords, type RecordsDocument } from "./records-cli";
19
19
  import { parseFrontMatter, RECORD_WARNING_CODES, SEAL_WARNING_CODES } from "./records";
20
20
  import { WORK_WARNING_CODES } from "./work";
21
21
  import { ANSWER_WARNING_CODES } from "./points";
22
+ import { FLAG_WARNING_CODES } from "./flags";
22
23
  import { workspaceGraph } from "./graph-cli";
23
24
  import graphSchema from "./graph.schema.json";
24
25
  import recordsSchema from "./records.schema.json";
@@ -172,7 +173,7 @@ describe("chant workspace records checks each pin", () => {
172
173
  test("the schema lists exactly the warning codes", () => {
173
174
  // A work kind's records carry the work warnings too (#2683), work-done-gap-open included since records walks a done item's region (#2686),
174
175
  // an answer kind's the answer warnings (ws-058), and records adds record-unattested for an author seal under a signers file at base (#2688).
175
- expect(recordsSchema.$defs.warning.properties.code.enum).toEqual([...RECORD_WARNING_CODES, ...WORK_WARNING_CODES, ...ANSWER_WARNING_CODES, ...SEAL_WARNING_CODES]);
176
+ expect(recordsSchema.$defs.warning.properties.code.enum).toEqual([...RECORD_WARNING_CODES, ...WORK_WARNING_CODES, ...ANSWER_WARNING_CODES, ...SEAL_WARNING_CODES, ...FLAG_WARNING_CODES]);
176
177
  });
177
178
 
178
179
  test("records pin <path> prints the entry's path from the workspace root and the file's hash", () => {
@@ -14,6 +14,7 @@ import { queryRecords, RECORDS_CONTRACT_VERSION, RECORDS_OUTPUT_SCHEMA_ID, type
14
14
  import { READ_ERROR_CODES, RECORD_REASON_CODES, RECORD_WARNING_CODES, recordTextDigest, REVIEW_REASON_CODES, SEAL_WARNING_CODES } from "./records";
15
15
  import { WORK_WARNING_CODES } from "./work";
16
16
  import { ANSWER_WARNING_CODES } from "./points";
17
+ import { FLAG_WARNING_CODES } from "./flags";
17
18
  import schema from "./records.schema.json";
18
19
  import { PROVENANCE_LEVELS } from "./trust/attestor";
19
20
 
@@ -152,7 +153,7 @@ describe("records output schema", () => {
152
153
  test("lists exactly the warning codes the code can return", () => {
153
154
  // A work kind's records carry the work warnings too (#2683), work-done-gap-open included since records walks a done item's region (#2686),
154
155
  // an answer kind's the answer warnings (ws-058), and records adds record-unattested for an author seal under a signers file at base (#2688).
155
- expect(schema.$defs.warning.properties.code.enum).toEqual([...RECORD_WARNING_CODES, ...WORK_WARNING_CODES, ...ANSWER_WARNING_CODES, ...SEAL_WARNING_CODES]);
156
+ expect(schema.$defs.warning.properties.code.enum).toEqual([...RECORD_WARNING_CODES, ...WORK_WARNING_CODES, ...ANSWER_WARNING_CODES, ...SEAL_WARNING_CODES, ...FLAG_WARNING_CODES]);
156
157
  });
157
158
 
158
159
  test("every failure validates with its code", async () => {
@@ -254,7 +254,7 @@
254
254
  "items": { "$ref": "#/$defs/asset" }
255
255
  },
256
256
  "warnings": {
257
- "description": "Added in contract 1 by #2549. Findings that leave the record valid: a pinned file that changed, went missing or did not follow a superseding decision, a supersedes link that has no effect yet, (added by #2654) an evidence list that is empty, (added by #2672) a verdict that names no digest, or (added by #2683) a work record's links and dates, or (added by #2688) a record whose author seal is not attested under a signers file at base, or (added by #2772) a work record's acceptance criteria unmet when it is done, or met by a manual verdict from its implementer, or (added by #3147) a work record's contract that no record has or nobody approved, or a builder tier its kind does not list. A work record never carries record-no-evidence; a done one with no evidence carries work-done-unpinned. valid and --current do not look at them.",
257
+ "description": "Added in contract 1 by #2549. Findings that leave the record valid: a pinned file that changed, went missing or did not follow a superseding decision, a supersedes link that has no effect yet, (added by #2654) an evidence list that is empty, (added by #2672) a verdict that names no digest, or (added by #2683) a work record's links and dates, or (added by #2688) a record whose author seal is not attested under a signers file at base, or (added by #2772) a work record's acceptance criteria unmet when it is done, or met by a manual verdict from its implementer, or (added by #3147) a work record's contract that no record has or nobody approved, or a builder tier its kind does not list, or (added by #4024) a flag record's work item that no record has, or a flag due for removal. A work record never carries record-no-evidence; a done one with no evidence carries work-done-unpinned. valid and --current do not look at them.",
258
258
  "type": "array",
259
259
  "items": { "$ref": "#/$defs/warning" }
260
260
  },
@@ -322,6 +322,23 @@
322
322
  "description": "Added in contract 1 by #3147, on every parsed record of a work kind whose work block names a contract kind. The contract record the item builds, by the id in the work block's contract field, with that record's state now; state is null when no record of the contract kind has the id. Null when the item names no contract.",
323
323
  "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/workLink" }]
324
324
  },
325
+ "flag": {
326
+ "description": "Added in contract 1 by #4024, on every parsed record of a flag kind (a kind with a flag block). work is the work item the flag hides, with that item's state (null when no record of the flag kind's work kind has it), or null when the record names none. implements lists each decision the item implements, with its state and confirmed: true when it is in one of its kind's closed states and nothing supersedes it. stale is true when the item implements at least one decision and every one is confirmed: the flag is due for removal, warned flag-stale, and chant workspace check reports it as WSP118.",
327
+ "type": "object",
328
+ "required": ["work", "implements", "stale"],
329
+ "properties": {
330
+ "work": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/workLink" }] },
331
+ "implements": {
332
+ "type": "array",
333
+ "items": {
334
+ "type": "object",
335
+ "required": ["id", "state", "confirmed"],
336
+ "properties": { "id": { "type": "string" }, "state": { "type": ["string", "null"] }, "confirmed": { "type": "boolean" } }
337
+ }
338
+ },
339
+ "stale": { "type": "boolean" }
340
+ }
341
+ },
325
342
  "answers": {
326
343
  "description": "Added in contract 1 by #3147, on every record with an id of a work kind whose work block names an answer kind. The decision-point answers about the item: each answer record whose constrains names the item's id, in path order, joined by id and never copied onto the item. Read at the same revision; in the working tree, with the answers a steward keeps on the lifecycle ledger laid over it. Absent when the answer kind can't be read.",
327
344
  "type": "array",
@@ -414,7 +431,9 @@
414
431
  "answer-point-unknown",
415
432
  "answer-point-changed",
416
433
  "record-unattested",
417
- "record-ratified-below-quorum"
434
+ "record-ratified-below-quorum",
435
+ "flag-work-unknown",
436
+ "flag-stale"
418
437
  ]
419
438
  },
420
439
  "message": { "type": "string" }