@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
@@ -0,0 +1,195 @@
1
+ /**
2
+ * `chant ledger <table>` (#4363): the rows of one ledger on `chant/lifecycle`
3
+ * as a JSON read contract (`workspace/ledger.schema.json`), filtered with
4
+ * `--where`, `--since` and `--at` instead of SQL.
5
+ *
6
+ * The tables, their columns and the rows are the ones `chant query` loads
7
+ * (`./query.ts` {@link QUERY_TABLES}, {@link loadQueryData}), so the two
8
+ * agree on every row. A column `chant query` keeps as JSON text is an object
9
+ * or array here. No SQL engine loads.
10
+ *
11
+ * `--since <time>` keeps the rows whose time column ({@link LEDGER_TIME_COLUMN})
12
+ * is at or after it. `--at <rev>` reads the ledger as the commit `rev` of
13
+ * `chant/lifecycle` held it ({@link revisionLedgerReadPort}).
14
+ *
15
+ * Everything here but {@link revisionLedgerReadPort} is pure over a
16
+ * {@link LedgerReadPort}, so a product that reads the branch its own way
17
+ * (terragucci, behold) supplies its own port.
18
+ */
19
+ import { execFileSync } from "node:child_process";
20
+ import { FilterError, matchesWhere, parseSince, parseWhere, type FilterFields, type FilterFieldType } from "../read-filter";
21
+ import type { ReasonCode } from "../workspace/reason-codes";
22
+ import type { LedgerReadPort } from "./ledger-port";
23
+ import { loadQueryData, QUERY_TABLES, type QueryLedger, type QueryRow, type QueryTable } from "./query";
24
+
25
+ /** The version of the `ledger` document this chant writes. */
26
+ export const LEDGER_READ_CONTRACT_VERSION = 1;
27
+
28
+ /** `$id` of the JSON Schema for `chant ledger --json`. */
29
+ export const LEDGER_READ_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/ledger/v1/ledger.schema.json";
30
+
31
+ /** The tables, in the order `chant query` lists them. */
32
+ export const LEDGER_TABLES = Object.keys(QUERY_TABLES) as QueryTable[];
33
+
34
+ /** The column `--since` compares, per table; null for a table with no time of its own. */
35
+ export const LEDGER_TIME_COLUMN: Record<QueryTable, string | null> = {
36
+ resources: "observed_at",
37
+ snapshots: "observed_at",
38
+ runs: "started",
39
+ gates: "timestamp",
40
+ deploys: "timestamp",
41
+ releases: null,
42
+ cuts: "timestamp",
43
+ };
44
+
45
+ /** The columns that hold JSON, which this read prints parsed. */
46
+ const JSON_COLUMNS = new Set(["attributes", "labels", "outcomes", "promoted_from", "restores", "redeploys", "artifacts"]);
47
+ /** The columns that hold an ISO instant. */
48
+ const TIME_COLUMNS = new Set(["last_updated", "observed_at", "started", "ended", "timestamp", "expires_at"]);
49
+ /** INTEGER columns that hold 0 or 1, which this read prints as booleans. */
50
+ const BOOLEAN_COLUMNS = new Set(["signed", "empty"]);
51
+
52
+ /** The fields `--where` takes on a table: its columns, typed. */
53
+ export function ledgerFields(table: QueryTable): FilterFields {
54
+ const out: Record<string, FilterFieldType> = {};
55
+ for (const [name, sqlType] of QUERY_TABLES[table]) {
56
+ out[name] = BOOLEAN_COLUMNS.has(name) ? "boolean" : sqlType === "INTEGER" ? "number" : JSON_COLUMNS.has(name) ? "json" : TIME_COLUMNS.has(name) ? "time" : "text";
57
+ }
58
+ return out;
59
+ }
60
+
61
+ export type LedgerValue = string | number | boolean | null | Record<string, unknown> | unknown[];
62
+ export type LedgerRow = Record<string, LedgerValue>;
63
+
64
+ /** The row as the contract prints it: JSON columns parsed, 0/1 columns as booleans. */
65
+ function contractRow(table: QueryTable, row: QueryRow): LedgerRow {
66
+ const out: LedgerRow = {};
67
+ for (const [name] of QUERY_TABLES[table]) {
68
+ const v = row[name] ?? null;
69
+ if (v !== null && JSON_COLUMNS.has(name) && typeof v === "string") {
70
+ try {
71
+ out[name] = JSON.parse(v) as LedgerValue;
72
+ } catch {
73
+ out[name] = v;
74
+ }
75
+ } else if (BOOLEAN_COLUMNS.has(name) && typeof v === "number") out[name] = v === 1;
76
+ else out[name] = v;
77
+ }
78
+ return out;
79
+ }
80
+
81
+ export interface LedgerReadOptions {
82
+ where?: readonly string[];
83
+ /** An ISO date or time, or a span back from now such as `7d`. */
84
+ since?: string;
85
+ /** The revision of `chant/lifecycle` the ports read, as given; only echoed here. */
86
+ at?: string | null;
87
+ now?: Date;
88
+ }
89
+
90
+ export type LedgerReadDocument =
91
+ | {
92
+ $schema: string;
93
+ contract: number;
94
+ table: QueryTable;
95
+ /** The table's columns, in order. */
96
+ columns: string[];
97
+ at: string | null;
98
+ filter: { where: string[]; since: string | null };
99
+ /** Rows in the table before the filter. */
100
+ total: number;
101
+ rows: LedgerRow[];
102
+ /** Lines and files of this table that could not be read as their kind, left out. */
103
+ malformed: number;
104
+ }
105
+ | { $schema: string; contract: number; error: { code: LedgerReadErrorCode; message: string } };
106
+
107
+ /** Why the read printed no rows. Closed. */
108
+ export const LEDGER_READ_ERROR_CODES = ["filter-invalid", "table-unknown", "revision-unknown", "ledger-unreadable"] as const satisfies readonly ReasonCode[];
109
+ export type LedgerReadErrorCode = (typeof LEDGER_READ_ERROR_CODES)[number];
110
+
111
+ const head = { $schema: LEDGER_READ_SCHEMA_ID, contract: LEDGER_READ_CONTRACT_VERSION };
112
+
113
+ /** A failure document. */
114
+ export function ledgerReadFailure(code: LedgerReadErrorCode, message: string): LedgerReadDocument {
115
+ return { ...head, error: { code, message } };
116
+ }
117
+
118
+ /** Read one table from the ledgers and filter it. A bad table or filter is a failure document, before anything is read. */
119
+ export async function readLedgerTable(table: string, ledgers: readonly QueryLedger[] | (() => Promise<readonly QueryLedger[]>), opts: LedgerReadOptions = {}): Promise<LedgerReadDocument> {
120
+ if (!(LEDGER_TABLES as string[]).includes(table)) return ledgerReadFailure("table-unknown", `no table ${JSON.stringify(table)}; the tables are ${LEDGER_TABLES.join(", ")}`);
121
+ const t = table as QueryTable;
122
+ let clauses;
123
+ let since: string | null = null;
124
+ try {
125
+ clauses = parseWhere(opts.where ?? [], ledgerFields(t), opts.now);
126
+ if (opts.since !== undefined) {
127
+ if (LEDGER_TIME_COLUMN[t] === null) throw new FilterError(`--since: ${t} has no time column; filter it with --where`);
128
+ since = parseSince(opts.since, opts.now);
129
+ }
130
+ } catch (err) {
131
+ if (err instanceof FilterError) return ledgerReadFailure("filter-invalid", err.message);
132
+ throw err;
133
+ }
134
+ const load = await loadQueryData(typeof ledgers === "function" ? await ledgers() : ledgers);
135
+ const all = load.data[t].map((r) => contractRow(t, r));
136
+ const timeCol = LEDGER_TIME_COLUMN[t];
137
+ const sinceMs = since === null ? null : Date.parse(since);
138
+ const rows = all.filter((r) => {
139
+ if (sinceMs !== null && timeCol !== null) {
140
+ const v = r[timeCol];
141
+ if (typeof v !== "string" || !(Date.parse(v) >= sinceMs)) return false;
142
+ }
143
+ return matchesWhere(r, clauses);
144
+ });
145
+ return {
146
+ ...head,
147
+ table: t,
148
+ columns: QUERY_TABLES[t].map(([c]) => c),
149
+ at: opts.at ?? null,
150
+ filter: { where: [...(opts.where ?? [])], since },
151
+ total: all.length,
152
+ rows,
153
+ malformed: load.malformed[t],
154
+ };
155
+ }
156
+
157
+ /** Thrown by {@link resolveLedgerRevision} for a revision git can't resolve. */
158
+ export class LedgerRevisionError extends Error {}
159
+
160
+ /** The commit `rev` names in the repository at `cwd`. Throws a {@link LedgerRevisionError}. */
161
+ export function resolveLedgerRevision(cwd: string, rev: string): string {
162
+ try {
163
+ return execFileSync("git", ["rev-parse", "--verify", "--quiet", `${rev}^{commit}`], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim();
164
+ } catch {
165
+ throw new LedgerRevisionError(`--at ${rev} names no commit here; give a commit of chant/lifecycle, such as chant/lifecycle~3`);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * A port over the ledger as the commit `commit` holds it, under `prefix`
171
+ * (`""`, or `_members/<member>/` per level). It never fetches.
172
+ */
173
+ export function revisionLedgerReadPort(cwd: string, commit: string, prefix: string): LedgerReadPort {
174
+ const git = (args: string[]): string | null => {
175
+ try {
176
+ return execFileSync("git", args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 256 * 1024 * 1024 });
177
+ } catch {
178
+ return null;
179
+ }
180
+ };
181
+ const lsTree = (path: string, nameOnly: boolean): string[] => {
182
+ const spec = path === "" ? commit : `${commit}:${path}`;
183
+ const out = git(["ls-tree", "--full-tree", ...(nameOnly ? ["--name-only"] : []), spec]);
184
+ return out === null ? [] : out.split("\n").filter(Boolean);
185
+ };
186
+ return {
187
+ read: async (dir, file) => git(["show", `${commit}:${prefix}${dir}/${file}`]),
188
+ list: async (dir) => lsTree(`${prefix}${dir}`, true),
189
+ trees: async () =>
190
+ lsTree(prefix.replace(/\/$/, ""), false)
191
+ .map((line) => /^\d+\s+(\w+)\s+[0-9a-f]+\t(.+)$/.exec(line))
192
+ .filter((m): m is RegExpExecArray => m !== null && m[1] === "tree")
193
+ .map((m) => m[2]),
194
+ };
195
+ }
@@ -70,6 +70,30 @@ export function resolveTrunk(cwd: string, greenBranch: string | null): Trunk {
70
70
  return { remote: RELEASE_REMOTE, branch: "main", from: "default" };
71
71
  }
72
72
 
73
+ /**
74
+ * {@link checkOnTrunk} across the branches `ci.green` judges (#4325): the
75
+ * trunk `commit` is on, `trunk` itself or one of `others` (the declaration's
76
+ * further green branches, which `ci.branches` routes members to). A commit on
77
+ * none of them is refused with the first trunk's error.
78
+ */
79
+ export function checkOnGreenBranches(cwd: string, commit: string, trunk: Trunk, others: readonly string[]): Trunk {
80
+ try {
81
+ checkOnTrunk(cwd, commit, trunk);
82
+ return trunk;
83
+ } catch (err) {
84
+ for (const branch of others) {
85
+ const routed: Trunk = { ...trunk, branch };
86
+ try {
87
+ checkOnTrunk(cwd, commit, routed);
88
+ return routed;
89
+ } catch {
90
+ // Not on this one either; the next, then the first branch's error.
91
+ }
92
+ }
93
+ throw err;
94
+ }
95
+ }
96
+
73
97
  /**
74
98
  * Refuse `commit` unless it is reachable from `<remote>/<branch>` as this
75
99
  * clone knows it. A commit on the local branch only is `release-commit-not-pushed`;
@@ -39,7 +39,7 @@ import { sortedJsonReplacer } from "../utils";
39
39
  import type { OpConfig } from "../op/types";
40
40
  import type { StepRecord } from "../op/local-executor";
41
41
  import { opRunFailureOf, type OpRunRecord, type OpRunRecordInput, type OpRunPhaseRecord, type OpRunStepRecord } from "../op/runtime";
42
- import { readBlobFromPath, readPathSha, readBlobBySha, writeBlobToPath, RefCASConflictError } from "./git";
42
+ import { readBlobFromPath, readPathSha, readBlobBySha, writeBlobToPath, RefCASConflictError, type LedgerLocation } from "./git";
43
43
 
44
44
  /** Prefix folding the per-op run ledgers into one flat name under `<env>/`. See the module doc. */
45
45
  const PREFIX = "runs__";
@@ -95,6 +95,8 @@ export function buildRunRecord(
95
95
  runOrigin?: OpRunRecord["runOrigin"];
96
96
  /** Each phase's wall-clock time, by name, as the executor measured it. */
97
97
  phaseDurations?: Record<string, number>;
98
+ /** The workspace run that started this one (#2554). */
99
+ workspaceRun?: OpRunRecord["workspaceRun"];
98
100
  },
99
101
  ): OpRunRecordInput {
100
102
  const phases: OpRunPhaseRecord[] = [];
@@ -145,6 +147,7 @@ export function buildRunRecord(
145
147
  ...(times.resumed ? { resumed: times.resumed } : {}),
146
148
  ...(times.gitSha ? { gitSha: times.gitSha } : {}),
147
149
  ...(times.runOrigin ? { runOrigin: times.runOrigin } : {}),
150
+ ...(times.workspaceRun ? { workspaceRun: times.workspaceRun } : {}),
148
151
  };
149
152
  }
150
153
 
@@ -193,7 +196,7 @@ export async function appendRunRecord(
193
196
  export async function readRunLedger(
194
197
  environment: string,
195
198
  op: string,
196
- opts?: { cwd?: string },
199
+ opts?: LedgerLocation,
197
200
  ): Promise<{ records: OpRunRecord[]; malformed: number }> {
198
201
  const content = await readBlobFromPath(environment, fileFor(op), opts);
199
202
  if (!content) return { records: [], malformed: 0 };
@@ -0,0 +1,122 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import {
3
+ runPostSynthChecks,
4
+ runCrossRootChecks,
5
+ createCrossRootContext,
6
+ isPostSynthCheck,
7
+ isCrossRootCheck,
8
+ type CrossRootCheck,
9
+ type CrossRootInput,
10
+ type PostSynthCheck,
11
+ } from "./post-synth";
12
+
13
+ function buildResult(outputs: Record<string, string> = {}, entities: Record<string, unknown> = {}) {
14
+ const out = new Map(Object.entries(outputs));
15
+ return {
16
+ outputs: out,
17
+ entities: new Map(Object.entries(entities)) as Map<string, never>,
18
+ warnings: [] as string[],
19
+ errors: [] as Array<{ message: string; name: string }>,
20
+ sourceFileCount: 0,
21
+ };
22
+ }
23
+
24
+ const secretRoot: CrossRootInput = {
25
+ root: "workloads",
26
+ buildResult: buildResult({ k8s: "kind: Secret\nmetadata:\n name: db\n" }, { dbSecret: {} }),
27
+ };
28
+ const fluxRoot: CrossRootInput = {
29
+ root: "flux",
30
+ dir: "/repo/flux",
31
+ buildResult: buildResult({ k8s: "kind: Kustomization\nmetadata:\n name: apps\n---\nkind: GitRepository\n" }),
32
+ };
33
+
34
+ const kindsAcross: CrossRootCheck = {
35
+ id: "XR001",
36
+ description: "records kinds across roots",
37
+ scope: "cross-root",
38
+ check(ctx) {
39
+ return ctx.docs.map((d) => ({
40
+ checkId: "XR001",
41
+ severity: "info" as const,
42
+ message: String((d.value as { kind?: string }).kind),
43
+ root: d.root,
44
+ }));
45
+ },
46
+ };
47
+
48
+ describe("cross-root post-synth checks (chant #1939)", () => {
49
+ test("a per-build run never calls a cross-root check", () => {
50
+ let called = false;
51
+ const xr = { ...kindsAcross, check: () => { called = true; return []; } };
52
+ const diags = runPostSynthChecks([xr as unknown as PostSynthCheck], buildResult());
53
+ expect(diags).toEqual([]);
54
+ expect(called).toBe(false);
55
+ });
56
+
57
+ test("guards keep the two kinds apart", () => {
58
+ const plain: PostSynthCheck = { id: "P", description: "p", check: () => [] };
59
+ expect(isPostSynthCheck(kindsAcross)).toBe(false);
60
+ expect(isCrossRootCheck(kindsAcross)).toBe(true);
61
+ expect(isPostSynthCheck(plain)).toBe(true);
62
+ expect(isCrossRootCheck(plain)).toBe(false);
63
+ });
64
+
65
+ test("docs are the union across roots, tagged by root", () => {
66
+ const diags = runCrossRootChecks([kindsAcross], [secretRoot, fluxRoot]);
67
+ expect(diags.map((d) => `${d.root}:${d.message}`)).toEqual([
68
+ "workloads:Secret",
69
+ "flux:Kustomization",
70
+ "flux:GitRepository",
71
+ ]);
72
+ });
73
+
74
+ test("a cross-root check can see that the other half lives in another root", () => {
75
+ const needsDecryption: CrossRootCheck = {
76
+ id: "XR002",
77
+ description: "a Secret needs a Kustomization in some root",
78
+ scope: "cross-root",
79
+ check(ctx) {
80
+ const hasKs = ctx.docs.some((d) => (d.value as { kind?: string }).kind === "Kustomization");
81
+ return ctx.docs
82
+ .filter((d) => (d.value as { kind?: string }).kind === "Secret" && !hasKs)
83
+ .map((d) => ({ checkId: "XR002", severity: "warning" as const, message: "no Kustomization in any root", root: d.root }));
84
+ },
85
+ };
86
+ expect(runCrossRootChecks([needsDecryption], [secretRoot, fluxRoot])).toEqual([]);
87
+ expect(runCrossRootChecks([needsDecryption], [secretRoot])).toEqual([
88
+ { checkId: "XR002", severity: "warning", message: "no Kustomization in any root", root: "workloads" },
89
+ ]);
90
+ });
91
+
92
+ test("roots stay apart and each is a PostSynthContext", () => {
93
+ const ctx = createCrossRootContext([secretRoot, fluxRoot], { env: "prod" });
94
+ expect(ctx.roots.map((r) => r.root)).toEqual(["workloads", "flux"]);
95
+ expect(ctx.root("flux")?.dir).toBe("/repo/flux");
96
+ expect(ctx.root("flux")?.projectDir).toBe("/repo/flux");
97
+ expect(ctx.root("flux")?.docs).toHaveLength(2);
98
+ expect(ctx.root("workloads")?.env).toBe("prod");
99
+ expect(ctx.root("missing")).toBeUndefined();
100
+ expect(ctx.entities).toEqual([{ root: "workloads", name: "dbSecret", entity: {} }]);
101
+ expect(ctx.env).toBe("prod");
102
+ });
103
+
104
+ test("the union is parsed lazily, once", () => {
105
+ const ctx = createCrossRootContext([secretRoot, fluxRoot]);
106
+ expect(ctx.docs).toBe(ctx.docs);
107
+ expect(ctx.entities).toBe(ctx.entities);
108
+ });
109
+
110
+ test("plain checks in the list are skipped, and nothing is built when none is cross-root", () => {
111
+ let called = false;
112
+ const plain: PostSynthCheck = { id: "P", description: "p", check: () => { called = true; return []; } };
113
+ // Duplicate root names would throw if a context were built.
114
+ expect(runCrossRootChecks([plain], [secretRoot, secretRoot])).toEqual([]);
115
+ expect(called).toBe(false);
116
+ });
117
+
118
+ test("root names must be unique and non-empty", () => {
119
+ expect(() => createCrossRootContext([secretRoot, secretRoot])).toThrow(/appears twice/);
120
+ expect(() => createCrossRootContext([{ ...secretRoot, root: "" }])).toThrow(/needs a name/);
121
+ });
122
+ });
@@ -143,6 +143,8 @@ function isPostSynthCheck(obj: unknown): obj is PostSynthCheck {
143
143
  typeof o.description === "string" &&
144
144
  typeof o.check === "function" &&
145
145
  // Exclude LintRules (which also have check) by checking for PostSynthCheck-specific fields
146
- typeof o.severity !== "string"
146
+ typeof o.severity !== "string" &&
147
+ // A cross-root check (chant #1939) is not a per-build check.
148
+ o.scope !== "cross-root"
147
149
  );
148
150
  }
@@ -192,6 +192,11 @@ export interface PostSynthDiagnostic {
192
192
  /** Where it is missing from (e.g. a root module name). */
193
193
  scope: string;
194
194
  };
195
+ /**
196
+ * The build root the finding is about, set by a {@link CrossRootCheck}
197
+ * (chant #1939). Absent from a per-build finding.
198
+ */
199
+ root?: string;
195
200
  }
196
201
 
197
202
  /**
@@ -214,16 +219,26 @@ export interface PostSynthCheck {
214
219
  * new check would otherwise change the audit output of every project.
215
220
  */
216
221
  auditOptIn?: boolean;
222
+ /**
223
+ * `"build"`, the default: the check sees one build. A check that reads
224
+ * across build roots is a {@link CrossRootCheck} instead (chant #1939).
225
+ */
226
+ scope?: "build";
217
227
  }
218
228
 
219
- /** Structural type guard — used to collect project-authored policy checks. */
229
+ /**
230
+ * Structural type guard — used to collect project-authored policy checks.
231
+ * A {@link CrossRootCheck} is not a `PostSynthCheck`, so a policy module or a
232
+ * lexicon's check directory that exports one never puts it in a per-build run.
233
+ */
220
234
  export function isPostSynthCheck(value: unknown): value is PostSynthCheck {
221
235
  return (
222
236
  typeof value === "object" &&
223
237
  value !== null &&
224
238
  typeof (value as PostSynthCheck).id === "string" &&
225
239
  typeof (value as PostSynthCheck).description === "string" &&
226
- typeof (value as PostSynthCheck).check === "function"
240
+ typeof (value as PostSynthCheck).check === "function" &&
241
+ (value as { scope?: unknown }).scope !== "cross-root"
227
242
  );
228
243
  }
229
244
 
@@ -259,11 +274,206 @@ export function runPostSynthChecks(
259
274
 
260
275
  const diagnostics: PostSynthDiagnostic[] = [];
261
276
  for (const check of checks) {
277
+ // chant #1939: a cross-root check never runs in a per-build pass, even
278
+ // when a caller hands one over untyped. runCrossRootChecks runs it.
279
+ if ((check as { scope?: unknown }).scope === "cross-root") continue;
262
280
  diagnostics.push(...check.check(ctx));
263
281
  }
264
282
  return diagnostics;
265
283
  }
266
284
 
285
+ // ---------------------------------------------------------------------------
286
+ // Cross-build-root mode (chant #1939)
287
+ // ---------------------------------------------------------------------------
288
+
289
+ /**
290
+ * One build root handed to {@link runCrossRootChecks}: a name, and the build
291
+ * result the caller already has for it. The caller decides what a root is
292
+ * (a workspace member, a project directory, an environment's build) and
293
+ * builds it; this module never builds or reads the disk.
294
+ */
295
+ export interface CrossRootInput {
296
+ /**
297
+ * The root's name, unique within one run. A workspace member's name, or a
298
+ * project-relative path. Findings name it in {@link PostSynthDiagnostic.root}.
299
+ */
300
+ root: string;
301
+ /** The root's directory, when it has one. */
302
+ dir?: string;
303
+ /** The environment this root was built for, when known. */
304
+ env?: string;
305
+ buildResult: PostSynthContext["buildResult"];
306
+ projectConfig?: Record<string, unknown>;
307
+ }
308
+
309
+ /**
310
+ * One build root as a cross-root check sees it: an ordinary
311
+ * {@link PostSynthContext} over that root's build, so a per-build helper
312
+ * (k8s's `allManifests(ctx)`) works on it unchanged, plus its name.
313
+ */
314
+ export interface BuildRootView extends PostSynthContext {
315
+ readonly root: string;
316
+ readonly dir?: string;
317
+ readonly docs: OutputDoc[];
318
+ }
319
+
320
+ /** An {@link OutputDoc} tagged with the build root it came from. */
321
+ export interface RootedOutputDoc extends OutputDoc {
322
+ root: string;
323
+ }
324
+
325
+ /**
326
+ * A link between two build roots, as the caller knows it (chant #2549): in a
327
+ * workspace, a member link from the declaration or one the members' graphs
328
+ * surface. A cross-root check that compares what the outputs say with what
329
+ * was written down reads these from {@link CrossRootContext.links}.
330
+ */
331
+ export interface CrossRootLink {
332
+ consumer: string;
333
+ producer: string;
334
+ output: string;
335
+ /** How the link was found: `declared`, `kind-reader`, or `inferred:<rule>` for one the roots' graphs surface. */
336
+ origin: string;
337
+ /** The consumer's parameter an inferred link feeds; null or absent for a declared one. */
338
+ input?: string | null;
339
+ /** Whether the link resolved against the producer's outputs, as the caller judged it. */
340
+ status?: string;
341
+ }
342
+
343
+ /** An entity tagged with the build root that declared it. */
344
+ export interface RootedEntity {
345
+ root: string;
346
+ name: string;
347
+ entity: Declarable;
348
+ }
349
+
350
+ /**
351
+ * Context provided to a {@link CrossRootCheck}. `roots` keeps every root's
352
+ * build apart; `docs` and `entities` are the union across roots, each entry
353
+ * tagged with its root, built lazily on first access.
354
+ */
355
+ export interface CrossRootContext {
356
+ /** Every root in the run, in the order the caller gave them. */
357
+ readonly roots: readonly BuildRootView[];
358
+ /** Look a root up by name. */
359
+ root(name: string): BuildRootView | undefined;
360
+ /** Every root's parsed output documents, tagged by root. Lazy. */
361
+ readonly docs: readonly RootedOutputDoc[];
362
+ /** Every root's entities, tagged by root. Lazy. */
363
+ readonly entities: readonly RootedEntity[];
364
+ /** The run's environment, when the caller set one for the whole run. */
365
+ readonly env?: string;
366
+ readonly activityContracts?: ReadonlyMap<string, ActivityContract>;
367
+ /** The links between roots the caller passed (#2549), or absent when it passed none. */
368
+ readonly links?: readonly CrossRootLink[];
369
+ }
370
+
371
+ /** What a cross-root run takes besides its roots. */
372
+ export interface CrossRootOptions {
373
+ env?: string;
374
+ activityContracts?: ReadonlyMap<string, ActivityContract>;
375
+ /** The links between roots (#2549), handed to every check as {@link CrossRootContext.links}. */
376
+ links?: readonly CrossRootLink[];
377
+ }
378
+
379
+ /**
380
+ * A check that reads across build roots (chant #1939). It declares
381
+ * `scope: "cross-root"`, and only {@link runCrossRootChecks} runs it:
382
+ * `chant build`, `chant lint` and every other per-build pass skip it, so a
383
+ * project that never asks for a cross-root run pays nothing for it.
384
+ */
385
+ export interface CrossRootCheck {
386
+ id: string;
387
+ description: string;
388
+ scope: "cross-root";
389
+ check(ctx: CrossRootContext): PostSynthDiagnostic[];
390
+ /** As {@link PostSynthCheck.auditOptIn}. */
391
+ auditOptIn?: boolean;
392
+ }
393
+
394
+ /** Structural type guard for {@link CrossRootCheck}. */
395
+ export function isCrossRootCheck(value: unknown): value is CrossRootCheck {
396
+ return (
397
+ typeof value === "object" &&
398
+ value !== null &&
399
+ typeof (value as CrossRootCheck).id === "string" &&
400
+ typeof (value as CrossRootCheck).description === "string" &&
401
+ typeof (value as CrossRootCheck).check === "function" &&
402
+ (value as CrossRootCheck).scope === "cross-root"
403
+ );
404
+ }
405
+
406
+ /**
407
+ * Build the {@link CrossRootContext} for a set of roots. Exported for tests
408
+ * and for a caller that runs checks itself; most callers want
409
+ * {@link runCrossRootChecks}. Throws on an empty or duplicate root name.
410
+ */
411
+ export function createCrossRootContext(
412
+ inputs: readonly CrossRootInput[],
413
+ opts?: CrossRootOptions,
414
+ ): CrossRootContext {
415
+ const seen = new Set<string>();
416
+ const roots: BuildRootView[] = inputs.map((input) => {
417
+ if (input.root.length === 0) throw new Error("cross-root run: a build root needs a name");
418
+ if (seen.has(input.root)) throw new Error(`cross-root run: build root "${input.root}" appears twice`);
419
+ seen.add(input.root);
420
+ const getDocs = createDocsAccessor(input.buildResult.outputs);
421
+ const env = input.env ?? opts?.env;
422
+ return {
423
+ root: input.root,
424
+ ...(input.dir ? { dir: input.dir, projectDir: input.dir } : {}),
425
+ outputs: input.buildResult.outputs,
426
+ entities: input.buildResult.entities,
427
+ env,
428
+ buildResult: input.buildResult,
429
+ ...(opts?.activityContracts ? { activityContracts: opts.activityContracts } : {}),
430
+ ...(input.projectConfig ? { projectConfig: input.projectConfig } : {}),
431
+ get docs(): OutputDoc[] {
432
+ return getDocs();
433
+ },
434
+ };
435
+ });
436
+ const byName = new Map(roots.map((r) => [r.root, r]));
437
+ let docs: RootedOutputDoc[] | undefined;
438
+ let entities: RootedEntity[] | undefined;
439
+ return {
440
+ roots,
441
+ root: (name) => byName.get(name),
442
+ get docs(): readonly RootedOutputDoc[] {
443
+ docs ??= roots.flatMap((r) => r.docs.map((d) => ({ ...d, root: r.root })));
444
+ return docs;
445
+ },
446
+ get entities(): readonly RootedEntity[] {
447
+ entities ??= roots.flatMap((r) =>
448
+ [...r.entities].map(([name, entity]) => ({ root: r.root, name, entity })),
449
+ );
450
+ return entities;
451
+ },
452
+ ...(opts?.env ? { env: opts.env } : {}),
453
+ ...(opts?.activityContracts ? { activityContracts: opts.activityContracts } : {}),
454
+ ...(opts?.links ? { links: opts.links } : {}),
455
+ };
456
+ }
457
+
458
+ /**
459
+ * Run the cross-root checks in `checks` over `roots` (chant #1939). Anything
460
+ * in `checks` that is not a {@link CrossRootCheck} is skipped, so a caller can
461
+ * pass a lexicon's whole check list. With no cross-root check to run it
462
+ * returns at once, without building a context.
463
+ */
464
+ export function runCrossRootChecks(
465
+ checks: ReadonlyArray<CrossRootCheck | PostSynthCheck>,
466
+ roots: readonly CrossRootInput[],
467
+ opts?: CrossRootOptions,
468
+ ): PostSynthDiagnostic[] {
469
+ const selected = checks.filter(isCrossRootCheck);
470
+ if (selected.length === 0) return [];
471
+ const ctx = createCrossRootContext(roots, opts);
472
+ const diagnostics: PostSynthDiagnostic[] = [];
473
+ for (const check of selected) diagnostics.push(...check.check(ctx));
474
+ return diagnostics;
475
+ }
476
+
267
477
  // chant #1138 — `applyConfiguredSeverity` (the `lint.rules` severity-override
268
478
  // pass over a set of `PostSynthDiagnostic`s) lives in `./config.ts`, not here,
269
479
  // even though it operates on this module's own type. This file is a leaf:
@@ -28,6 +28,8 @@ export { ops016 } from "./ops016-gate-resume";
28
28
  export { ops017, ops017Check, workspaceIdentityGates } from "./ops017-gate-alias";
29
29
  export { ops018 } from "./ops018-shell-image-digest";
30
30
  export { sys010, sys010Check } from "./sys010-key-over-plain-http";
31
+ // OPS019 (#2554) reads across members, so it is a cross-root check that only `chant workspace run` runs.
32
+ export { ops019Check, parseWorkspaceOpTarget, formatWorkspaceOpTarget, OPS019_ID, type WorkspaceOpTarget } from "./ops019-workspace-op-target";
31
33
 
32
34
  export interface CoreOpCheckOptions {
33
35
  /** `decide.backends` from the project's chant.config, for SYS010 (#2828). */