@intentius/chant 0.124.46 → 0.124.48

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 (633) hide show
  1. package/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  2. package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  3. package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  4. package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  5. package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  6. package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  7. package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
  8. package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
  9. package/dist/__golden__/wave-loop/op-denied.json +16 -0
  10. package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  11. package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  12. package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
  13. package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
  14. package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
  15. package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  16. package/dist/__golden__/wave-loop/op-held-on.json +16 -0
  17. package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  18. package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  19. package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  20. package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  21. package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
  22. package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  23. package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
  24. package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  25. package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
  26. package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
  27. package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  28. package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  29. package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
  30. package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  31. package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  32. package/dist/__golden__/wave-loop/op-overridden.json +16 -0
  33. package/dist/__golden__/wave-loop/op-per-run.json +20 -0
  34. package/dist/__golden__/wave-loop/op-point.json +13 -0
  35. package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
  36. package/dist/__golden__/wave-loop/op-sealed.json +10 -0
  37. package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
  38. package/dist/__golden__/wave-loop/op-spend.json +10 -0
  39. package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
  40. package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
  41. package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
  42. package/dist/__golden__/wave-loop/op-wide.json +39 -0
  43. package/dist/action-pins.d.ts +61 -0
  44. package/dist/action-pins.d.ts.map +1 -0
  45. package/dist/action-pins.js +77 -0
  46. package/dist/cli/commands/carve.d.ts +3 -0
  47. package/dist/cli/commands/carve.d.ts.map +1 -1
  48. package/dist/cli/commands/carve.js +36 -7
  49. package/dist/cli/commands/import-report.d.ts +26 -0
  50. package/dist/cli/commands/import-report.d.ts.map +1 -0
  51. package/dist/cli/commands/import-report.js +65 -0
  52. package/dist/cli/commands/import.d.ts +11 -1
  53. package/dist/cli/commands/import.d.ts.map +1 -1
  54. package/dist/cli/commands/import.js +22 -3
  55. package/dist/cli/commands/migrate.d.ts +13 -1
  56. package/dist/cli/commands/migrate.d.ts.map +1 -1
  57. package/dist/cli/commands/migrate.js +134 -10
  58. package/dist/cli/handlers/approve.d.ts.map +1 -1
  59. package/dist/cli/handlers/approve.js +21 -2
  60. package/dist/cli/handlers/build.d.ts.map +1 -1
  61. package/dist/cli/handlers/build.js +6 -1
  62. package/dist/cli/handlers/ledger.d.ts +3 -0
  63. package/dist/cli/handlers/ledger.d.ts.map +1 -0
  64. package/dist/cli/handlers/ledger.js +55 -0
  65. package/dist/cli/handlers/migrate.d.ts.map +1 -1
  66. package/dist/cli/handlers/migrate.js +18 -11
  67. package/dist/cli/handlers/misc.d.ts.map +1 -1
  68. package/dist/cli/handlers/misc.js +12 -1
  69. package/dist/cli/handlers/pr-env.js +2 -2
  70. package/dist/cli/handlers/pr.d.ts +15 -1
  71. package/dist/cli/handlers/pr.d.ts.map +1 -1
  72. package/dist/cli/handlers/pr.js +143 -39
  73. package/dist/cli/handlers/query.d.ts +7 -2
  74. package/dist/cli/handlers/query.d.ts.map +1 -1
  75. package/dist/cli/handlers/query.js +16 -4
  76. package/dist/cli/handlers/release.d.ts.map +1 -1
  77. package/dist/cli/handlers/release.js +6 -3
  78. package/dist/cli/handlers/search.d.ts +2 -4
  79. package/dist/cli/handlers/search.d.ts.map +1 -1
  80. package/dist/cli/handlers/search.js +13 -39
  81. package/dist/cli/main.d.ts.map +1 -1
  82. package/dist/cli/main.js +65 -14
  83. package/dist/cli/parse-args.d.ts.map +1 -1
  84. package/dist/cli/parse-args.js +36 -2
  85. package/dist/cli/registry.d.ts +14 -4
  86. package/dist/cli/registry.d.ts.map +1 -1
  87. package/dist/components/builders.d.ts +5 -1
  88. package/dist/components/builders.d.ts.map +1 -1
  89. package/dist/components/builders.js +5 -0
  90. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  91. package/dist/components/capability-plugin-loader.js +16 -1
  92. package/dist/components/capability-plugin.d.ts +14 -0
  93. package/dist/components/capability-plugin.d.ts.map +1 -1
  94. package/dist/components/pr-hooks.d.ts +21 -1
  95. package/dist/components/pr-hooks.d.ts.map +1 -1
  96. package/dist/components/pr-hooks.js +72 -4
  97. package/dist/components/pr-pipeline.d.ts +45 -10
  98. package/dist/components/pr-pipeline.d.ts.map +1 -1
  99. package/dist/components/pr-pipeline.js +47 -14
  100. package/dist/components/pr-policy.d.ts +36 -0
  101. package/dist/components/pr-policy.d.ts.map +1 -1
  102. package/dist/components/pr-policy.js +36 -0
  103. package/dist/components/starter-plugin.d.ts +1 -0
  104. package/dist/components/starter-plugin.d.ts.map +1 -1
  105. package/dist/components/starter-plugin.js +5 -1
  106. package/dist/components/verbs/index.d.ts +2 -0
  107. package/dist/components/verbs/index.d.ts.map +1 -1
  108. package/dist/components/verbs/index.js +2 -0
  109. package/dist/components/verbs/publish-artifact.d.ts +65 -0
  110. package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
  111. package/dist/components/verbs/publish-artifact.js +74 -0
  112. package/dist/components/verbs/publish-image.d.ts +129 -0
  113. package/dist/components/verbs/publish-image.d.ts.map +1 -0
  114. package/dist/components/verbs/publish-image.js +145 -0
  115. package/dist/config-environments.d.ts +20 -0
  116. package/dist/config-environments.d.ts.map +1 -1
  117. package/dist/config-environments.js +12 -0
  118. package/dist/config.d.ts +9 -1
  119. package/dist/config.d.ts.map +1 -1
  120. package/dist/config.js +6 -2
  121. package/dist/gate-decision.d.ts +11 -2
  122. package/dist/gate-decision.d.ts.map +1 -1
  123. package/dist/gate-decision.js +15 -3
  124. package/dist/graph-ir.d.ts +25 -0
  125. package/dist/graph-ir.d.ts.map +1 -1
  126. package/dist/graph-walk.d.ts +66 -0
  127. package/dist/graph-walk.d.ts.map +1 -0
  128. package/dist/graph-walk.js +70 -0
  129. package/dist/import/parser.d.ts +19 -0
  130. package/dist/import/parser.d.ts.map +1 -1
  131. package/dist/lexicon.d.ts +71 -6
  132. package/dist/lexicon.d.ts.map +1 -1
  133. package/dist/lifecycle/gate-ledger.d.ts +11 -0
  134. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  135. package/dist/lifecycle/git.d.ts +2 -5
  136. package/dist/lifecycle/git.d.ts.map +1 -1
  137. package/dist/lifecycle/ledger-read.d.ts +65 -0
  138. package/dist/lifecycle/ledger-read.d.ts.map +1 -0
  139. package/dist/lifecycle/ledger-read.js +160 -0
  140. package/dist/lifecycle/release-workstation.d.ts +7 -0
  141. package/dist/lifecycle/release-workstation.d.ts.map +1 -1
  142. package/dist/lifecycle/release-workstation.js +25 -0
  143. package/dist/lifecycle/run-ledger.d.ts +4 -3
  144. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  145. package/dist/lifecycle/run-ledger.js +1 -0
  146. package/dist/lint/discover.js +3 -1
  147. package/dist/lint/post-synth.d.ts +127 -1
  148. package/dist/lint/post-synth.d.ts.map +1 -1
  149. package/dist/lint/post-synth.js +84 -2
  150. package/dist/lint/rules/op/index.d.ts +1 -0
  151. package/dist/lint/rules/op/index.d.ts.map +1 -1
  152. package/dist/lint/rules/op/index.js +2 -0
  153. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
  154. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
  155. package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
  156. package/dist/op/activities/activity-contracts.d.ts +5 -2
  157. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  158. package/dist/op/activities/activity-contracts.js +5 -2
  159. package/dist/op/activities/index.d.ts +2 -2
  160. package/dist/op/activities/index.d.ts.map +1 -1
  161. package/dist/op/activities/index.js +1 -1
  162. package/dist/op/activities/review-agent.d.ts +90 -4
  163. package/dist/op/activities/review-agent.d.ts.map +1 -1
  164. package/dist/op/activities/review-agent.js +217 -19
  165. package/dist/op/activities/work-evidence.d.ts +8 -1
  166. package/dist/op/activities/work-evidence.d.ts.map +1 -1
  167. package/dist/op/activities/work-evidence.js +1 -0
  168. package/dist/op/builders.d.ts +9 -5
  169. package/dist/op/builders.d.ts.map +1 -1
  170. package/dist/op/builders.js +9 -5
  171. package/dist/op/composites/apply-op.d.ts +29 -2
  172. package/dist/op/composites/apply-op.d.ts.map +1 -1
  173. package/dist/op/composites/apply-op.js +20 -1
  174. package/dist/op/gate-approval.d.ts +11 -5
  175. package/dist/op/gate-approval.d.ts.map +1 -1
  176. package/dist/op/gate-approval.js +11 -6
  177. package/dist/op/gate-quorum.d.ts +100 -3
  178. package/dist/op/gate-quorum.d.ts.map +1 -1
  179. package/dist/op/gate-quorum.js +108 -6
  180. package/dist/op/gate-review.d.ts +9 -0
  181. package/dist/op/gate-review.d.ts.map +1 -1
  182. package/dist/op/gate-review.js +13 -0
  183. package/dist/op/gate.d.ts +44 -3
  184. package/dist/op/gate.d.ts.map +1 -1
  185. package/dist/op/gate.js +25 -4
  186. package/dist/op/index.d.ts +3 -3
  187. package/dist/op/index.d.ts.map +1 -1
  188. package/dist/op/index.js +1 -1
  189. package/dist/op/local-executor.d.ts +38 -3
  190. package/dist/op/local-executor.d.ts.map +1 -1
  191. package/dist/op/local-executor.js +48 -6
  192. package/dist/op/op-waves-run.d.ts +26 -1
  193. package/dist/op/op-waves-run.d.ts.map +1 -1
  194. package/dist/op/op-waves-run.js +259 -13
  195. package/dist/op/op-waves.d.ts +72 -5
  196. package/dist/op/op-waves.d.ts.map +1 -1
  197. package/dist/op/op-waves.js +110 -15
  198. package/dist/op/runtime.d.ts +11 -0
  199. package/dist/op/runtime.d.ts.map +1 -1
  200. package/dist/op/schedule-overdue.d.ts +16 -0
  201. package/dist/op/schedule-overdue.d.ts.map +1 -1
  202. package/dist/op/schedule-overdue.js +36 -0
  203. package/dist/op/stage-hooks.d.ts +9 -2
  204. package/dist/op/stage-hooks.d.ts.map +1 -1
  205. package/dist/op/stage-hooks.js +7 -5
  206. package/dist/op/workspace-run-env.d.ts +22 -0
  207. package/dist/op/workspace-run-env.d.ts.map +1 -0
  208. package/dist/op/workspace-run-env.js +21 -0
  209. package/dist/pr-forge.d.ts +24 -0
  210. package/dist/pr-forge.d.ts.map +1 -1
  211. package/dist/pr-forge.js +47 -0
  212. package/dist/pr-post.d.ts +42 -0
  213. package/dist/pr-post.d.ts.map +1 -1
  214. package/dist/pr-post.js +67 -1
  215. package/dist/read-filter.d.ts +65 -0
  216. package/dist/read-filter.d.ts.map +1 -0
  217. package/dist/read-filter.js +179 -0
  218. package/dist/run-event.d.ts +1 -1
  219. package/dist/run-event.d.ts.map +1 -1
  220. package/dist/terraform/carve.d.ts +24 -3
  221. package/dist/terraform/carve.d.ts.map +1 -1
  222. package/dist/terraform/carve.js +32 -14
  223. package/dist/terraform/cuts.d.ts +97 -0
  224. package/dist/terraform/cuts.d.ts.map +1 -0
  225. package/dist/terraform/cuts.js +138 -0
  226. package/dist/terraform/folds.d.ts +26 -0
  227. package/dist/terraform/folds.d.ts.map +1 -0
  228. package/dist/terraform/folds.js +38 -0
  229. package/dist/terraform/graph.d.ts.map +1 -1
  230. package/dist/terraform/graph.js +10 -0
  231. package/dist/terraform/reach.d.ts +140 -0
  232. package/dist/terraform/reach.d.ts.map +1 -0
  233. package/dist/terraform/reach.js +170 -0
  234. package/dist/terraform/score.d.ts +14 -0
  235. package/dist/terraform/score.d.ts.map +1 -1
  236. package/dist/terraform/score.js +14 -31
  237. package/dist/terraform/state.d.ts.map +1 -1
  238. package/dist/terraform/state.js +4 -2
  239. package/dist/terraform/types.d.ts +8 -0
  240. package/dist/terraform/types.d.ts.map +1 -1
  241. package/dist/wave-blocked.d.ts +10 -1
  242. package/dist/wave-blocked.d.ts.map +1 -1
  243. package/dist/wave-blocked.js +31 -3
  244. package/dist/wave-runtime.mjs +263 -254
  245. package/dist/workspace/check.schema.json +11 -2
  246. package/dist/workspace/checks/ci-branch.d.ts +44 -0
  247. package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
  248. package/dist/workspace/checks/ci-branch.js +133 -0
  249. package/dist/workspace/checks/links.d.ts +3 -0
  250. package/dist/workspace/checks/links.d.ts.map +1 -1
  251. package/dist/workspace/checks/links.js +12 -1
  252. package/dist/workspace/checks/org.d.ts +48 -0
  253. package/dist/workspace/checks/org.d.ts.map +1 -0
  254. package/dist/workspace/checks/org.js +156 -0
  255. package/dist/workspace/checks.d.ts +11 -1
  256. package/dist/workspace/checks.d.ts.map +1 -1
  257. package/dist/workspace/checks.js +59 -7
  258. package/dist/workspace/ci-branches.d.ts +16 -0
  259. package/dist/workspace/ci-branches.d.ts.map +1 -1
  260. package/dist/workspace/ci-branches.js +27 -0
  261. package/dist/workspace/ci-green-cli.js +7 -7
  262. package/dist/workspace/ci-green-workflow.d.ts +1 -1
  263. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  264. package/dist/workspace/ci-green-workflow.js +13 -8
  265. package/dist/workspace/ci-green.d.ts +14 -0
  266. package/dist/workspace/ci-green.d.ts.map +1 -1
  267. package/dist/workspace/ci-green.js +44 -11
  268. package/dist/workspace/ci-run.d.ts +9 -1
  269. package/dist/workspace/ci-run.d.ts.map +1 -1
  270. package/dist/workspace/ci-run.js +67 -6
  271. package/dist/workspace/ci-serve.d.ts +9 -0
  272. package/dist/workspace/ci-serve.d.ts.map +1 -1
  273. package/dist/workspace/ci-serve.js +114 -76
  274. package/dist/workspace/compose-graph.d.ts +14 -0
  275. package/dist/workspace/compose-graph.d.ts.map +1 -1
  276. package/dist/workspace/composites.d.ts +4 -1
  277. package/dist/workspace/composites.d.ts.map +1 -1
  278. package/dist/workspace/composites.js +5 -2
  279. package/dist/workspace/composites.schema.json +22 -0
  280. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  281. package/dist/workspace/cross-root-lint.d.ts +56 -0
  282. package/dist/workspace/cross-root-lint.d.ts.map +1 -0
  283. package/dist/workspace/cross-root-lint.js +111 -0
  284. package/dist/workspace/dbt-models-reader.d.ts +44 -0
  285. package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
  286. package/dist/workspace/dbt-models-reader.js +356 -0
  287. package/dist/workspace/dbt-project-common.d.ts +40 -0
  288. package/dist/workspace/dbt-project-common.d.ts.map +1 -0
  289. package/dist/workspace/dbt-project-common.js +106 -0
  290. package/dist/workspace/dbt-project-reader.d.ts +4 -3
  291. package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
  292. package/dist/workspace/dbt-project-reader.js +14 -108
  293. package/dist/workspace/decision-rank.d.ts +26 -0
  294. package/dist/workspace/decision-rank.d.ts.map +1 -0
  295. package/dist/workspace/decision-rank.js +16 -0
  296. package/dist/workspace/declaration.d.ts +43 -2
  297. package/dist/workspace/declaration.d.ts.map +1 -1
  298. package/dist/workspace/declaration.js +45 -11
  299. package/dist/workspace/declaration.schema.json +133 -24
  300. package/dist/workspace/environments.d.ts +26 -2
  301. package/dist/workspace/environments.d.ts.map +1 -1
  302. package/dist/workspace/environments.js +26 -2
  303. package/dist/workspace/flyway-dir.d.ts +39 -0
  304. package/dist/workspace/flyway-dir.d.ts.map +1 -0
  305. package/dist/workspace/flyway-dir.js +104 -0
  306. package/dist/workspace/flyway-layout.d.ts +96 -0
  307. package/dist/workspace/flyway-layout.d.ts.map +1 -0
  308. package/dist/workspace/flyway-layout.js +308 -0
  309. package/dist/workspace/graph-cli.d.ts.map +1 -1
  310. package/dist/workspace/graph-cli.js +26 -8
  311. package/dist/workspace/graph.schema.json +34 -0
  312. package/dist/workspace/intent.d.ts +2 -3
  313. package/dist/workspace/intent.d.ts.map +1 -1
  314. package/dist/workspace/intent.js +5 -9
  315. package/dist/workspace/kind-link-readers.d.ts +59 -2
  316. package/dist/workspace/kind-link-readers.d.ts.map +1 -1
  317. package/dist/workspace/kind-link-readers.js +17 -1
  318. package/dist/workspace/kinds.d.ts +66 -2
  319. package/dist/workspace/kinds.d.ts.map +1 -1
  320. package/dist/workspace/kinds.js +98 -4
  321. package/dist/workspace/ledger.schema.json +158 -0
  322. package/dist/workspace/lexicon-outputs.d.ts +20 -1
  323. package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
  324. package/dist/workspace/lexicon-outputs.js +102 -10
  325. package/dist/workspace/lineage-check.d.ts +3 -0
  326. package/dist/workspace/lineage-check.d.ts.map +1 -1
  327. package/dist/workspace/lineage-check.js +23 -4
  328. package/dist/workspace/links.d.ts +8 -1
  329. package/dist/workspace/links.d.ts.map +1 -1
  330. package/dist/workspace/links.js +25 -1
  331. package/dist/workspace/ls.d.ts +8 -0
  332. package/dist/workspace/ls.d.ts.map +1 -1
  333. package/dist/workspace/ls.js +7 -1
  334. package/dist/workspace/ls.schema.json +7 -0
  335. package/dist/workspace/member-commands.d.ts.map +1 -1
  336. package/dist/workspace/member-commands.js +54 -5
  337. package/dist/workspace/migrate-links.d.ts +45 -0
  338. package/dist/workspace/migrate-links.d.ts.map +1 -0
  339. package/dist/workspace/migrate-links.js +100 -0
  340. package/dist/workspace/migration-dirs.d.ts +74 -0
  341. package/dist/workspace/migration-dirs.d.ts.map +1 -0
  342. package/dist/workspace/migration-dirs.js +254 -0
  343. package/dist/workspace/reason-codes.d.ts +8 -0
  344. package/dist/workspace/reason-codes.d.ts.map +1 -1
  345. package/dist/workspace/reason-codes.js +11 -0
  346. package/dist/workspace/records-cli.d.ts +11 -0
  347. package/dist/workspace/records-cli.d.ts.map +1 -1
  348. package/dist/workspace/records-cli.js +57 -5
  349. package/dist/workspace/records.schema.json +5 -0
  350. package/dist/workspace/release-candidates.d.ts +2 -0
  351. package/dist/workspace/release-candidates.d.ts.map +1 -1
  352. package/dist/workspace/release-candidates.js +5 -2
  353. package/dist/workspace/release-train.d.ts +53 -0
  354. package/dist/workspace/release-train.d.ts.map +1 -0
  355. package/dist/workspace/release-train.js +134 -0
  356. package/dist/workspace/release-workflow.d.ts.map +1 -1
  357. package/dist/workspace/release-workflow.js +4 -3
  358. package/dist/workspace/repo-ref.d.ts +45 -0
  359. package/dist/workspace/repo-ref.d.ts.map +1 -0
  360. package/dist/workspace/repo-ref.js +114 -0
  361. package/dist/workspace/run-event.schema.json +2 -2
  362. package/dist/workspace/runs-cli.d.ts +9 -0
  363. package/dist/workspace/runs-cli.d.ts.map +1 -1
  364. package/dist/workspace/runs-cli.js +48 -3
  365. package/dist/workspace/runs.schema.json +7 -0
  366. package/dist/workspace/search-contract.d.ts +1 -1
  367. package/dist/workspace/search-contract.d.ts.map +1 -1
  368. package/dist/workspace/status-decisions.d.ts +37 -0
  369. package/dist/workspace/status-decisions.d.ts.map +1 -0
  370. package/dist/workspace/status-decisions.js +147 -0
  371. package/dist/workspace/status-gates.d.ts +9 -0
  372. package/dist/workspace/status-gates.d.ts.map +1 -1
  373. package/dist/workspace/status.d.ts +4 -0
  374. package/dist/workspace/status.d.ts.map +1 -1
  375. package/dist/workspace/status.js +14 -2
  376. package/dist/workspace/status.schema.json +6 -0
  377. package/dist/workspace/work-cli.d.ts.map +1 -1
  378. package/dist/workspace/work-cli.js +5 -3
  379. package/dist/workspace/work-evidence-ops.d.ts +83 -0
  380. package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
  381. package/dist/workspace/work-evidence-ops.js +169 -0
  382. package/dist/workspace/work-evidence.d.ts +12 -2
  383. package/dist/workspace/work-evidence.d.ts.map +1 -1
  384. package/dist/workspace/work-evidence.js +21 -3
  385. package/dist/workspace/work-evidence.schema.json +49 -2
  386. package/dist/workspace/workspace-gates.d.ts +110 -0
  387. package/dist/workspace/workspace-gates.d.ts.map +1 -0
  388. package/dist/workspace/workspace-gates.js +140 -0
  389. package/dist/workspace/workspace-kinds.schema.json +58 -3
  390. package/dist/workspace/workspace-ledger.d.ts +76 -0
  391. package/dist/workspace/workspace-ledger.d.ts.map +1 -0
  392. package/dist/workspace/workspace-ledger.js +91 -0
  393. package/dist/workspace/workspace-run.d.ts +112 -0
  394. package/dist/workspace/workspace-run.d.ts.map +1 -0
  395. package/dist/workspace/workspace-run.js +432 -0
  396. package/package.json +1 -1
  397. package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  398. package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  399. package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  400. package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  401. package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  402. package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  403. package/src/__golden__/wave-loop/op-cost-member.json +13 -0
  404. package/src/__golden__/wave-loop/op-denied-source.json +16 -0
  405. package/src/__golden__/wave-loop/op-denied.json +16 -0
  406. package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  407. package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  408. package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
  409. package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
  410. package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
  411. package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  412. package/src/__golden__/wave-loop/op-held-on.json +16 -0
  413. package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  414. package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  415. package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  416. package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  417. package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
  418. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  419. package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
  420. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  421. package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
  422. package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
  423. package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  424. package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  425. package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
  426. package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  427. package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  428. package/src/__golden__/wave-loop/op-overridden.json +16 -0
  429. package/src/__golden__/wave-loop/op-per-run.json +20 -0
  430. package/src/__golden__/wave-loop/op-point.json +13 -0
  431. package/src/__golden__/wave-loop/op-pr-review.json +10 -0
  432. package/src/__golden__/wave-loop/op-sealed.json +10 -0
  433. package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
  434. package/src/__golden__/wave-loop/op-spend.json +10 -0
  435. package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
  436. package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
  437. package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
  438. package/src/__golden__/wave-loop/op-wide.json +39 -0
  439. package/src/action-pins.test.ts +78 -0
  440. package/src/action-pins.ts +92 -0
  441. package/src/cli/commands/carve-score-once.test.ts +99 -0
  442. package/src/cli/commands/carve.ts +37 -6
  443. package/src/cli/commands/check-lexicon.test.ts +2 -2
  444. package/src/cli/commands/import-report.ts +71 -0
  445. package/src/cli/commands/import.ts +33 -3
  446. package/src/cli/commands/migrate-dialect.test.ts +145 -0
  447. package/src/cli/commands/migrate.ts +132 -11
  448. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
  449. package/src/cli/handlers/approve.ts +23 -2
  450. package/src/cli/handlers/build.ts +7 -1
  451. package/src/cli/handlers/ledger.ts +54 -0
  452. package/src/cli/handlers/migrate.ts +21 -12
  453. package/src/cli/handlers/misc.ts +10 -1
  454. package/src/cli/handlers/pr-env.ts +2 -2
  455. package/src/cli/handlers/pr.ts +138 -36
  456. package/src/cli/handlers/query.ts +16 -4
  457. package/src/cli/handlers/release.ts +6 -3
  458. package/src/cli/handlers/search.ts +13 -34
  459. package/src/cli/main.test.ts +15 -0
  460. package/src/cli/main.ts +65 -14
  461. package/src/cli/parse-args.ts +27 -2
  462. package/src/cli/registry.ts +14 -4
  463. package/src/components/builders.ts +8 -0
  464. package/src/components/capability-plugin-loader.ts +13 -1
  465. package/src/components/capability-plugin.ts +16 -0
  466. package/src/components/pr-hooks.test.ts +73 -5
  467. package/src/components/pr-hooks.ts +95 -5
  468. package/src/components/pr-pipeline.ts +64 -16
  469. package/src/components/pr-policy.test.ts +64 -1
  470. package/src/components/pr-policy.ts +53 -0
  471. package/src/components/registry.test.ts +1 -1
  472. package/src/components/starter-plugin.ts +6 -0
  473. package/src/components/verbs/index.ts +2 -0
  474. package/src/components/verbs/publish-artifact.test.ts +60 -0
  475. package/src/components/verbs/publish-artifact.ts +122 -0
  476. package/src/components/verbs/publish-image.test.ts +101 -0
  477. package/src/components/verbs/publish-image.ts +265 -0
  478. package/src/config-environments.ts +28 -1
  479. package/src/config.ts +8 -1
  480. package/src/gate-decision-bundle.test.ts +1 -0
  481. package/src/gate-decision-identity.test.ts +9 -0
  482. package/src/gate-decision.ts +26 -3
  483. package/src/graph-ir.ts +27 -0
  484. package/src/graph-walk.test.ts +44 -0
  485. package/src/graph-walk.ts +102 -0
  486. package/src/import/parser.ts +20 -0
  487. package/src/lexicon.ts +74 -6
  488. package/src/lifecycle/gate-ledger.ts +8 -0
  489. package/src/lifecycle/git.ts +2 -2
  490. package/src/lifecycle/ledger-read.test.ts +107 -0
  491. package/src/lifecycle/ledger-read.ts +195 -0
  492. package/src/lifecycle/release-workstation.ts +24 -0
  493. package/src/lifecycle/run-ledger.ts +5 -2
  494. package/src/lint/cross-root.test.ts +122 -0
  495. package/src/lint/discover.ts +3 -1
  496. package/src/lint/post-synth.ts +212 -2
  497. package/src/lint/rules/op/index.ts +2 -0
  498. package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
  499. package/src/op/activities/activity-contracts.ts +5 -2
  500. package/src/op/activities/index.ts +2 -2
  501. package/src/op/activities/review-agent.test.ts +221 -4
  502. package/src/op/activities/review-agent.ts +265 -22
  503. package/src/op/activities/work-evidence.ts +9 -1
  504. package/src/op/builders.ts +9 -5
  505. package/src/op/composites/apply-op.test.ts +108 -0
  506. package/src/op/composites/apply-op.ts +37 -2
  507. package/src/op/gate-approval.test.ts +6 -1
  508. package/src/op/gate-approval.ts +12 -6
  509. package/src/op/gate-quorum-at-base.test.ts +211 -0
  510. package/src/op/gate-quorum.ts +156 -8
  511. package/src/op/gate-review.ts +14 -0
  512. package/src/op/gate.ts +67 -8
  513. package/src/op/index.ts +3 -2
  514. package/src/op/local-executor.ts +69 -9
  515. package/src/op/op-waves-depends-on.test.ts +81 -0
  516. package/src/op/op-waves-hook-targets.test.ts +4 -2
  517. package/src/op/op-waves-quorum-product.test.ts +158 -0
  518. package/src/op/op-waves-run.ts +288 -14
  519. package/src/op/op-waves.ts +143 -14
  520. package/src/op/runtime.ts +8 -0
  521. package/src/op/schedule-overdue.ts +33 -0
  522. package/src/op/stage-hooks.ts +13 -5
  523. package/src/op/workspace-run-env.ts +29 -0
  524. package/src/pr-forge-bundle.test.ts +2 -2
  525. package/src/pr-forge.test.ts +47 -0
  526. package/src/pr-forge.ts +68 -0
  527. package/src/pr-post-open.e2e.test.ts +36 -0
  528. package/src/pr-post.test.ts +102 -3
  529. package/src/pr-post.ts +89 -1
  530. package/src/read-filter.test.ts +54 -0
  531. package/src/read-filter.ts +193 -0
  532. package/src/run-event.ts +1 -1
  533. package/src/stage-hooks-bundle.test.ts +1 -0
  534. package/src/terraform/carve.ts +52 -15
  535. package/src/terraform/cuts.test.ts +173 -0
  536. package/src/terraform/cuts.ts +188 -0
  537. package/src/terraform/folds.ts +44 -0
  538. package/src/terraform/graph.ts +9 -0
  539. package/src/terraform/radius.test.ts +90 -0
  540. package/src/terraform/reach.test.ts +146 -0
  541. package/src/terraform/reach.ts +247 -0
  542. package/src/terraform/score.ts +27 -29
  543. package/src/terraform/state.ts +3 -1
  544. package/src/terraform/types.ts +8 -0
  545. package/src/wave-blocked.ts +28 -3
  546. package/src/wave-loop-golden.test.ts +4 -3
  547. package/src/workspace/behold-kinds.test.ts +1 -1
  548. package/src/workspace/check-contract.test.ts +7 -6
  549. package/src/workspace/check.schema.json +11 -2
  550. package/src/workspace/checks/ci-branch.test.ts +128 -0
  551. package/src/workspace/checks/ci-branch.ts +141 -0
  552. package/src/workspace/checks/links.ts +12 -1
  553. package/src/workspace/checks/org.ts +169 -0
  554. package/src/workspace/checks.ts +64 -7
  555. package/src/workspace/ci-branches.ts +31 -0
  556. package/src/workspace/ci-green-branches.test.ts +153 -0
  557. package/src/workspace/ci-green-cli.ts +7 -7
  558. package/src/workspace/ci-green-workflow.test.ts +4 -3
  559. package/src/workspace/ci-green-workflow.ts +13 -9
  560. package/src/workspace/ci-green.ts +49 -12
  561. package/src/workspace/ci-run.test.ts +72 -1
  562. package/src/workspace/ci-run.ts +68 -8
  563. package/src/workspace/ci-serve.test.ts +95 -0
  564. package/src/workspace/ci-serve.ts +106 -65
  565. package/src/workspace/component-environments.test.ts +25 -2
  566. package/src/workspace/compose-graph.ts +9 -2
  567. package/src/workspace/composites.schema.json +22 -0
  568. package/src/workspace/composites.test.ts +39 -8
  569. package/src/workspace/composites.ts +6 -2
  570. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  571. package/src/workspace/cross-root-lint.test.ts +90 -0
  572. package/src/workspace/cross-root-lint.ts +126 -0
  573. package/src/workspace/dbt-kind.test.ts +3 -2
  574. package/src/workspace/dbt-models-reader.ts +362 -0
  575. package/src/workspace/dbt-models.test.ts +248 -0
  576. package/src/workspace/dbt-project-common.ts +113 -0
  577. package/src/workspace/dbt-project-reader.ts +29 -112
  578. package/src/workspace/decision-rank.ts +40 -0
  579. package/src/workspace/declaration.schema.json +133 -24
  580. package/src/workspace/declaration.ts +84 -15
  581. package/src/workspace/environments.ts +40 -4
  582. package/src/workspace/flyway-dir.ts +113 -0
  583. package/src/workspace/flyway-layout.ts +337 -0
  584. package/src/workspace/graph-cli.ts +25 -10
  585. package/src/workspace/graph-contract.test.ts +4 -2
  586. package/src/workspace/graph.schema.json +34 -0
  587. package/src/workspace/identity.test.ts +14 -2
  588. package/src/workspace/intent.ts +6 -14
  589. package/src/workspace/kind-link-readers.ts +68 -3
  590. package/src/workspace/kinds.test.ts +12 -7
  591. package/src/workspace/kinds.ts +132 -7
  592. package/src/workspace/ledger.schema.json +158 -0
  593. package/src/workspace/lexicon-outputs.ts +132 -13
  594. package/src/workspace/lineage-check.ts +30 -7
  595. package/src/workspace/links.ts +24 -1
  596. package/src/workspace/ls-contract.test.ts +1 -1
  597. package/src/workspace/ls.schema.json +7 -0
  598. package/src/workspace/ls.ts +10 -1
  599. package/src/workspace/member-commands.ts +60 -2
  600. package/src/workspace/member-file-schema.test.ts +124 -0
  601. package/src/workspace/migrate-links.test.ts +99 -0
  602. package/src/workspace/migrate-links.ts +108 -0
  603. package/src/workspace/migration-dirs.test.ts +272 -0
  604. package/src/workspace/migration-dirs.ts +267 -0
  605. package/src/workspace/org-scope.test.ts +238 -0
  606. package/src/workspace/reason-codes.test.ts +6 -1
  607. package/src/workspace/reason-codes.ts +11 -0
  608. package/src/workspace/records-cli.ts +58 -5
  609. package/src/workspace/records.schema.json +5 -0
  610. package/src/workspace/release-candidates.ts +7 -2
  611. package/src/workspace/release-train.ts +157 -0
  612. package/src/workspace/release-workflow.ts +4 -3
  613. package/src/workspace/repo-ref.ts +113 -0
  614. package/src/workspace/run-event.schema.json +2 -2
  615. package/src/workspace/runs-cli.ts +48 -4
  616. package/src/workspace/runs.schema.json +7 -0
  617. package/src/workspace/status-contract.test.ts +46 -1
  618. package/src/workspace/status-decisions.test.ts +100 -0
  619. package/src/workspace/status-decisions.ts +151 -0
  620. package/src/workspace/status-gates.ts +9 -0
  621. package/src/workspace/status.schema.json +6 -0
  622. package/src/workspace/status.ts +17 -3
  623. package/src/workspace/where-filters.test.ts +39 -0
  624. package/src/workspace/work-cli.ts +5 -3
  625. package/src/workspace/work-evidence-ops.test.ts +176 -0
  626. package/src/workspace/work-evidence-ops.ts +189 -0
  627. package/src/workspace/work-evidence.schema.json +49 -2
  628. package/src/workspace/work-evidence.ts +22 -3
  629. package/src/workspace/workspace-gates.ts +200 -0
  630. package/src/workspace/workspace-kinds.schema.json +58 -3
  631. package/src/workspace/workspace-ledger.ts +130 -0
  632. package/src/workspace/workspace-run.test.ts +322 -0
  633. package/src/workspace/workspace-run.ts +461 -0
@@ -307,7 +307,8 @@ export function formatWorkHistory(doc) {
307
307
  * <file|->` (#3159): the `workEvidence` activity (#2772) as a command, so a
308
308
  * writer that is not an Op, such as hud, attaches evidence through chant under
309
309
  * the lease it holds. `--from` gives the entry as JSON: criterion, result,
310
- * title, a url or a path, and optionally as_of. It always prints the
310
+ * title, a url, a path or an ops result to cite (#3171), and optionally
311
+ * as_of. It always prints the
311
312
  * work-evidence document; exit 0 when the entry was appended, 1 otherwise.
312
313
  */
313
314
  async function runWorkEvidence(ctx) {
@@ -326,7 +327,7 @@ async function runWorkEvidence(ctx) {
326
327
  if (!args.token)
327
328
  return fail("evidence needs --token <token>: the lease's fencing token, as its claim printed it");
328
329
  if (args.migrateFrom === undefined)
329
- return fail("evidence needs --from <file|->: the entry as JSON, with criterion, result, title and a url or a path");
330
+ return fail("evidence needs --from <file|->: the entry as JSON, with criterion, result, title and a url, a path or an ops result");
330
331
  for (const [flag, v] of [["--ttl", args.ttl], ["--outcome", args.outcome], ["--note", args.note]]) {
331
332
  if (v !== undefined)
332
333
  return fail(`evidence takes no ${flag}`);
@@ -344,7 +345,7 @@ async function runWorkEvidence(ctx) {
344
345
  catch (err) {
345
346
  return print({ $schema: WORK_EVIDENCE_OUTPUT_SCHEMA_ID, contract: WORK_EVIDENCE_CONTRACT_VERSION, error: { code: "write-input-invalid", message: `--from ${args.migrateFrom} could not be read: ${err instanceof Error ? err.message : String(err)}` } }, 1);
346
347
  }
347
- const known = ["criterion", "result", "title", "url", "path", "as_of"];
348
+ const known = ["criterion", "result", "title", "url", "path", "ops", "as_of"];
348
349
  const unknown = Object.keys(fields).filter((k) => !known.includes(k));
349
350
  if (unknown.length > 0)
350
351
  return fail(`the entry takes ${known.join(", ")}, not ${unknown.join(", ")}`);
@@ -360,6 +361,7 @@ async function runWorkEvidence(ctx) {
360
361
  title: str("title") ?? "",
361
362
  url: str("url"),
362
363
  path: str("path"),
364
+ ops: fields.ops,
363
365
  asOf: str("as_of"),
364
366
  });
365
367
  return print(doc, "error" in doc ? 1 : 0);
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Evidence that cites an ops result (#3171): a run on the Op run ledger, a
3
+ * deploy on an environment's release ledger, a gate answer on a gate ledger,
4
+ * or a release plan in `_plans/`. `attachWorkEvidence` resolves the citation
5
+ * here before it writes anything, so a criterion is only ticked by a record
6
+ * the `chant/lifecycle` branch really holds.
7
+ *
8
+ * The citation names the record the way `chant workspace graph --intent`'s
9
+ * `trace` names its links (#4023): `ref` is the ledger file on the branch,
10
+ * `field` and `value` are what picks the record out of it, and `sha256` is
11
+ * the hash of the record as stored, a ledger line or a plan file. A citation
12
+ * that comes with a `sha256` is refused when the record no longer hashes to
13
+ * it.
14
+ *
15
+ * A run says what it showed: an `ok` run is passing evidence and a `fail`
16
+ * run failing evidence, and the result given must agree. A run that is
17
+ * still gated or waiting has no outcome yet and is refused. A deploy, a gate
18
+ * answer and a plan show what they record; whether that meets the criterion
19
+ * is the citer's `result`.
20
+ *
21
+ * Everything is read from the local `chant/lifecycle` branch. Nothing is
22
+ * fetched, the stance `graph --intent` takes.
23
+ */
24
+ import type { EvidenceResult } from "./work.js";
25
+ /** The ledgers evidence can cite. */
26
+ export declare const OPS_EVIDENCE_LEDGERS: readonly ["run", "deploy", "gate", "plan"];
27
+ export type OpsEvidenceLedger = (typeof OPS_EVIDENCE_LEDGERS)[number];
28
+ /** What a caller cites: which record, in which ledger, and optionally the hash it expects. */
29
+ export type OpsCitation = {
30
+ /** The workspace member whose ledger holds the record, when it is not the flat layout. */
31
+ member?: string;
32
+ /** The hash of the record as stored, when the caller already has it. */
33
+ sha256?: string;
34
+ } & ({
35
+ ledger: "run";
36
+ env: string;
37
+ op: string;
38
+ id: string;
39
+ } | {
40
+ ledger: "deploy";
41
+ env: string;
42
+ runId: string;
43
+ component?: string;
44
+ } | {
45
+ ledger: "gate";
46
+ op: string;
47
+ gate: string;
48
+ at: string;
49
+ } | {
50
+ ledger: "plan";
51
+ digest: string;
52
+ });
53
+ /** The citation as the evidence entry stores it, once it resolved. */
54
+ export interface OpsEvidence {
55
+ ledger: OpsEvidenceLedger;
56
+ /** The ledger file, as `chant/lifecycle:<path>`. */
57
+ ref: string;
58
+ /** The field of the record that picked it out, and its value. */
59
+ field: string;
60
+ value: string;
61
+ /** Hex SHA-256 of the record as stored. */
62
+ sha256: string;
63
+ /** The environment, for a run or a deploy. */
64
+ env?: string;
65
+ /** The run's status, for a run. */
66
+ outcome?: string;
67
+ }
68
+ export type OpsCitationError = {
69
+ code: "write-input-invalid" | "work-evidence-ops-missing" | "work-evidence-ops-mismatch" | "work-evidence-ops-unfinished";
70
+ message: string;
71
+ };
72
+ /** Check a citation's shape, before anything is read. Returns the message for a bad one. */
73
+ export declare function opsCitationProblem(cite: unknown): string | null;
74
+ /**
75
+ * Find the cited record on the local `chant/lifecycle` branch and check it
76
+ * against the citation and the result given. Never throws for a refusal.
77
+ */
78
+ export declare function resolveOpsCitation(cite: OpsCitation, result: EvidenceResult, cwd: string): Promise<{
79
+ ops: OpsEvidence;
80
+ } | {
81
+ error: OpsCitationError;
82
+ }>;
83
+ //# sourceMappingURL=work-evidence-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-evidence-ops.d.ts","sourceRoot":"","sources":["../../src/workspace/work-evidence-ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,qCAAqC;AACrC,eAAO,MAAM,oBAAoB,YAAI,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAC/E,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,8FAA8F;AAC9F,MAAM,MAAM,WAAW,GAAG;IACxB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,CACA;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CACrC,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,qBAAqB,GAAG,2BAA2B,GAAG,4BAA4B,GAAG,8BAA8B,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAsB9K,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAuB/D;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAAC,CA2E5J"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Evidence that cites an ops result (#3171): a run on the Op run ledger, a
3
+ * deploy on an environment's release ledger, a gate answer on a gate ledger,
4
+ * or a release plan in `_plans/`. `attachWorkEvidence` resolves the citation
5
+ * here before it writes anything, so a criterion is only ticked by a record
6
+ * the `chant/lifecycle` branch really holds.
7
+ *
8
+ * The citation names the record the way `chant workspace graph --intent`'s
9
+ * `trace` names its links (#4023): `ref` is the ledger file on the branch,
10
+ * `field` and `value` are what picks the record out of it, and `sha256` is
11
+ * the hash of the record as stored, a ledger line or a plan file. A citation
12
+ * that comes with a `sha256` is refused when the record no longer hashes to
13
+ * it.
14
+ *
15
+ * A run says what it showed: an `ok` run is passing evidence and a `fail`
16
+ * run failing evidence, and the result given must agree. A run that is
17
+ * still gated or waiting has no outcome yet and is refused. A deploy, a gate
18
+ * answer and a plan show what they record; whether that meets the criterion
19
+ * is the citer's `result`.
20
+ *
21
+ * Everything is read from the local `chant/lifecycle` branch. Nothing is
22
+ * fetched, the stance `graph --intent` takes.
23
+ */
24
+ import { createHash } from "node:crypto";
25
+ import { ledgerDir, readBlobFromPath } from "../lifecycle/git.js";
26
+ /** The ledgers evidence can cite. */
27
+ export const OPS_EVIDENCE_LEDGERS = ["run", "deploy", "gate", "plan"];
28
+ const NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
29
+ const HEX64 = /^[0-9a-f]{64}$/;
30
+ const sha256 = (s) => createHash("sha256").update(s).digest("hex");
31
+ function lines(text) {
32
+ const out = [];
33
+ for (const raw of text.split("\n")) {
34
+ const line = raw.trim();
35
+ if (line === "")
36
+ continue;
37
+ try {
38
+ const rec = JSON.parse(line);
39
+ if (rec !== null && typeof rec === "object" && !Array.isArray(rec))
40
+ out.push({ line, rec: rec });
41
+ }
42
+ catch {
43
+ // A malformed line is skipped, as every ledger reader skips it.
44
+ }
45
+ }
46
+ return out;
47
+ }
48
+ /** Check a citation's shape, before anything is read. Returns the message for a bad one. */
49
+ export function opsCitationProblem(cite) {
50
+ if (cite === null || typeof cite !== "object" || Array.isArray(cite))
51
+ return "ops is an object naming a ledger";
52
+ const c = cite;
53
+ const str = (k) => typeof c[k] === "string" && c[k] !== "";
54
+ const name = (k) => typeof c[k] === "string" && NAME.test(c[k]);
55
+ if (!OPS_EVIDENCE_LEDGERS.includes(c.ledger))
56
+ return `ops.ledger is one of ${OPS_EVIDENCE_LEDGERS.join(", ")}, not ${JSON.stringify(c.ledger)}`;
57
+ if (c.member !== undefined && !name("member"))
58
+ return "ops.member is a member name";
59
+ if (c.sha256 !== undefined && !(typeof c.sha256 === "string" && HEX64.test(c.sha256)))
60
+ return "ops.sha256 is a hex SHA-256";
61
+ const allowed = {
62
+ run: { names: ["env", "op"], strings: ["id"], optional: [] },
63
+ deploy: { names: ["env"], strings: ["runId"], optional: ["component"] },
64
+ gate: { names: ["op"], strings: ["gate", "at"], optional: [] },
65
+ plan: { names: [], strings: ["digest"], optional: [] },
66
+ };
67
+ const spec = allowed[c.ledger];
68
+ for (const k of spec.names)
69
+ if (!name(k))
70
+ return `a ${c.ledger} citation names ops.${k}`;
71
+ for (const k of spec.strings)
72
+ if (!str(k))
73
+ return `a ${c.ledger} citation names ops.${k}`;
74
+ for (const k of spec.optional)
75
+ if (c[k] !== undefined && !str(k))
76
+ return `ops.${k} is a string`;
77
+ const known = new Set(["ledger", "member", "sha256", ...spec.names, ...spec.strings, ...spec.optional]);
78
+ const extra = Object.keys(c).filter((k) => !known.has(k));
79
+ if (extra.length > 0)
80
+ return `a ${c.ledger} citation takes ${[...known].join(", ")}, not ${extra.join(", ")}`;
81
+ if (c.ledger === "plan" && /[/\\]/.test(c.digest))
82
+ return "ops.digest is a plan digest, not a path";
83
+ return null;
84
+ }
85
+ /**
86
+ * Find the cited record on the local `chant/lifecycle` branch and check it
87
+ * against the citation and the result given. Never throws for a refusal.
88
+ */
89
+ export async function resolveOpsCitation(cite, result, cwd) {
90
+ const problem = opsCitationProblem(cite);
91
+ if (problem)
92
+ return { error: { code: "write-input-invalid", message: problem } };
93
+ const loc = { cwd, ...(cite.member !== undefined ? { member: cite.member } : {}) };
94
+ const missing = (what) => ({ error: { code: "work-evidence-ops-missing", message: `the local chant/lifecycle branch has no ${what}` } });
95
+ let found;
96
+ switch (cite.ledger) {
97
+ case "run": {
98
+ const file = `runs__${cite.op}.jsonl`;
99
+ const content = await readBlobFromPath(cite.env, file, loc);
100
+ const hit = content === null ? undefined : lines(content).find((l) => l.rec.id === cite.id);
101
+ if (!hit)
102
+ return missing(`run ${cite.id} of ${cite.op} in ${cite.env}`);
103
+ const status = String(hit.rec.status);
104
+ if (status !== "ok" && status !== "fail") {
105
+ return { error: { code: "work-evidence-ops-unfinished", message: `run ${cite.id} of ${cite.op} is ${status}: it has no outcome yet to cite` } };
106
+ }
107
+ const shows = status === "ok" ? "pass" : "fail";
108
+ if (shows !== result) {
109
+ return { error: { code: "work-evidence-ops-mismatch", message: `run ${cite.id} of ${cite.op} in ${cite.env} ended ${status}, so it is ${shows} evidence, not ${result}` } };
110
+ }
111
+ found = { dir: cite.env, file, text: hit.line, field: "id", value: cite.id, env: cite.env, outcome: status };
112
+ break;
113
+ }
114
+ case "deploy": {
115
+ const file = "releases.jsonl";
116
+ const content = await readBlobFromPath(cite.env, file, loc);
117
+ const hits = content === null ? [] : lines(content).filter((l) => l.rec.runId === cite.runId && (cite.component === undefined || l.rec.component === cite.component));
118
+ if (hits.length === 0)
119
+ return missing(`deploy by run ${cite.runId}${cite.component ? ` of ${cite.component}` : ""} in ${cite.env}`);
120
+ if (hits.length > 1) {
121
+ return { error: { code: "write-input-invalid", message: `run ${cite.runId} deployed ${hits.length} components in ${cite.env}: name the one cited in ops.component` } };
122
+ }
123
+ found = { dir: cite.env, file, text: hits[0].line, field: "runId", value: cite.runId, env: cite.env };
124
+ break;
125
+ }
126
+ case "gate": {
127
+ const file = `${cite.op}.jsonl`;
128
+ const content = await readBlobFromPath("_gates", file, loc);
129
+ const hit = content === null ? undefined : lines(content).find((l) => (l.rec.kind ?? "resolution") === "resolution" && l.rec.gate === cite.gate && l.rec.timestamp === cite.at);
130
+ if (!hit)
131
+ return missing(`answer to gate ${cite.gate} of ${cite.op} at ${cite.at}`);
132
+ found = { dir: "_gates", file, text: hit.line, field: "timestamp", value: cite.at };
133
+ break;
134
+ }
135
+ case "plan": {
136
+ const file = `${cite.digest.replace(/:/g, "_")}.json`;
137
+ const content = await readBlobFromPath("_plans", file, loc);
138
+ if (content === null)
139
+ return missing(`release plan ${cite.digest}`);
140
+ let digest;
141
+ try {
142
+ digest = JSON.parse(content).digest;
143
+ }
144
+ catch {
145
+ digest = undefined;
146
+ }
147
+ if (digest !== cite.digest)
148
+ return { error: { code: "work-evidence-ops-mismatch", message: `the plan stored for ${cite.digest} names another digest` } };
149
+ found = { dir: "_plans", file, text: content, field: "digest", value: cite.digest };
150
+ break;
151
+ }
152
+ }
153
+ const hash = sha256(found.text);
154
+ if (cite.sha256 !== undefined && cite.sha256 !== hash) {
155
+ return { error: { code: "work-evidence-ops-mismatch", message: `the ${cite.ledger} record cited hashes to ${hash}, not the ${cite.sha256} given: it is another record` } };
156
+ }
157
+ const ref = `chant/lifecycle:${await ledgerDir(found.dir, loc)}/${found.file}`;
158
+ return {
159
+ ops: {
160
+ ledger: cite.ledger,
161
+ ref,
162
+ field: found.field,
163
+ value: found.value,
164
+ sha256: hash,
165
+ ...(found.env !== undefined ? { env: found.env } : {}),
166
+ ...(found.outcome !== undefined ? { outcome: found.outcome } : {}),
167
+ },
168
+ };
169
+ }
@@ -17,10 +17,18 @@
17
17
  * one: the run holding the lease is the item's implementer, and a manual
18
18
  * verdict comes from someone else. A person records that verdict with
19
19
  * `records amend`, naming themselves in `by`.
20
+ *
21
+ * Evidence is a public link, a workspace file pinned by hash, or an ops
22
+ * result (#3171): a run, a deploy, a gate answer or a release plan on the
23
+ * `chant/lifecycle` branch, cited the way `graph --intent`'s trace cites it.
24
+ * The citation is resolved against the ledger it names before anything is
25
+ * written, and a run's outcome must agree with the result
26
+ * (`./work-evidence-ops.ts`).
20
27
  */
21
28
  import { type EvidenceResult, type WorkAcceptance } from "./work.js";
29
+ import { type OpsCitation } from "./work-evidence-ops.js";
22
30
  /** Why evidence was not attached. Closed. Nothing is written with any of them. */
23
- export declare const WORK_EVIDENCE_ERROR_CODES: readonly ["kind-unreadable", "kind-invalid", "schema-unreadable", "schema-id-mismatch", "schema-invalid", "location-missing", "write-usage-invalid", "write-input-invalid", "record-not-found", "amend-id-immutable", "record-closed", "amend-supersede-instead", "record-sign-failed", "ratify-quorum-not-met", "record-conflict", "write-lock-timeout", "write-lock-not-held", "write-scope-member", "write-scope-kind", "write-scope-class-unknown", "agent-unknown", "principal-unidentified", "record-unparseable", "record-schema-invalid", "record-id-duplicate", "record-supersedes-unknown", "record-supersedes-conflict", "record-remediates-unknown", "record-remediates-not-closed", "record-seal-mismatch", "session-seal-mismatch", "session-verdict-unknown-record", "work-kind-missing", "work-kind-ambiguous", "work-item-unknown", "work-item-closed", "work-criterion-unknown", "work-acceptance-self-verified", "lease-held", "lease-not-held", "lease-token-mismatch", "not-a-git-repository"];
31
+ export declare const WORK_EVIDENCE_ERROR_CODES: readonly ["kind-unreadable", "kind-invalid", "schema-unreadable", "schema-id-mismatch", "schema-invalid", "location-missing", "write-usage-invalid", "write-input-invalid", "record-not-found", "amend-id-immutable", "record-closed", "amend-supersede-instead", "record-sign-failed", "ratify-quorum-not-met", "record-conflict", "write-lock-timeout", "write-lock-not-held", "write-scope-member", "write-scope-kind", "write-scope-class-unknown", "agent-unknown", "principal-unidentified", "record-unparseable", "record-schema-invalid", "record-id-duplicate", "record-supersedes-unknown", "record-supersedes-conflict", "record-remediates-unknown", "record-remediates-not-closed", "record-seal-mismatch", "session-seal-mismatch", "session-verdict-unknown-record", "work-kind-missing", "work-kind-ambiguous", "work-item-unknown", "work-item-closed", "work-criterion-unknown", "work-acceptance-self-verified", "lease-held", "lease-not-held", "lease-token-mismatch", "not-a-git-repository", "work-evidence-ops-missing", "work-evidence-ops-mismatch", "work-evidence-ops-unfinished"];
24
32
  export type WorkEvidenceErrorCode = (typeof WORK_EVIDENCE_ERROR_CODES)[number];
25
33
  export interface AttachWorkEvidenceRequest {
26
34
  /** Where the workspace is found, and what `path` and `kind` resolve against. */
@@ -38,8 +46,10 @@ export interface AttachWorkEvidenceRequest {
38
46
  title: string;
39
47
  /** A public link, or */
40
48
  url?: string;
41
- /** a workspace file, pinned by the hash of its bytes now. */
49
+ /** a workspace file, pinned by the hash of its bytes now, or */
42
50
  path?: string;
51
+ /** an ops result on the `chant/lifecycle` branch (#3171), verified against its ledger. */
52
+ ops?: OpsCitation;
43
53
  /** When the evidence was taken, as an ISO 8601 timestamp. Now by default. */
44
54
  asOf?: string;
45
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"work-evidence.d.ts","sourceRoot":"","sources":["../../src/workspace/work-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,OAAO,EAAwD,KAAK,cAAc,EAAyB,KAAK,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG/I,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,q9BAYI,CAAC;AAC3C,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E,MAAM,WAAW,yBAAyB;IACxC,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4DAA4D;AAC5D,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD,kFAAkF;AAClF,eAAO,MAAM,8BAA8B,4FAA4F,CAAC;AAExI,UAAU,OAAO;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG,OAAO,GACxC,CACI;IACE,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,wDAAwD;IACxD,UAAU,EAAE,cAAc,CAAC;CAC5B,GACD;IAAE,KAAK,EAAE;QAAE,IAAI,EAAE,qBAAqB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAC9D,CAAC;AAWJ,sGAAsG;AACtG,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,yBAAyB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+DtG"}
1
+ {"version":3,"file":"work-evidence.d.ts","sourceRoot":"","sources":["../../src/workspace/work-evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,OAAO,EAAwD,KAAK,cAAc,EAAyB,KAAK,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE/I,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE3E,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,gjCAeI,CAAC;AAC3C,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E,MAAM,WAAW,yBAAyB;IACxC,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4DAA4D;AAC5D,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD,kFAAkF;AAClF,eAAO,MAAM,8BAA8B,4FAA4F,CAAC;AAExI,UAAU,OAAO;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG,OAAO,GACxC,CACI;IACE,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,wDAAwD;IACxD,UAAU,EAAE,cAAc,CAAC;CAC5B,GACD;IAAE,KAAK,EAAE;QAAE,IAAI,EAAE,qBAAqB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAC9D,CAAC;AAWJ,sGAAsG;AACtG,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,yBAAyB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqEtG"}
@@ -17,6 +17,13 @@
17
17
  * one: the run holding the lease is the item's implementer, and a manual
18
18
  * verdict comes from someone else. A person records that verdict with
19
19
  * `records amend`, naming themselves in `by`.
20
+ *
21
+ * Evidence is a public link, a workspace file pinned by hash, or an ops
22
+ * result (#3171): a run, a deploy, a gate answer or a release plan on the
23
+ * `chant/lifecycle` branch, cited the way `graph --intent`'s trace cites it.
24
+ * The citation is resolved against the ledger it names before anything is
25
+ * written, and a run's outcome must agree with the result
26
+ * (`./work-evidence-ops.ts`).
20
27
  */
21
28
  import { relative, sep } from "node:path";
22
29
  import { activeWorkLeases } from "../lifecycle/work-lease.js";
@@ -24,6 +31,7 @@ import { pinFile } from "./records-cli.js";
24
31
  import { AMEND_ERROR_CODES, amendRecord } from "./records-write.js";
25
32
  import { acceptanceCriteria, EVIDENCE_RESULTS, workAcceptance } from "./work.js";
26
33
  import { findWorkItem, WorkError } from "./work-cli.js";
34
+ import { resolveOpsCitation } from "./work-evidence-ops.js";
27
35
  /** Why evidence was not attached. Closed. Nothing is written with any of them. */
28
36
  export const WORK_EVIDENCE_ERROR_CODES = [
29
37
  ...AMEND_ERROR_CODES,
@@ -37,6 +45,9 @@ export const WORK_EVIDENCE_ERROR_CODES = [
37
45
  "lease-not-held",
38
46
  "lease-token-mismatch",
39
47
  "not-a-git-repository",
48
+ "work-evidence-ops-missing",
49
+ "work-evidence-ops-mismatch",
50
+ "work-evidence-ops-unfinished",
40
51
  ];
41
52
  /** The version of the attach document this chant writes. */
42
53
  export const WORK_EVIDENCE_CONTRACT_VERSION = 1;
@@ -59,8 +70,9 @@ export async function attachWorkEvidence(req) {
59
70
  }
60
71
  if (typeof req.title !== "string" || req.title.trim() === "")
61
72
  throw new EvidenceError("write-usage-invalid", "the evidence has no title");
62
- if ((req.url === undefined) === (req.path === undefined))
63
- throw new EvidenceError("write-usage-invalid", "the evidence is a url or a path, exactly one of them");
73
+ if ([req.url, req.path, req.ops].filter((v) => v !== undefined).length !== 1) {
74
+ throw new EvidenceError("write-usage-invalid", "the evidence is a url, a path or an ops result, exactly one of them");
75
+ }
64
76
  if (req.url !== undefined && !req.url.startsWith("https://"))
65
77
  throw new EvidenceError("write-input-invalid", `evidence links are https://, not ${JSON.stringify(req.url)}`);
66
78
  const found = await findWorkItem(req.item, req.cwd, req.kind);
@@ -87,7 +99,13 @@ export async function attachWorkEvidence(req) {
87
99
  throw new EvidenceError("work-acceptance-self-verified", `${req.criterion} is verified by a person, and ${req.holder} holds ${req.item}'s lease, so it is the implementer: a manual verdict comes from someone else, with records amend`);
88
100
  }
89
101
  let pin;
90
- if (req.path !== undefined) {
102
+ if (req.ops !== undefined) {
103
+ const resolved = await resolveOpsCitation(req.ops, req.result, req.cwd);
104
+ if ("error" in resolved)
105
+ throw new EvidenceError(resolved.error.code, resolved.error.message);
106
+ pin = { ops: resolved.ops };
107
+ }
108
+ else if (req.path !== undefined) {
91
109
  const pinned = pinFile(req.path, req.cwd);
92
110
  if ("error" in pinned)
93
111
  throw new EvidenceError("write-input-invalid", pinned.error);
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "evidence": {
47
47
  "type": "object",
48
- "description": "The entry appended: a title, a url or a path pinned by sha256, as_of, and the criterion, its verification, the result and by, the lease holder.",
48
+ "description": "The entry appended: a title, a url, a path pinned by sha256 or an ops result verified against its ledger (#3171), as_of, and the criterion, its verification, the result and by, the lease holder.",
49
49
  "required": [
50
50
  "title",
51
51
  "criterion",
@@ -91,6 +91,50 @@
91
91
  "by": {
92
92
  "type": "string",
93
93
  "description": "The lease holder that attached it."
94
+ },
95
+ "ops": {
96
+ "type": "object",
97
+ "description": "An ops result on the chant/lifecycle branch (#3171), named the way graph --intent's trace names a link: the ledger file in ref, the field and value that pick the record out of it, and the record's sha256 as stored. A run carries its env and outcome, a deploy its env.",
98
+ "required": [
99
+ "ledger",
100
+ "ref",
101
+ "field",
102
+ "value",
103
+ "sha256"
104
+ ],
105
+ "properties": {
106
+ "ledger": {
107
+ "enum": [
108
+ "run",
109
+ "deploy",
110
+ "gate",
111
+ "plan"
112
+ ]
113
+ },
114
+ "ref": {
115
+ "type": "string",
116
+ "pattern": "^chant/lifecycle:"
117
+ },
118
+ "field": {
119
+ "type": "string"
120
+ },
121
+ "value": {
122
+ "type": "string"
123
+ },
124
+ "sha256": {
125
+ "type": "string",
126
+ "pattern": "^[0-9a-f]{64}$"
127
+ },
128
+ "env": {
129
+ "type": "string"
130
+ },
131
+ "outcome": {
132
+ "enum": [
133
+ "ok",
134
+ "fail"
135
+ ]
136
+ }
137
+ }
94
138
  }
95
139
  }
96
140
  },
@@ -207,7 +251,10 @@
207
251
  "lease-held",
208
252
  "lease-not-held",
209
253
  "lease-token-mismatch",
210
- "not-a-git-repository"
254
+ "not-a-git-repository",
255
+ "work-evidence-ops-missing",
256
+ "work-evidence-ops-mismatch",
257
+ "work-evidence-ops-unfinished"
211
258
  ]
212
259
  },
213
260
  "message": {
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Workspace gates (#2554, #2524 D17, ws-039).
3
+ *
4
+ * A workspace gate is one approval for a change across members. A run of
5
+ * `chant workspace run --gate <name>` whose member runs stop at their own
6
+ * gates records a pending fact under `_members/_workspace/_gates/<name>.jsonl`
7
+ * that lists each stopped member gate and the plan it waits on (a cover),
8
+ * with the digest of that list. `chant workspace run approve <name>` records
9
+ * an approval of one such digest.
10
+ *
11
+ * The rule (ws-039): a workspace gate never satisfies a member gate, unless
12
+ * both hold:
13
+ *
14
+ * 1. its approval's digest covers the member's plan: the approval lists the
15
+ * member, the Op, the gate and the plan digest the member run reached it
16
+ * with, and the list still hashes to the approval's digest;
17
+ * 2. the member opts in at base: its entry in `chant.workspace.json`, read
18
+ * from the base revision as other policy is, sets
19
+ * `acceptWorkspaceGates: true`. A declaration read only from the working
20
+ * tree never opts a member in.
21
+ *
22
+ * A member run started under the gate (`CHANT_WORKSPACE_GATE`) asks this
23
+ * module through `GateCheckInput.workspace` after its own approvals have
24
+ * not passed the gate. Nothing is written to the member's gate ledger: the
25
+ * run's step record says `via: "workspace"` and names the workspace gate.
26
+ */
27
+ import type { WorkspaceGateStood } from "../op/gate.js";
28
+ /** One member gate a workspace gate covers. */
29
+ export interface WorkspaceGateCover {
30
+ member: string;
31
+ op: string;
32
+ gate: string;
33
+ planDigest: string;
34
+ /** The member gate's environment, when it is bound to one. */
35
+ environment?: string;
36
+ }
37
+ export interface WorkspaceGatePending {
38
+ version: 1;
39
+ kind: "pending";
40
+ gate: string;
41
+ /** The workspace run that recorded it. */
42
+ run: string;
43
+ timestamp: string;
44
+ digest: string;
45
+ covers: WorkspaceGateCover[];
46
+ }
47
+ export interface WorkspaceGateApproval {
48
+ version: 1;
49
+ kind: "approval";
50
+ gate: string;
51
+ digest: string;
52
+ covers: WorkspaceGateCover[];
53
+ approvedBy: string;
54
+ timestamp: string;
55
+ note?: string;
56
+ }
57
+ export type WorkspaceGateLine = WorkspaceGatePending | WorkspaceGateApproval;
58
+ /** Covers in one order, so the same set always has the same digest. */
59
+ export declare function sortCovers(covers: readonly WorkspaceGateCover[]): WorkspaceGateCover[];
60
+ /** The digest a workspace gate's pending fact and approval carry: the member plans it covers. */
61
+ export declare function workspaceGateDigest(covers: readonly WorkspaceGateCover[]): string;
62
+ /** What a member gate asks about. */
63
+ export interface MemberGateQuery {
64
+ op: string;
65
+ gate: string;
66
+ planDigest: string;
67
+ environment?: string;
68
+ }
69
+ /**
70
+ * The rule of ws-039, pure: the newest approval that stands in for the
71
+ * member gate `q`, or null. Null whenever the member has not opted in.
72
+ */
73
+ export declare function workspaceGateStandsIn(q: MemberGateQuery, ctx: {
74
+ member: string;
75
+ optedIn: boolean;
76
+ approvals: readonly WorkspaceGateApproval[];
77
+ }): WorkspaceGateApproval | null;
78
+ /** A workspace gate's ledger, oldest first. */
79
+ export declare function readWorkspaceGate(cwd: string, gate: string): Promise<{
80
+ pending: WorkspaceGatePending[];
81
+ approvals: WorkspaceGateApproval[];
82
+ malformed: number;
83
+ }>;
84
+ export declare function appendWorkspaceGatePending(cwd: string, input: Omit<WorkspaceGatePending, "version" | "kind" | "digest" | "covers"> & {
85
+ covers: readonly WorkspaceGateCover[];
86
+ }): Promise<WorkspaceGatePending>;
87
+ /**
88
+ * Approve a workspace gate's pending fact: the newest one, or the one whose
89
+ * digest is `digest`. The approval copies its covers. Throws when there is no
90
+ * such fact.
91
+ */
92
+ export declare function approveWorkspaceGate(cwd: string, input: {
93
+ gate: string;
94
+ digest?: string;
95
+ approvedBy: string;
96
+ timestamp: string;
97
+ note?: string;
98
+ }): Promise<WorkspaceGateApproval>;
99
+ /**
100
+ * Whether the member holding `cwd` opts in to workspace gates at base, and
101
+ * its name. A member of a nested workspace, the root member and a directory
102
+ * no member owns never opt in.
103
+ */
104
+ export declare function memberAcceptsWorkspaceGates(cwd: string): Promise<{
105
+ member: string | null;
106
+ accepts: boolean;
107
+ }>;
108
+ /** The stand-in a member run started under workspace gate `gate` asks (`GateCheckInput.workspace`). */
109
+ export declare function memberGateStandIn(cwd: string, gate: string, q: MemberGateQuery): Promise<WorkspaceGateStood | null>;
110
+ //# sourceMappingURL=workspace-gates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-gates.d.ts","sourceRoot":"","sources":["../../src/workspace/workspace-gates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG,qBAAqB,CAAC;AAE7E,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,GAAG,kBAAkB,EAAE,CAKtF;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAEjF;AAED,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,eAAe,EAClB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,SAAS,qBAAqB,EAAE,CAAA;CAAE,GACrF,qBAAqB,GAAG,IAAI,CAc9B;AAkBD,+CAA+C;AAC/C,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAAC,SAAS,EAAE,qBAAqB,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAOtK;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC,GAAG;IAAE,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAKpN;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7F,OAAO,CAAC,qBAAqB,CAAC,CAuBhC;AAED;;;;GAIG;AACH,wBAAsB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CASnH;AAED,uGAAuG;AACvG,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAMzH"}