@intentius/chant 0.124.46 → 0.124.49

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 (726) 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 +41 -14
  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/graph-reader.d.ts +26 -0
  63. package/dist/cli/handlers/graph-reader.d.ts.map +1 -0
  64. package/dist/cli/handlers/graph-reader.js +41 -0
  65. package/dist/cli/handlers/graph.d.ts.map +1 -1
  66. package/dist/cli/handlers/graph.js +14 -0
  67. package/dist/cli/handlers/ledger.d.ts +3 -0
  68. package/dist/cli/handlers/ledger.d.ts.map +1 -0
  69. package/dist/cli/handlers/ledger.js +55 -0
  70. package/dist/cli/handlers/migrate.d.ts.map +1 -1
  71. package/dist/cli/handlers/migrate.js +18 -11
  72. package/dist/cli/handlers/misc.d.ts.map +1 -1
  73. package/dist/cli/handlers/misc.js +12 -1
  74. package/dist/cli/handlers/pr-env.js +2 -2
  75. package/dist/cli/handlers/pr.d.ts +15 -1
  76. package/dist/cli/handlers/pr.d.ts.map +1 -1
  77. package/dist/cli/handlers/pr.js +183 -40
  78. package/dist/cli/handlers/query.d.ts +7 -2
  79. package/dist/cli/handlers/query.d.ts.map +1 -1
  80. package/dist/cli/handlers/query.js +16 -4
  81. package/dist/cli/handlers/release.d.ts.map +1 -1
  82. package/dist/cli/handlers/release.js +6 -3
  83. package/dist/cli/handlers/search.d.ts +2 -4
  84. package/dist/cli/handlers/search.d.ts.map +1 -1
  85. package/dist/cli/handlers/search.js +13 -39
  86. package/dist/cli/main.d.ts.map +1 -1
  87. package/dist/cli/main.js +87 -14
  88. package/dist/cli/parse-args.d.ts.map +1 -1
  89. package/dist/cli/parse-args.js +47 -2
  90. package/dist/cli/registry.d.ts +22 -4
  91. package/dist/cli/registry.d.ts.map +1 -1
  92. package/dist/components/builders.d.ts +5 -1
  93. package/dist/components/builders.d.ts.map +1 -1
  94. package/dist/components/builders.js +5 -0
  95. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  96. package/dist/components/capability-plugin-loader.js +16 -1
  97. package/dist/components/capability-plugin.d.ts +14 -0
  98. package/dist/components/capability-plugin.d.ts.map +1 -1
  99. package/dist/components/pr-hooks.d.ts +21 -1
  100. package/dist/components/pr-hooks.d.ts.map +1 -1
  101. package/dist/components/pr-hooks.js +72 -4
  102. package/dist/components/pr-pipeline.d.ts +45 -10
  103. package/dist/components/pr-pipeline.d.ts.map +1 -1
  104. package/dist/components/pr-pipeline.js +47 -14
  105. package/dist/components/pr-policy.d.ts +36 -0
  106. package/dist/components/pr-policy.d.ts.map +1 -1
  107. package/dist/components/pr-policy.js +36 -0
  108. package/dist/components/pr-run.d.ts +3 -0
  109. package/dist/components/pr-run.d.ts.map +1 -1
  110. package/dist/components/pr-run.js +1 -0
  111. package/dist/components/starter-plugin.d.ts +1 -0
  112. package/dist/components/starter-plugin.d.ts.map +1 -1
  113. package/dist/components/starter-plugin.js +5 -1
  114. package/dist/components/verbs/index.d.ts +2 -0
  115. package/dist/components/verbs/index.d.ts.map +1 -1
  116. package/dist/components/verbs/index.js +2 -0
  117. package/dist/components/verbs/publish-artifact.d.ts +65 -0
  118. package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
  119. package/dist/components/verbs/publish-artifact.js +74 -0
  120. package/dist/components/verbs/publish-image.d.ts +129 -0
  121. package/dist/components/verbs/publish-image.d.ts.map +1 -0
  122. package/dist/components/verbs/publish-image.js +145 -0
  123. package/dist/config-environments.d.ts +20 -0
  124. package/dist/config-environments.d.ts.map +1 -1
  125. package/dist/config-environments.js +12 -0
  126. package/dist/config.d.ts +25 -1
  127. package/dist/config.d.ts.map +1 -1
  128. package/dist/config.js +10 -2
  129. package/dist/gate-decision.d.ts +20 -2
  130. package/dist/gate-decision.d.ts.map +1 -1
  131. package/dist/gate-decision.js +30 -3
  132. package/dist/graph-ir.d.ts +25 -0
  133. package/dist/graph-ir.d.ts.map +1 -1
  134. package/dist/graph-walk.d.ts +66 -0
  135. package/dist/graph-walk.d.ts.map +1 -0
  136. package/dist/graph-walk.js +70 -0
  137. package/dist/import/parser.d.ts +19 -0
  138. package/dist/import/parser.d.ts.map +1 -1
  139. package/dist/lexicon.d.ts +94 -6
  140. package/dist/lexicon.d.ts.map +1 -1
  141. package/dist/lifecycle/gate-ledger.d.ts +11 -0
  142. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  143. package/dist/lifecycle/git.d.ts +2 -5
  144. package/dist/lifecycle/git.d.ts.map +1 -1
  145. package/dist/lifecycle/ledger-read.d.ts +65 -0
  146. package/dist/lifecycle/ledger-read.d.ts.map +1 -0
  147. package/dist/lifecycle/ledger-read.js +160 -0
  148. package/dist/lifecycle/release-workstation.d.ts +7 -0
  149. package/dist/lifecycle/release-workstation.d.ts.map +1 -1
  150. package/dist/lifecycle/release-workstation.js +25 -0
  151. package/dist/lifecycle/run-ledger.d.ts +4 -3
  152. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  153. package/dist/lifecycle/run-ledger.js +1 -0
  154. package/dist/lint/discover.js +3 -1
  155. package/dist/lint/post-synth.d.ts +127 -1
  156. package/dist/lint/post-synth.d.ts.map +1 -1
  157. package/dist/lint/post-synth.js +84 -2
  158. package/dist/lint/rules/op/index.d.ts +1 -0
  159. package/dist/lint/rules/op/index.d.ts.map +1 -1
  160. package/dist/lint/rules/op/index.js +2 -0
  161. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
  162. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
  163. package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
  164. package/dist/op/activities/activity-contracts.d.ts +9 -6
  165. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  166. package/dist/op/activities/activity-contracts.js +5 -2
  167. package/dist/op/activities/index.d.ts +2 -2
  168. package/dist/op/activities/index.d.ts.map +1 -1
  169. package/dist/op/activities/index.js +1 -1
  170. package/dist/op/activities/review-agent.d.ts +90 -4
  171. package/dist/op/activities/review-agent.d.ts.map +1 -1
  172. package/dist/op/activities/review-agent.js +217 -19
  173. package/dist/op/activities/work-evidence.d.ts +8 -1
  174. package/dist/op/activities/work-evidence.d.ts.map +1 -1
  175. package/dist/op/activities/work-evidence.js +1 -0
  176. package/dist/op/builders.d.ts +9 -5
  177. package/dist/op/builders.d.ts.map +1 -1
  178. package/dist/op/builders.js +9 -5
  179. package/dist/op/composites/apply-op.d.ts +29 -2
  180. package/dist/op/composites/apply-op.d.ts.map +1 -1
  181. package/dist/op/composites/apply-op.js +20 -1
  182. package/dist/op/gate-approval-base.d.ts +25 -0
  183. package/dist/op/gate-approval-base.d.ts.map +1 -0
  184. package/dist/op/gate-approval-base.js +71 -0
  185. package/dist/op/gate-approval.d.ts +18 -9
  186. package/dist/op/gate-approval.d.ts.map +1 -1
  187. package/dist/op/gate-approval.js +13 -31
  188. package/dist/op/gate-name.d.ts +13 -0
  189. package/dist/op/gate-name.d.ts.map +1 -1
  190. package/dist/op/gate-name.js +14 -1
  191. package/dist/op/gate-quorum.d.ts +100 -3
  192. package/dist/op/gate-quorum.d.ts.map +1 -1
  193. package/dist/op/gate-quorum.js +108 -6
  194. package/dist/op/gate-review.d.ts +9 -0
  195. package/dist/op/gate-review.d.ts.map +1 -1
  196. package/dist/op/gate-review.js +13 -0
  197. package/dist/op/gate.d.ts +47 -5
  198. package/dist/op/gate.d.ts.map +1 -1
  199. package/dist/op/gate.js +25 -4
  200. package/dist/op/index.d.ts +3 -3
  201. package/dist/op/index.d.ts.map +1 -1
  202. package/dist/op/index.js +1 -1
  203. package/dist/op/local-executor.d.ts +45 -3
  204. package/dist/op/local-executor.d.ts.map +1 -1
  205. package/dist/op/local-executor.js +68 -7
  206. package/dist/op/op-waves-run.d.ts +26 -1
  207. package/dist/op/op-waves-run.d.ts.map +1 -1
  208. package/dist/op/op-waves-run.js +259 -13
  209. package/dist/op/op-waves.d.ts +72 -5
  210. package/dist/op/op-waves.d.ts.map +1 -1
  211. package/dist/op/op-waves.js +110 -15
  212. package/dist/op/runtime.d.ts +11 -0
  213. package/dist/op/runtime.d.ts.map +1 -1
  214. package/dist/op/schedule-overdue.d.ts +16 -0
  215. package/dist/op/schedule-overdue.d.ts.map +1 -1
  216. package/dist/op/schedule-overdue.js +36 -0
  217. package/dist/op/stage-hooks.d.ts +9 -2
  218. package/dist/op/stage-hooks.d.ts.map +1 -1
  219. package/dist/op/stage-hooks.js +7 -5
  220. package/dist/op/workspace-run-env.d.ts +22 -0
  221. package/dist/op/workspace-run-env.d.ts.map +1 -0
  222. package/dist/op/workspace-run-env.js +21 -0
  223. package/dist/pr-forge.d.ts +24 -0
  224. package/dist/pr-forge.d.ts.map +1 -1
  225. package/dist/pr-forge.js +47 -0
  226. package/dist/pr-loop.d.ts +10 -0
  227. package/dist/pr-loop.d.ts.map +1 -1
  228. package/dist/pr-loop.js +4 -0
  229. package/dist/pr-migrations.d.ts +62 -0
  230. package/dist/pr-migrations.d.ts.map +1 -0
  231. package/dist/pr-migrations.js +50 -0
  232. package/dist/pr-post.d.ts +42 -0
  233. package/dist/pr-post.d.ts.map +1 -1
  234. package/dist/pr-post.js +68 -2
  235. package/dist/read-filter.d.ts +65 -0
  236. package/dist/read-filter.d.ts.map +1 -0
  237. package/dist/read-filter.js +179 -0
  238. package/dist/run-event.d.ts +1 -1
  239. package/dist/run-event.d.ts.map +1 -1
  240. package/dist/terraform/carve.d.ts +24 -3
  241. package/dist/terraform/carve.d.ts.map +1 -1
  242. package/dist/terraform/carve.js +32 -14
  243. package/dist/terraform/cuts.d.ts +97 -0
  244. package/dist/terraform/cuts.d.ts.map +1 -0
  245. package/dist/terraform/cuts.js +138 -0
  246. package/dist/terraform/folds.d.ts +26 -0
  247. package/dist/terraform/folds.d.ts.map +1 -0
  248. package/dist/terraform/folds.js +38 -0
  249. package/dist/terraform/graph.d.ts.map +1 -1
  250. package/dist/terraform/graph.js +10 -0
  251. package/dist/terraform/reach.d.ts +140 -0
  252. package/dist/terraform/reach.d.ts.map +1 -0
  253. package/dist/terraform/reach.js +170 -0
  254. package/dist/terraform/score.d.ts +14 -0
  255. package/dist/terraform/score.d.ts.map +1 -1
  256. package/dist/terraform/score.js +14 -31
  257. package/dist/terraform/state.d.ts.map +1 -1
  258. package/dist/terraform/state.js +4 -2
  259. package/dist/terraform/types.d.ts +8 -0
  260. package/dist/terraform/types.d.ts.map +1 -1
  261. package/dist/wave-blocked.d.ts +10 -1
  262. package/dist/wave-blocked.d.ts.map +1 -1
  263. package/dist/wave-blocked.js +31 -3
  264. package/dist/wave-runtime.mjs +264 -254
  265. package/dist/workspace/check.schema.json +13 -2
  266. package/dist/workspace/checks/ci-branch.d.ts +44 -0
  267. package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
  268. package/dist/workspace/checks/ci-branch.js +133 -0
  269. package/dist/workspace/checks/gate-approval.d.ts +58 -0
  270. package/dist/workspace/checks/gate-approval.d.ts.map +1 -0
  271. package/dist/workspace/checks/gate-approval.js +103 -0
  272. package/dist/workspace/checks/links.d.ts +3 -0
  273. package/dist/workspace/checks/links.d.ts.map +1 -1
  274. package/dist/workspace/checks/links.js +12 -1
  275. package/dist/workspace/checks/org.d.ts +48 -0
  276. package/dist/workspace/checks/org.d.ts.map +1 -0
  277. package/dist/workspace/checks/org.js +156 -0
  278. package/dist/workspace/checks.d.ts +12 -1
  279. package/dist/workspace/checks.d.ts.map +1 -1
  280. package/dist/workspace/checks.js +63 -7
  281. package/dist/workspace/ci-branches.d.ts +16 -0
  282. package/dist/workspace/ci-branches.d.ts.map +1 -1
  283. package/dist/workspace/ci-branches.js +27 -0
  284. package/dist/workspace/ci-green-cli.js +7 -7
  285. package/dist/workspace/ci-green-workflow.d.ts +1 -1
  286. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  287. package/dist/workspace/ci-green-workflow.js +13 -8
  288. package/dist/workspace/ci-green.d.ts +14 -0
  289. package/dist/workspace/ci-green.d.ts.map +1 -1
  290. package/dist/workspace/ci-green.js +44 -11
  291. package/dist/workspace/ci-run.d.ts +9 -1
  292. package/dist/workspace/ci-run.d.ts.map +1 -1
  293. package/dist/workspace/ci-run.js +67 -6
  294. package/dist/workspace/ci-serve.d.ts +9 -0
  295. package/dist/workspace/ci-serve.d.ts.map +1 -1
  296. package/dist/workspace/ci-serve.js +114 -76
  297. package/dist/workspace/compose-graph.d.ts +14 -0
  298. package/dist/workspace/compose-graph.d.ts.map +1 -1
  299. package/dist/workspace/composites.d.ts +4 -1
  300. package/dist/workspace/composites.d.ts.map +1 -1
  301. package/dist/workspace/composites.js +5 -2
  302. package/dist/workspace/composites.schema.json +22 -0
  303. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  304. package/dist/workspace/cross-root-lint.d.ts +56 -0
  305. package/dist/workspace/cross-root-lint.d.ts.map +1 -0
  306. package/dist/workspace/cross-root-lint.js +111 -0
  307. package/dist/workspace/dbt-models-reader.d.ts +44 -0
  308. package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
  309. package/dist/workspace/dbt-models-reader.js +356 -0
  310. package/dist/workspace/dbt-project-common.d.ts +40 -0
  311. package/dist/workspace/dbt-project-common.d.ts.map +1 -0
  312. package/dist/workspace/dbt-project-common.js +106 -0
  313. package/dist/workspace/dbt-project-reader.d.ts +4 -3
  314. package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
  315. package/dist/workspace/dbt-project-reader.js +14 -108
  316. package/dist/workspace/decision-rank.d.ts +26 -0
  317. package/dist/workspace/decision-rank.d.ts.map +1 -0
  318. package/dist/workspace/decision-rank.js +16 -0
  319. package/dist/workspace/declaration.d.ts +50 -2
  320. package/dist/workspace/declaration.d.ts.map +1 -1
  321. package/dist/workspace/declaration.js +57 -11
  322. package/dist/workspace/declaration.schema.json +166 -24
  323. package/dist/workspace/environments.d.ts +26 -2
  324. package/dist/workspace/environments.d.ts.map +1 -1
  325. package/dist/workspace/environments.js +26 -2
  326. package/dist/workspace/exit-cli.d.ts +44 -0
  327. package/dist/workspace/exit-cli.d.ts.map +1 -0
  328. package/dist/workspace/exit-cli.js +198 -0
  329. package/dist/workspace/exit.d.ts +159 -0
  330. package/dist/workspace/exit.d.ts.map +1 -0
  331. package/dist/workspace/exit.js +480 -0
  332. package/dist/workspace/exit.schema.json +257 -0
  333. package/dist/workspace/flyway-dir.d.ts +39 -0
  334. package/dist/workspace/flyway-dir.d.ts.map +1 -0
  335. package/dist/workspace/flyway-dir.js +104 -0
  336. package/dist/workspace/flyway-layout.d.ts +96 -0
  337. package/dist/workspace/flyway-layout.d.ts.map +1 -0
  338. package/dist/workspace/flyway-layout.js +308 -0
  339. package/dist/workspace/graph-cache.d.ts +3 -1
  340. package/dist/workspace/graph-cache.d.ts.map +1 -1
  341. package/dist/workspace/graph-cache.js +12 -1
  342. package/dist/workspace/graph-cli.d.ts.map +1 -1
  343. package/dist/workspace/graph-cli.js +26 -8
  344. package/dist/workspace/graph.schema.json +34 -0
  345. package/dist/workspace/import-fetch.d.ts +38 -0
  346. package/dist/workspace/import-fetch.d.ts.map +1 -0
  347. package/dist/workspace/import-fetch.js +99 -0
  348. package/dist/workspace/import-init.d.ts +26 -0
  349. package/dist/workspace/import-init.d.ts.map +1 -0
  350. package/dist/workspace/import-init.js +130 -0
  351. package/dist/workspace/import-source.d.ts +147 -0
  352. package/dist/workspace/import-source.d.ts.map +1 -0
  353. package/dist/workspace/import-source.js +370 -0
  354. package/dist/workspace/init.d.ts +4 -0
  355. package/dist/workspace/init.d.ts.map +1 -1
  356. package/dist/workspace/init.js +70 -3
  357. package/dist/workspace/intent.d.ts +2 -3
  358. package/dist/workspace/intent.d.ts.map +1 -1
  359. package/dist/workspace/intent.js +5 -9
  360. package/dist/workspace/kind-link-readers.d.ts +59 -2
  361. package/dist/workspace/kind-link-readers.d.ts.map +1 -1
  362. package/dist/workspace/kind-link-readers.js +17 -1
  363. package/dist/workspace/kind-readers.d.ts +6 -0
  364. package/dist/workspace/kind-readers.d.ts.map +1 -1
  365. package/dist/workspace/kind-readers.js +18 -0
  366. package/dist/workspace/kinds.d.ts +90 -3
  367. package/dist/workspace/kinds.d.ts.map +1 -1
  368. package/dist/workspace/kinds.js +161 -7
  369. package/dist/workspace/ledger.schema.json +158 -0
  370. package/dist/workspace/lexicon-outputs.d.ts +20 -1
  371. package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
  372. package/dist/workspace/lexicon-outputs.js +102 -10
  373. package/dist/workspace/lineage-check.d.ts +3 -0
  374. package/dist/workspace/lineage-check.d.ts.map +1 -1
  375. package/dist/workspace/lineage-check.js +23 -4
  376. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  377. package/dist/workspace/lineage-upgrade.js +13 -4
  378. package/dist/workspace/links.d.ts +8 -1
  379. package/dist/workspace/links.d.ts.map +1 -1
  380. package/dist/workspace/links.js +25 -1
  381. package/dist/workspace/ls.d.ts +8 -0
  382. package/dist/workspace/ls.d.ts.map +1 -1
  383. package/dist/workspace/ls.js +7 -1
  384. package/dist/workspace/ls.schema.json +7 -0
  385. package/dist/workspace/member-commands.d.ts.map +1 -1
  386. package/dist/workspace/member-commands.js +54 -5
  387. package/dist/workspace/migrate-links.d.ts +45 -0
  388. package/dist/workspace/migrate-links.d.ts.map +1 -0
  389. package/dist/workspace/migrate-links.js +100 -0
  390. package/dist/workspace/migration-dirs.d.ts +74 -0
  391. package/dist/workspace/migration-dirs.d.ts.map +1 -0
  392. package/dist/workspace/migration-dirs.js +254 -0
  393. package/dist/workspace/new-migrations.d.ts +47 -0
  394. package/dist/workspace/new-migrations.d.ts.map +1 -0
  395. package/dist/workspace/new-migrations.js +91 -0
  396. package/dist/workspace/pr-report.schema.json +46 -0
  397. package/dist/workspace/promote.d.ts +96 -0
  398. package/dist/workspace/promote.d.ts.map +1 -0
  399. package/dist/workspace/promote.js +263 -0
  400. package/dist/workspace/reason-codes.d.ts +21 -0
  401. package/dist/workspace/reason-codes.d.ts.map +1 -1
  402. package/dist/workspace/reason-codes.js +25 -0
  403. package/dist/workspace/records-cli.d.ts +11 -0
  404. package/dist/workspace/records-cli.d.ts.map +1 -1
  405. package/dist/workspace/records-cli.js +57 -5
  406. package/dist/workspace/records.schema.json +5 -0
  407. package/dist/workspace/release-candidates.d.ts +2 -0
  408. package/dist/workspace/release-candidates.d.ts.map +1 -1
  409. package/dist/workspace/release-candidates.js +5 -2
  410. package/dist/workspace/release-train.d.ts +53 -0
  411. package/dist/workspace/release-train.d.ts.map +1 -0
  412. package/dist/workspace/release-train.js +134 -0
  413. package/dist/workspace/release-workflow.d.ts.map +1 -1
  414. package/dist/workspace/release-workflow.js +4 -3
  415. package/dist/workspace/repo-ref.d.ts +45 -0
  416. package/dist/workspace/repo-ref.d.ts.map +1 -0
  417. package/dist/workspace/repo-ref.js +114 -0
  418. package/dist/workspace/run-event.schema.json +2 -2
  419. package/dist/workspace/runs-cli.d.ts +9 -0
  420. package/dist/workspace/runs-cli.d.ts.map +1 -1
  421. package/dist/workspace/runs-cli.js +48 -3
  422. package/dist/workspace/runs.schema.json +7 -0
  423. package/dist/workspace/search-contract.d.ts +1 -1
  424. package/dist/workspace/search-contract.d.ts.map +1 -1
  425. package/dist/workspace/status-decisions.d.ts +37 -0
  426. package/dist/workspace/status-decisions.d.ts.map +1 -0
  427. package/dist/workspace/status-decisions.js +147 -0
  428. package/dist/workspace/status-gates.d.ts +9 -0
  429. package/dist/workspace/status-gates.d.ts.map +1 -1
  430. package/dist/workspace/status.d.ts +4 -0
  431. package/dist/workspace/status.d.ts.map +1 -1
  432. package/dist/workspace/status.js +14 -2
  433. package/dist/workspace/status.schema.json +6 -0
  434. package/dist/workspace/work-cli.d.ts.map +1 -1
  435. package/dist/workspace/work-cli.js +5 -3
  436. package/dist/workspace/work-evidence-ops.d.ts +83 -0
  437. package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
  438. package/dist/workspace/work-evidence-ops.js +169 -0
  439. package/dist/workspace/work-evidence.d.ts +12 -2
  440. package/dist/workspace/work-evidence.d.ts.map +1 -1
  441. package/dist/workspace/work-evidence.js +21 -3
  442. package/dist/workspace/work-evidence.schema.json +49 -2
  443. package/dist/workspace/workspace-gates.d.ts +110 -0
  444. package/dist/workspace/workspace-gates.d.ts.map +1 -0
  445. package/dist/workspace/workspace-gates.js +140 -0
  446. package/dist/workspace/workspace-kinds.schema.json +108 -10
  447. package/dist/workspace/workspace-ledger.d.ts +76 -0
  448. package/dist/workspace/workspace-ledger.d.ts.map +1 -0
  449. package/dist/workspace/workspace-ledger.js +91 -0
  450. package/dist/workspace/workspace-run.d.ts +112 -0
  451. package/dist/workspace/workspace-run.d.ts.map +1 -0
  452. package/dist/workspace/workspace-run.js +432 -0
  453. package/package.json +1 -1
  454. package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  455. package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  456. package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  457. package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  458. package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  459. package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  460. package/src/__golden__/wave-loop/op-cost-member.json +13 -0
  461. package/src/__golden__/wave-loop/op-denied-source.json +16 -0
  462. package/src/__golden__/wave-loop/op-denied.json +16 -0
  463. package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  464. package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  465. package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
  466. package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
  467. package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
  468. package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  469. package/src/__golden__/wave-loop/op-held-on.json +16 -0
  470. package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  471. package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  472. package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  473. package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  474. package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
  475. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  476. package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
  477. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  478. package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
  479. package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
  480. package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  481. package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  482. package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
  483. package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  484. package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  485. package/src/__golden__/wave-loop/op-overridden.json +16 -0
  486. package/src/__golden__/wave-loop/op-per-run.json +20 -0
  487. package/src/__golden__/wave-loop/op-point.json +13 -0
  488. package/src/__golden__/wave-loop/op-pr-review.json +10 -0
  489. package/src/__golden__/wave-loop/op-sealed.json +10 -0
  490. package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
  491. package/src/__golden__/wave-loop/op-spend.json +10 -0
  492. package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
  493. package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
  494. package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
  495. package/src/__golden__/wave-loop/op-wide.json +39 -0
  496. package/src/action-pins.test.ts +78 -0
  497. package/src/action-pins.ts +92 -0
  498. package/src/cli/commands/carve-score-once.test.ts +99 -0
  499. package/src/cli/commands/carve.ts +37 -6
  500. package/src/cli/commands/check-lexicon.test.ts +2 -2
  501. package/src/cli/commands/import-report.ts +71 -0
  502. package/src/cli/commands/import.ts +33 -3
  503. package/src/cli/commands/migrate-dialect.test.ts +145 -0
  504. package/src/cli/commands/migrate.ts +132 -11
  505. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
  506. package/src/cli/handlers/approve.ts +33 -4
  507. package/src/cli/handlers/build.ts +7 -1
  508. package/src/cli/handlers/graph-reader.test.ts +31 -0
  509. package/src/cli/handlers/graph-reader.ts +51 -0
  510. package/src/cli/handlers/graph.ts +14 -0
  511. package/src/cli/handlers/ledger.ts +54 -0
  512. package/src/cli/handlers/migrate.ts +21 -12
  513. package/src/cli/handlers/misc.ts +10 -1
  514. package/src/cli/handlers/pr-env.ts +2 -2
  515. package/src/cli/handlers/pr.ts +176 -37
  516. package/src/cli/handlers/query.ts +16 -4
  517. package/src/cli/handlers/release.ts +6 -3
  518. package/src/cli/handlers/search.ts +13 -34
  519. package/src/cli/main.test.ts +17 -0
  520. package/src/cli/main.ts +87 -14
  521. package/src/cli/parse-args.ts +35 -2
  522. package/src/cli/registry.ts +22 -4
  523. package/src/components/builders.ts +8 -0
  524. package/src/components/capability-plugin-loader.ts +13 -1
  525. package/src/components/capability-plugin.ts +16 -0
  526. package/src/components/pr-env-run-bundle.test.ts +1 -0
  527. package/src/components/pr-hooks.test.ts +73 -5
  528. package/src/components/pr-hooks.ts +95 -5
  529. package/src/components/pr-pipeline.ts +64 -16
  530. package/src/components/pr-policy.test.ts +64 -1
  531. package/src/components/pr-policy.ts +53 -0
  532. package/src/components/pr-run.ts +4 -0
  533. package/src/components/registry.test.ts +1 -1
  534. package/src/components/starter-plugin.ts +6 -0
  535. package/src/components/verbs/index.ts +2 -0
  536. package/src/components/verbs/publish-artifact.test.ts +60 -0
  537. package/src/components/verbs/publish-artifact.ts +122 -0
  538. package/src/components/verbs/publish-image.test.ts +101 -0
  539. package/src/components/verbs/publish-image.ts +265 -0
  540. package/src/config-environments.ts +28 -1
  541. package/src/config.ts +24 -1
  542. package/src/gate-decision-bundle.test.ts +5 -2
  543. package/src/gate-decision-identity.test.ts +20 -0
  544. package/src/gate-decision.ts +46 -3
  545. package/src/graph-ir.ts +27 -0
  546. package/src/graph-walk.test.ts +44 -0
  547. package/src/graph-walk.ts +102 -0
  548. package/src/import/parser.ts +20 -0
  549. package/src/lexicon.ts +98 -6
  550. package/src/lifecycle/gate-ledger.ts +8 -0
  551. package/src/lifecycle/git.ts +2 -2
  552. package/src/lifecycle/ledger-read.test.ts +107 -0
  553. package/src/lifecycle/ledger-read.ts +195 -0
  554. package/src/lifecycle/release-workstation.ts +24 -0
  555. package/src/lifecycle/run-ledger.ts +5 -2
  556. package/src/lint/cross-root.test.ts +122 -0
  557. package/src/lint/discover.ts +3 -1
  558. package/src/lint/post-synth.ts +212 -2
  559. package/src/lint/rules/op/index.ts +2 -0
  560. package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
  561. package/src/op/activities/activity-contracts.ts +5 -2
  562. package/src/op/activities/index.ts +2 -2
  563. package/src/op/activities/review-agent.test.ts +221 -4
  564. package/src/op/activities/review-agent.ts +265 -22
  565. package/src/op/activities/work-evidence.ts +9 -1
  566. package/src/op/builders.ts +9 -5
  567. package/src/op/composites/apply-op.test.ts +108 -0
  568. package/src/op/composites/apply-op.ts +37 -2
  569. package/src/op/gate-approval-at-base.test.ts +97 -0
  570. package/src/op/gate-approval-base.ts +72 -0
  571. package/src/op/gate-approval.test.ts +6 -1
  572. package/src/op/gate-approval.ts +22 -27
  573. package/src/op/gate-name.ts +16 -1
  574. package/src/op/gate-quorum-at-base.test.ts +211 -0
  575. package/src/op/gate-quorum.ts +156 -8
  576. package/src/op/gate-review.ts +14 -0
  577. package/src/op/gate.ts +69 -9
  578. package/src/op/index.ts +3 -2
  579. package/src/op/local-executor.ts +91 -11
  580. package/src/op/op-waves-depends-on.test.ts +81 -0
  581. package/src/op/op-waves-hook-targets.test.ts +4 -2
  582. package/src/op/op-waves-quorum-product.test.ts +158 -0
  583. package/src/op/op-waves-run.ts +288 -14
  584. package/src/op/op-waves.ts +143 -14
  585. package/src/op/runtime.ts +8 -0
  586. package/src/op/schedule-overdue.ts +33 -0
  587. package/src/op/stage-hooks.ts +13 -5
  588. package/src/op/workspace-run-env.ts +29 -0
  589. package/src/pr-forge-bundle.test.ts +2 -2
  590. package/src/pr-forge.test.ts +47 -0
  591. package/src/pr-forge.ts +68 -0
  592. package/src/pr-loop-bundle.test.ts +3 -2
  593. package/src/pr-loop.test.ts +52 -0
  594. package/src/pr-loop.ts +12 -0
  595. package/src/pr-migrations.ts +97 -0
  596. package/src/pr-post-open.e2e.test.ts +36 -0
  597. package/src/pr-post.test.ts +102 -3
  598. package/src/pr-post.ts +90 -2
  599. package/src/read-filter.test.ts +54 -0
  600. package/src/read-filter.ts +193 -0
  601. package/src/run-event.ts +1 -1
  602. package/src/stage-hooks-bundle.test.ts +1 -0
  603. package/src/terraform/carve.ts +52 -15
  604. package/src/terraform/cuts.test.ts +173 -0
  605. package/src/terraform/cuts.ts +188 -0
  606. package/src/terraform/folds.ts +44 -0
  607. package/src/terraform/graph.ts +9 -0
  608. package/src/terraform/radius.test.ts +90 -0
  609. package/src/terraform/reach.test.ts +146 -0
  610. package/src/terraform/reach.ts +247 -0
  611. package/src/terraform/score.ts +27 -29
  612. package/src/terraform/state.ts +3 -1
  613. package/src/terraform/types.ts +8 -0
  614. package/src/wave-blocked.ts +28 -3
  615. package/src/wave-loop-golden.test.ts +4 -3
  616. package/src/workspace/__fixtures__/import/spacelift.json +9 -0
  617. package/src/workspace/__fixtures__/import/tfc.json +13 -0
  618. package/src/workspace/behold-kinds.test.ts +2 -1
  619. package/src/workspace/check-contract.test.ts +8 -6
  620. package/src/workspace/check.schema.json +13 -2
  621. package/src/workspace/checks/ci-branch.test.ts +128 -0
  622. package/src/workspace/checks/ci-branch.ts +141 -0
  623. package/src/workspace/checks/gate-approval.test.ts +77 -0
  624. package/src/workspace/checks/gate-approval.ts +121 -0
  625. package/src/workspace/checks/links.ts +12 -1
  626. package/src/workspace/checks/org.ts +169 -0
  627. package/src/workspace/checks.ts +68 -7
  628. package/src/workspace/ci-branches.ts +31 -0
  629. package/src/workspace/ci-green-branches.test.ts +153 -0
  630. package/src/workspace/ci-green-cli.ts +7 -7
  631. package/src/workspace/ci-green-workflow.test.ts +4 -3
  632. package/src/workspace/ci-green-workflow.ts +13 -9
  633. package/src/workspace/ci-green.ts +49 -12
  634. package/src/workspace/ci-run.test.ts +72 -1
  635. package/src/workspace/ci-run.ts +68 -8
  636. package/src/workspace/ci-serve.test.ts +95 -0
  637. package/src/workspace/ci-serve.ts +106 -65
  638. package/src/workspace/component-environments.test.ts +25 -2
  639. package/src/workspace/compose-graph.ts +9 -2
  640. package/src/workspace/composites.schema.json +22 -0
  641. package/src/workspace/composites.test.ts +39 -8
  642. package/src/workspace/composites.ts +6 -2
  643. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  644. package/src/workspace/cross-root-lint.test.ts +90 -0
  645. package/src/workspace/cross-root-lint.ts +126 -0
  646. package/src/workspace/dbt-kind.test.ts +3 -2
  647. package/src/workspace/dbt-models-reader.ts +362 -0
  648. package/src/workspace/dbt-models.test.ts +248 -0
  649. package/src/workspace/dbt-project-common.ts +113 -0
  650. package/src/workspace/dbt-project-reader.ts +29 -112
  651. package/src/workspace/decision-rank.ts +40 -0
  652. package/src/workspace/declaration.schema.json +166 -24
  653. package/src/workspace/declaration.ts +101 -15
  654. package/src/workspace/environments.ts +40 -4
  655. package/src/workspace/exit-cli.ts +219 -0
  656. package/src/workspace/exit.schema.json +257 -0
  657. package/src/workspace/exit.test.ts +185 -0
  658. package/src/workspace/exit.ts +560 -0
  659. package/src/workspace/flyway-dir.ts +113 -0
  660. package/src/workspace/flyway-layout.ts +337 -0
  661. package/src/workspace/graph-cache.ts +12 -2
  662. package/src/workspace/graph-cli.ts +25 -10
  663. package/src/workspace/graph-contract.test.ts +4 -2
  664. package/src/workspace/graph.schema.json +34 -0
  665. package/src/workspace/identity.test.ts +29 -2
  666. package/src/workspace/import-fetch.ts +151 -0
  667. package/src/workspace/import-init.ts +147 -0
  668. package/src/workspace/import-source.test.ts +183 -0
  669. package/src/workspace/import-source.ts +462 -0
  670. package/src/workspace/init.test.ts +55 -1
  671. package/src/workspace/init.ts +66 -4
  672. package/src/workspace/intent.ts +6 -14
  673. package/src/workspace/kind-link-readers.ts +68 -3
  674. package/src/workspace/kind-readers.test.ts +36 -0
  675. package/src/workspace/kind-readers.ts +18 -1
  676. package/src/workspace/kinds.test.ts +35 -7
  677. package/src/workspace/kinds.ts +212 -11
  678. package/src/workspace/ledger.schema.json +158 -0
  679. package/src/workspace/lexicon-outputs.ts +132 -13
  680. package/src/workspace/lineage-check.ts +30 -7
  681. package/src/workspace/lineage-upgrade.test.ts +20 -0
  682. package/src/workspace/lineage-upgrade.ts +16 -7
  683. package/src/workspace/links.ts +24 -1
  684. package/src/workspace/ls-contract.test.ts +1 -1
  685. package/src/workspace/ls.schema.json +7 -0
  686. package/src/workspace/ls.ts +10 -1
  687. package/src/workspace/member-commands.ts +60 -2
  688. package/src/workspace/member-file-schema.test.ts +124 -0
  689. package/src/workspace/migrate-links.test.ts +99 -0
  690. package/src/workspace/migrate-links.ts +108 -0
  691. package/src/workspace/migration-dirs.test.ts +272 -0
  692. package/src/workspace/migration-dirs.ts +267 -0
  693. package/src/workspace/new-migrations.test.ts +98 -0
  694. package/src/workspace/new-migrations.ts +109 -0
  695. package/src/workspace/org-scope.test.ts +238 -0
  696. package/src/workspace/pr-report.schema.json +46 -0
  697. package/src/workspace/promote.test.ts +114 -0
  698. package/src/workspace/promote.ts +302 -0
  699. package/src/workspace/reason-codes.test.ts +10 -1
  700. package/src/workspace/reason-codes.ts +25 -0
  701. package/src/workspace/records-cli.ts +58 -5
  702. package/src/workspace/records.schema.json +5 -0
  703. package/src/workspace/release-candidates.ts +7 -2
  704. package/src/workspace/release-train.ts +157 -0
  705. package/src/workspace/release-workflow.ts +4 -3
  706. package/src/workspace/repo-ref.ts +113 -0
  707. package/src/workspace/run-event.schema.json +2 -2
  708. package/src/workspace/runs-cli.ts +48 -4
  709. package/src/workspace/runs.schema.json +7 -0
  710. package/src/workspace/status-contract.test.ts +46 -1
  711. package/src/workspace/status-decisions.test.ts +100 -0
  712. package/src/workspace/status-decisions.ts +151 -0
  713. package/src/workspace/status-gates.ts +9 -0
  714. package/src/workspace/status.schema.json +6 -0
  715. package/src/workspace/status.ts +17 -3
  716. package/src/workspace/where-filters.test.ts +39 -0
  717. package/src/workspace/work-cli.ts +5 -3
  718. package/src/workspace/work-evidence-ops.test.ts +176 -0
  719. package/src/workspace/work-evidence-ops.ts +189 -0
  720. package/src/workspace/work-evidence.schema.json +49 -2
  721. package/src/workspace/work-evidence.ts +22 -3
  722. package/src/workspace/workspace-gates.ts +200 -0
  723. package/src/workspace/workspace-kinds.schema.json +108 -10
  724. package/src/workspace/workspace-ledger.ts +130 -0
  725. package/src/workspace/workspace-run.test.ts +322 -0
  726. package/src/workspace/workspace-run.ts +461 -0
@@ -190,6 +190,32 @@
190
190
  "wave 1 (apps) is refused by its policy; nothing applied."
191
191
  ],
192
192
  "files": {
193
+ ".chant/op-waves/tf-apply/outcomes/outcome-wave-1-share-2.json": {
194
+ "version": 1,
195
+ "wave": 1,
196
+ "at": "2026-10-11T00:00:00.000Z",
197
+ "members": {
198
+ "t3": {
199
+ "status": "refused"
200
+ }
201
+ }
202
+ },
203
+ ".chant/op-waves/tf-apply/outcomes/outcome-wave-1.json": {
204
+ "version": 1,
205
+ "wave": 1,
206
+ "at": "2026-10-11T00:00:00.000Z",
207
+ "members": {
208
+ "t1": {
209
+ "status": "refused"
210
+ },
211
+ "t2": {
212
+ "status": "refused"
213
+ },
214
+ "t3": {
215
+ "status": "refused"
216
+ }
217
+ }
218
+ },
193
219
  ".chant/op-waves/tf-apply/wave-1/plans.json": {
194
220
  "runs": [
195
221
  {
@@ -178,6 +178,35 @@
178
178
  "wave 3 (prod) is waiting on migrations-wave-3; nothing applied. chant approve migrations migrations-wave-3 --plan jcs1-sha256:106d25f35ee6bc02e9aa253d0b2633a764396833c82e0c5ec5a4ad83a2a85b4e"
179
179
  ],
180
180
  "files": {
181
+ ".chant/op-waves/migrations/outcomes/outcome-wave-3-share-1.json": {
182
+ "version": 1,
183
+ "wave": 3,
184
+ "at": "2026-10-11T00:00:00.000Z",
185
+ "members": {
186
+ "t1": {
187
+ "status": "waiting"
188
+ },
189
+ "t2": {
190
+ "status": "waiting"
191
+ }
192
+ }
193
+ },
194
+ ".chant/op-waves/migrations/outcomes/outcome-wave-3.json": {
195
+ "version": 1,
196
+ "wave": 3,
197
+ "at": "2026-10-11T00:00:00.000Z",
198
+ "members": {
199
+ "t1": {
200
+ "status": "waiting"
201
+ },
202
+ "t2": {
203
+ "status": "waiting"
204
+ },
205
+ "t3": {
206
+ "status": "waiting"
207
+ }
208
+ }
209
+ },
181
210
  ".chant/op-waves/migrations/wave-3/t1.plan.json": {
182
211
  "planDigest": "sha256:1111111111111111111111111111111111111111111111111111111111111111"
183
212
  },
@@ -351,6 +351,45 @@
351
351
  "t2: its plan moved since wave 3 was decided, so it was not applied. decided: sha256:2222222222222222222222222222222222222222222222222222222222222222; planned now: sha256:9999999999999999999999999999999999999999999999999999999999999999"
352
352
  ],
353
353
  "files": {
354
+ ".chant/op-waves/migrations/outcomes/outcome-wave-3-share-1.json": {
355
+ "version": 1,
356
+ "wave": 3,
357
+ "at": "2026-10-11T00:00:00.000Z",
358
+ "members": {
359
+ "t1": {
360
+ "status": "applied"
361
+ },
362
+ "t2": {
363
+ "status": "not-applied"
364
+ }
365
+ }
366
+ },
367
+ ".chant/op-waves/migrations/outcomes/outcome-wave-3-share-2.json": {
368
+ "version": 1,
369
+ "wave": 3,
370
+ "at": "2026-10-11T00:00:00.000Z",
371
+ "members": {
372
+ "t3": {
373
+ "status": "applied"
374
+ }
375
+ }
376
+ },
377
+ ".chant/op-waves/migrations/outcomes/outcome-wave-3.json": {
378
+ "version": 1,
379
+ "wave": 3,
380
+ "at": "2026-10-11T00:00:00.000Z",
381
+ "members": {
382
+ "t1": {
383
+ "status": "decided"
384
+ },
385
+ "t2": {
386
+ "status": "decided"
387
+ },
388
+ "t3": {
389
+ "status": "decided"
390
+ }
391
+ }
392
+ },
354
393
  ".chant/op-waves/migrations/wave-3/t1.hooks.json": {
355
394
  "version": 1,
356
395
  "opWaves": "migrations",
@@ -0,0 +1,78 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { readdirSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { ACTION_PINS, pinAtMajor, pinMajor, tagComments, unpinnedActions, usesRef } from "./action-pins";
5
+
6
+ describe("the action pin table", () => {
7
+ it("holds a full commit SHA and a release of the row's major for every action", () => {
8
+ for (const [key, p] of Object.entries(ACTION_PINS)) {
9
+ expect({ key, sha: /^[0-9a-f]{40}$/.test(p.sha) }).toEqual({ key, sha: true });
10
+ expect({ key, tag: p.tag.startsWith(`${p.major}.`) }).toEqual({ key, tag: true });
11
+ }
12
+ });
13
+
14
+ it("finds a tag, a branch or a short SHA, and passes a full SHA, a local action and a docker image", () => {
15
+ const yaml = [
16
+ " - uses: actions/checkout@v4",
17
+ " uses: https://code.forgejo.org/actions/cache@main",
18
+ " - uses: 'actions/setup-node@8207627'",
19
+ ` - uses: actions/checkout@${"a".repeat(40)} # v4.4.0`,
20
+ " - uses: ./.github/actions/local",
21
+ " - uses: docker://alpine:3.20",
22
+ ].join("\n");
23
+ expect(unpinnedActions(yaml)).toEqual(["actions/checkout@v4", "https://code.forgejo.org/actions/cache@main", "actions/setup-node@8207627"]);
24
+ });
25
+
26
+ it("writes the release beside a pinned line once, and leaves an unknown SHA alone", () => {
27
+ const line = ` - uses: ${usesRef(ACTION_PINS.checkout6)}`;
28
+ const once = tagComments(line);
29
+ expect(once).toBe(`${line} # ${ACTION_PINS.checkout6.tag}`);
30
+ expect(tagComments(once)).toBe(once);
31
+ expect(tagComments(` uses: actions/checkout@${"f".repeat(40)}`)).toBe(` uses: actions/checkout@${"f".repeat(40)}`);
32
+ });
33
+
34
+ it("moves a pinned upload-artifact to another major of the same action", () => {
35
+ expect(pinAtMajor(ACTION_PINS.uploadArtifact4.sha, "v3")).toBe(ACTION_PINS.uploadArtifact3);
36
+ expect(pinAtMajor(ACTION_PINS.uploadArtifact4.sha, "v9")).toBeUndefined();
37
+ expect(pinAtMajor("0".repeat(40), "v3")).toBeUndefined();
38
+ expect(pinMajor(ACTION_PINS.downloadArtifact4.sha)).toBe(4);
39
+ });
40
+ });
41
+
42
+ // #4410: the places that are not generators pin too.
43
+ const repoRoot = join(__dirname, "../../..");
44
+
45
+ describe("hand-written actions are pinned (#4410)", () => {
46
+ it("chant's own workflows name every action by a full commit SHA", () => {
47
+ const dir = join(repoRoot, ".github/workflows");
48
+ const unpinned: Record<string, string[]> = {};
49
+ for (const f of readdirSync(dir).filter((n) => n.endsWith(".yml"))) {
50
+ const found = unpinnedActions(readFileSync(join(dir, f), "utf8"));
51
+ if (found.length) unpinned[f] = found;
52
+ }
53
+ expect(unpinned).toEqual({});
54
+ });
55
+
56
+ it("every pinned line in chant's own workflows carries a release comment", () => {
57
+ const dir = join(repoRoot, ".github/workflows");
58
+ const bare: string[] = [];
59
+ for (const f of readdirSync(dir).filter((n) => n.endsWith(".yml"))) {
60
+ for (const line of readFileSync(join(dir, f), "utf8").split("\n")) {
61
+ if (/uses: *[^\s#]+@[0-9a-f]{40}\s*$/.test(line)) bare.push(`${f}: ${line.trim()}`);
62
+ }
63
+ }
64
+ expect(bare).toEqual([]);
65
+ });
66
+
67
+ it("no github composite writes a `uses:` tag literal; each takes its ref from the pin table", () => {
68
+ const dir = join(repoRoot, "lexicons/github/src/composites");
69
+ const literal: Record<string, string[]> = {};
70
+ for (const f of readdirSync(dir).filter((n) => n.endsWith(".ts") && !n.endsWith(".test.ts"))) {
71
+ const found = [...readFileSync(join(dir, f), "utf8").matchAll(/(?:uses|setupAction):\s*["'`]([^"'`]+)["'`]/g)]
72
+ .map((m) => m[1])
73
+ .filter((r) => unpinnedActions(`uses: ${r}`).length > 0);
74
+ if (found.length) literal[f] = found;
75
+ }
76
+ expect(literal).toEqual({});
77
+ });
78
+ });
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The GitHub Actions the workflows chant generates use, each pinned by commit
3
+ * SHA (#4403). A tag can move; a SHA cannot. Every generator takes its `uses:`
4
+ * from here, so an update is one change to this table. Each row is the commit
5
+ * the named major tag pointed at, with the release that commit carries;
6
+ * `tagComments` writes that release beside each `uses:` line.
7
+ *
8
+ * Forgejo's actions mirror (code.forgejo.org) carries the same commits. The
9
+ * forgejo lexicon moves `upload-artifact` and `download-artifact` to v3, whose
10
+ * rows are here too: v4 and later refuse to run on a Forgejo runner (#4008).
11
+ *
12
+ * Refresh a row by resolving the major tag to its commit:
13
+ *
14
+ * gh api repos/actions/checkout/commits/v6 --jq .sha
15
+ */
16
+
17
+ export interface ActionPin {
18
+ /** The action, with its subpath: `actions/cache/restore`. */
19
+ readonly slug: string;
20
+ /** The major tag the row follows, such as `v4`. */
21
+ readonly major: string;
22
+ readonly sha: string;
23
+ /** The release at that commit, written beside the `uses:` line. */
24
+ readonly tag: string;
25
+ }
26
+
27
+ const pin = (slug: string, major: string, sha: string, tag: string): ActionPin => ({ slug, major, sha, tag });
28
+
29
+ export const ACTION_PINS = {
30
+ checkout7: pin("actions/checkout", "v7", "3d3c42e5aac5ba805825da76410c181273ba90b1", "v7.0.1"),
31
+ checkout6: pin("actions/checkout", "v6", "d23441a48e516b6c34aea4fa41551a30e30af803", "v6.1.0"),
32
+ checkout4: pin("actions/checkout", "v4", "11d5960a326750d5838078e36cf38b85af677262", "v4.4.0"),
33
+ setupNode6: pin("actions/setup-node", "v6", "249970729cb0ef3589644e2896645e5dc5ba9c38", "v6.5.0"),
34
+ setupNode4: pin("actions/setup-node", "v4", "49933ea5288caeca8642d1e84afbd3f7d6820020", "v4.4.0"),
35
+ setupNode7: pin("actions/setup-node", "v7", "949feb2413d6458794dcd2491c4babbbce0c15c1", "v7.1.0"),
36
+ cache6: pin("actions/cache", "v6", "55cc8345863c7cc4c66a329aec7e433d2d1c52a9", "v6.1.0"),
37
+ uploadArtifact7: pin("actions/upload-artifact", "v7", "cf430e030ddbb5b0abf93d22962f4752f3646cd9", "v7.0.2"),
38
+ downloadArtifact8: pin("actions/download-artifact", "v8", "9000827ccba6bdab643e8b6fd33ac0654aef8333", "v8.0.2"),
39
+ setupGo7: pin("actions/setup-go", "v7", "b7ad1dad31e06c5925ef5d2fc7ad053ef454303e", "v7.0.0"),
40
+ setupPython7: pin("actions/setup-python", "v7", "6d4fd22b20465ccc0f7354476588e8df7c9ca0e0", "v7.1.0"),
41
+ setupBun2: pin("oven-sh/setup-bun", "v2", "0c5077e51419868618aeaa5fe8019c62421857d6", "v2.2.0"),
42
+ golangciLint9: pin("golangci/golangci-lint-action", "v9", "ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a", "v9.3.0"),
43
+ dockerLogin4: pin("docker/login-action", "v4", "81c6f93d4bc991e510b342a00b419b3bb4efc5c6", "v4.7.0"),
44
+ dockerSetupBuildx4: pin("docker/setup-buildx-action", "v4", "f87e5991a6d7451dcb8d9637bfbc97413f497069", "v4.4.1"),
45
+ dockerMetadata6: pin("docker/metadata-action", "v6", "dc802804100637a589fabce1cb79ff13a1411302", "v6.2.0"),
46
+ dockerBuildPush7: pin("docker/build-push-action", "v7", "c3c9e263c25d99ce0380d002d59b67737d91b0dc", "v7.4.0"),
47
+ createGithubAppToken2: pin("actions/create-github-app-token", "v2", "fee1f7d63c2ff003460e3d139729b119787bc349", "v2.2.2"),
48
+ cacheRestore4: pin("actions/cache/restore", "v4", "0057852bfaa89a56745cba8c7296529d2fc39830", "v4.3.0"),
49
+ cacheSave4: pin("actions/cache/save", "v4", "0057852bfaa89a56745cba8c7296529d2fc39830", "v4.3.0"),
50
+ uploadArtifact4: pin("actions/upload-artifact", "v4", "ea165f8d65b6e75b540449e92b4886f43607fa02", "v4.6.2"),
51
+ uploadArtifact3: pin("actions/upload-artifact", "v3", "ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5", "v3.2.1"),
52
+ downloadArtifact4: pin("actions/download-artifact", "v4", "d3f86a106a0bac45b974a628896c90dbdf5c8093", "v4.3.0"),
53
+ downloadArtifact3: pin("actions/download-artifact", "v3", "9bc31d5ccc31df68ecc42ccf4149144866c47d8a", "v3.0.2"),
54
+ } as const satisfies Record<string, ActionPin>;
55
+
56
+ /** The `uses:` value for a pin: `actions/checkout@<sha>`. */
57
+ export const usesRef = (p: ActionPin): string => `${p.slug}@${p.sha}`;
58
+
59
+ const TAG_BY_SHA = new Map<string, string>();
60
+ for (const p of Object.values(ACTION_PINS) as ActionPin[]) TAG_BY_SHA.set(p.sha, p.tag);
61
+
62
+ /** Write each pinned `uses:` line's release beside it, as `# v4.4.0`. A line that has a comment, or a SHA not in the table, is left alone. */
63
+ export function tagComments(yaml: string): string {
64
+ return yaml.replace(/^(\s*(?:- )?uses: *["']?[^\s"'#]+@([0-9a-f]{40})["']?)[ \t]*$/gm, (line, head: string, sha: string) => {
65
+ const tag = TAG_BY_SHA.get(sha);
66
+ return tag ? `${head} # ${tag}` : line;
67
+ });
68
+ }
69
+
70
+ /** Every `uses:` in a workflow that names an action by a tag or branch, not a 40-character commit SHA. Local actions and docker images are not actions on a forge. */
71
+ export function unpinnedActions(yaml: string): string[] {
72
+ const out: string[] = [];
73
+ for (const m of yaml.matchAll(/^\s*(?:- )?uses: *["']?([^\s"'#]+)["']?/gm)) {
74
+ const ref = m[1];
75
+ if (ref.startsWith("./") || ref.startsWith("../") || ref.startsWith("docker://")) continue;
76
+ if (!/@[0-9a-f]{40}$/.test(ref)) out.push(ref);
77
+ }
78
+ return out;
79
+ }
80
+
81
+ /** The row for the same action as the one `sha` pins, at `major`. The forgejo lexicon uses it to move a pinned `upload-artifact` v4 to v3. */
82
+ export function pinAtMajor(sha: string, major: string): ActionPin | undefined {
83
+ const rows = Object.values(ACTION_PINS) as ActionPin[];
84
+ const from = rows.find((p) => p.sha === sha);
85
+ return from ? rows.find((p) => p.slug === from.slug && p.major === major) : undefined;
86
+ }
87
+
88
+ /** The major of the row `sha` belongs to, as a number, when it is in the table. */
89
+ export function pinMajor(sha: string): number | undefined {
90
+ const row = (Object.values(ACTION_PINS) as ActionPin[]).find((p) => p.sha === sha);
91
+ return row ? Number(row.major.slice(1)) : undefined;
92
+ }
@@ -0,0 +1,99 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { carveJson } from "./carve";
3
+ import { boundaryIndex, boundaryReport } from "../../terraform/carve";
4
+ import { scoreEstate } from "../../terraform/score";
5
+ import type { TfEdge, TfGraph, TfNode } from "../../terraform/types";
6
+
7
+ const node = (type: string, name: string): TfNode => ({
8
+ address: `${type}.${name}`,
9
+ kind: "resource",
10
+ type,
11
+ name,
12
+ instances: 1,
13
+ hasDynamic: false,
14
+ });
15
+
16
+ const edge = (from: string, to: string, extra: Partial<TfEdge> = {}): TfEdge => ({
17
+ from,
18
+ to,
19
+ attrs: ["id"],
20
+ via: ["bucket"],
21
+ ...extra,
22
+ });
23
+
24
+ /** A fixture with a fold, an output edge, a module, an unmapped type and a duplicate edge. */
25
+ function fixture(): TfGraph {
26
+ return {
27
+ nodes: [
28
+ node("aws_s3_bucket", "assets"),
29
+ node("aws_s3_bucket_versioning", "assets"),
30
+ node("aws_lambda_function", "api"),
31
+ node("aws_sqs_queue", "q"),
32
+ node("random_pet", "name"),
33
+ { address: "module.cdn", kind: "module", name: "cdn", instances: 1, hasDynamic: false },
34
+ ],
35
+ edges: [
36
+ edge("aws_s3_bucket_versioning.assets", "aws_s3_bucket.assets"),
37
+ edge("aws_lambda_function.api", "aws_s3_bucket.assets", { attrs: ["bucket"] }),
38
+ edge("aws_lambda_function.api", "aws_s3_bucket.assets", { attrs: ["arn"], via: ["env"] }),
39
+ edge("output.bucket", "aws_s3_bucket.assets", { fromKind: "output", via: ["value"] }),
40
+ edge("aws_lambda_function.api", "aws_sqs_queue.q"),
41
+ edge("module.cdn", "aws_lambda_function.api"),
42
+ ],
43
+ };
44
+ }
45
+
46
+ /** The old path: every resource's boundary rescored the whole estate. */
47
+ function legacyJson(graph: TfGraph) {
48
+ const results = scoreEstate(graph);
49
+ return results.map((r) => {
50
+ const report = boundaryReport(graph, r.address, { dialect: "terraform" });
51
+ return report ? { ...r, boundary: { inbound: report.inbound, outbound: report.outbound } } : r;
52
+ });
53
+ }
54
+
55
+ function chain(n: number): TfGraph {
56
+ const nodes: TfNode[] = [];
57
+ const edges: TfEdge[] = [];
58
+ for (let i = 0; i < n; i++) {
59
+ nodes.push(node("aws_sqs_queue", `q${i}`));
60
+ if (i > 0) edges.push(edge(`aws_sqs_queue.q${i}`, `aws_sqs_queue.q${i - 1}`));
61
+ if (i > 1) edges.push(edge(`aws_sqs_queue.q${i}`, `aws_sqs_queue.q${i - 2}`));
62
+ }
63
+ return { nodes, edges };
64
+ }
65
+
66
+ describe("carve advise scores the estate once (#4391)", () => {
67
+ test("output is byte-identical to the per-resource rescoring path", () => {
68
+ const graph = fixture();
69
+ const payload = carveJson({ ok: true, from: "x", source: "terraform", results: scoreEstate(graph), graph });
70
+ expect(JSON.stringify(payload.resources)).toBe(JSON.stringify(legacyJson(graph)));
71
+ expect(payload.resources.some((r) => r.boundary?.inbound.length)).toBe(true);
72
+ });
73
+
74
+ test("a supplied peelability and edge index give the same report", () => {
75
+ const graph = fixture();
76
+ for (const r of scoreEstate(graph)) {
77
+ expect(JSON.stringify(boundaryReport(graph, r.address, { peelability: r, index: boundaryIndex(graph) }))).toBe(
78
+ JSON.stringify(boundaryReport(graph, r.address)),
79
+ );
80
+ }
81
+ });
82
+
83
+ test("on a few thousand nodes the old path costs more per resource than the whole new pass", () => {
84
+ const graph = chain(3000);
85
+ // Radius is its own walk per node (#2326), not what this test is about.
86
+ const t0 = performance.now();
87
+ const results = scoreEstate(graph, { radius: false });
88
+ const payload = carveJson({ ok: true, from: "x", source: "terraform", results, graph });
89
+ const fresh = performance.now() - t0;
90
+ expect(payload.resources).toHaveLength(3000);
91
+
92
+ // Rescoring is O(V) per resource, so 50 of them already outweigh the one pass over all 3000.
93
+ const sample = results.slice(0, 50);
94
+ const t1 = performance.now();
95
+ for (const r of sample) boundaryReport(graph, r.address);
96
+ const legacy = performance.now() - t1;
97
+ expect(legacy).toBeGreaterThan(fresh);
98
+ });
99
+ });
@@ -19,7 +19,7 @@ import { adviseCloudAssembly, CDK_DIALECT } from "../../cdk/advise";
19
19
  import { isCloudAssembly } from "../../cdk/assembly";
20
20
  import { parseTerraformDir, Hcl2JsonNotInstalled } from "../../terraform/parse";
21
21
  import { scoreEstate, type Peelability, type PeelabilityBand, type ScoreOptions } from "../../terraform/score";
22
- import { boundaryReport, type BoundaryEdge, type CarveDialect } from "../../terraform/carve";
22
+ import { boundaryIndex, boundaryReport, type BoundaryIndex, type BoundaryEdge, type CarveDialect } from "../../terraform/carve";
23
23
  import type { TfGraph } from "../../terraform/types";
24
24
 
25
25
  export interface CarveAdviseOptions {
@@ -141,6 +141,9 @@ async function adviseTerraform(opts: CarveAdviseOptions): Promise<CarveAdviseRes
141
141
  * additive and ignorable: the top-level `source` discriminator, per-resource
142
142
  * `notes` and `members`, and two more `bridge` values in a list that was
143
143
  * already declared open-ended.
144
+ *
145
+ * Per-resource `radius` (#2326) is additive the same way: a new field beside
146
+ * `score`, not a term inside it, so the score and its penalties are unchanged.
144
147
  */
145
148
  export const CARVE_REPORT_VERSION = 1;
146
149
 
@@ -201,6 +204,7 @@ export function carveJson(result: CarveAdviseResult): CarveJsonReport {
201
204
  );
202
205
  const source = result.source ?? "terraform";
203
206
  const dialect: CarveDialect = source === "cdk" ? CDK_DIALECT : "terraform";
207
+ const index = result.graph ? boundaryIndex(result.graph) : undefined;
204
208
  return {
205
209
  version: CARVE_REPORT_VERSION,
206
210
  from: result.from,
@@ -209,7 +213,7 @@ export function carveJson(result: CarveAdviseResult): CarveJsonReport {
209
213
  count: results.length,
210
214
  bands: counts,
211
215
  ...(result.diagnostics?.length ? { diagnostics: result.diagnostics } : {}),
212
- resources: results.map((r) => withBoundary(r, result.graph, dialect, result.scoreOptions)),
216
+ resources: results.map((r) => withBoundary(r, result.graph, dialect, result.scoreOptions, index)),
213
217
  };
214
218
  }
215
219
 
@@ -219,9 +223,11 @@ function withBoundary(
219
223
  graph: TfGraph | undefined,
220
224
  dialect: CarveDialect,
221
225
  score: ScoreOptions | undefined,
226
+ index: BoundaryIndex | undefined,
222
227
  ): CarveJsonResource {
223
228
  if (!graph) return r;
224
- const report = boundaryReport(graph, r.address, { dialect, score });
229
+ // The ranking already scored this resource; the report reads it back rather than rescoring the estate (#4391).
230
+ const report = boundaryReport(graph, r.address, { dialect, score, peelability: r, index });
225
231
  if (!report) return r;
226
232
  return { ...r, boundary: { inbound: report.inbound, outbound: report.outbound } };
227
233
  }
@@ -246,6 +252,8 @@ export function formatCarveReport(result: CarveAdviseResult): string {
246
252
  );
247
253
  for (const note of result.diagnostics ?? []) lines.push(` ! ${note}`);
248
254
  lines.push("");
255
+ const cells = new Map(results.map((r) => [r.address, radiusCell(r)]));
256
+ const cellWidth = Math.max(...[...cells.values()].map((c) => c.length));
249
257
 
250
258
  for (const band of BAND_ORDER) {
251
259
  const inBand = results.filter((r) => r.band === band);
@@ -253,9 +261,11 @@ export function formatCarveReport(result: CarveAdviseResult): string {
253
261
  lines.push(`${bandLabel(band, cdk)} (${inBand.length})`);
254
262
  for (const r of inBand) {
255
263
  const target = r.mapsTo ? ` -> ${r.mapsTo}` : "";
256
- lines.push(` ${String(r.score).padStart(3)} ${r.address}${target}`);
257
- lines.push(` ${reasons(r, cdk)}`);
258
- for (const note of r.notes ?? []) lines.push(` ${note}`);
264
+ const cell = cellWidth > 0 ? `${cells.get(r.address)!.padEnd(cellWidth)} ` : "";
265
+ const indent = " ".repeat(7 + (cellWidth > 0 ? cellWidth + 2 : 0));
266
+ lines.push(` ${String(r.score).padStart(3)} ${cell}${r.address}${target}`);
267
+ lines.push(`${indent}${reasons(r, cdk)}`);
268
+ for (const note of r.notes ?? []) lines.push(`${indent}${note}`);
259
269
  }
260
270
  lines.push("");
261
271
  }
@@ -263,9 +273,30 @@ export function formatCarveReport(result: CarveAdviseResult): string {
263
273
  lines.push(
264
274
  `Bands: 80-100 carve now | 50-79 carve with boundary edits | 0-49 leave in ${cdk ? "CDK" : "Terraform"}`,
265
275
  );
276
+ if (cellWidth > 0) {
277
+ lines.push(
278
+ "Radius: resources+outputs that depend on it at any depth, dN the farthest hop; - none; " +
279
+ (cdk ? "xN across a stack boundary." : "? a module or unresolved count/for_each hides how many."),
280
+ );
281
+ }
266
282
  return lines.join("\n").trimEnd();
267
283
  }
268
284
 
285
+ /**
286
+ * The radius column (#2326): `3+1 d2` is three resources and one output that
287
+ * depend on the node, the farthest two hops away; `-` is nothing; `?` stands in
288
+ * for a count a module or unresolved `count` hides; ` x2` is how many sit
289
+ * across a stack boundary. Empty when the result carries no radius.
290
+ */
291
+ function radiusCell(r: Peelability): string {
292
+ const radius = r.radius;
293
+ if (!radius) return "";
294
+ if (radius.depth === 0) return "-";
295
+ const n = (v: number | "unknown"): string => (v === "unknown" ? "?" : String(v));
296
+ const cross = radius.crossStack !== undefined && radius.crossStack !== 0 ? ` x${n(radius.crossStack)}` : "";
297
+ return `${n(radius.resources)}+${radius.outputs} d${radius.depth}${cross}`;
298
+ }
299
+
269
300
  function bandLabel(band: PeelabilityBand, cdk: boolean): string {
270
301
  switch (band) {
271
302
  case "clean leaf":
@@ -85,8 +85,8 @@ describe("coverageReportCheck", () => {
85
85
  describe("countRequiredNames (#3377)", () => {
86
86
  const read = (lex: string) => readFileSync(join(repoRoot, "lexicons", lex, "src/validate.ts"), "utf8");
87
87
 
88
- test("counts names with digits: otel reports 37", () => {
89
- expect(countRequiredNames(read("otel"))).toBe(37);
88
+ test("counts names with digits: otel reports 38", () => {
89
+ expect(countRequiredNames(read("otel"))).toBe(38);
90
90
  });
91
91
 
92
92
  test("counts only the REQUIRED_NAMES entries: prometheus reports the array length", () => {
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The review report of `chant import` (#4398): the parser's diagnostics as
3
+ * SARIF (`--report <path>`), a summary on stderr, and the exit code under
4
+ * `--strict`. The shape follows `chant migrate`: a needs-review diagnostic is
5
+ * a `warning`, and `--strict` makes any open `warning` or `error` fail the
6
+ * run. An `info` diagnostic names something not carried that needs no
7
+ * decision, and never fails a run.
8
+ */
9
+
10
+ import { writeFileSync } from "fs";
11
+ import type { ImportDiagnostic } from "../../import/parser";
12
+ import type { LintDiagnostic } from "../../lint/rule";
13
+ import { formatSarif } from "../reporters/stylish";
14
+
15
+ /** Import diagnostics as lint diagnostics against `file`, the template that was imported. */
16
+ export function importDiagnosticsToLint(file: string, diagnostics: readonly ImportDiagnostic[]): LintDiagnostic[] {
17
+ return diagnostics.map((d) => ({
18
+ file,
19
+ line: d.line ?? 1,
20
+ column: d.column ?? 1,
21
+ ruleId: d.ruleId,
22
+ severity: d.severity,
23
+ message: d.message,
24
+ ...(d.entity ? { entity: d.entity } : {}),
25
+ }));
26
+ }
27
+
28
+ /** The SARIF document for a run. */
29
+ export function importSarif(file: string, diagnostics: readonly ImportDiagnostic[], version?: string): string {
30
+ return formatSarif(importDiagnosticsToLint(file, diagnostics), undefined, undefined, version);
31
+ }
32
+
33
+ /** Write the SARIF report; an unwritable path is returned as a message, not thrown. */
34
+ export function writeImportReport(path: string, file: string, diagnostics: readonly ImportDiagnostic[], version?: string): string | undefined {
35
+ try {
36
+ writeFileSync(path, importSarif(file, diagnostics, version));
37
+ return undefined;
38
+ } catch (err) {
39
+ return `could not write SARIF report to ${path}: ${err instanceof Error ? err.message : String(err)}`;
40
+ }
41
+ }
42
+
43
+ /** Diagnostics that are open: everything but `info`. */
44
+ export function openDiagnostics(diagnostics: readonly ImportDiagnostic[]): ImportDiagnostic[] {
45
+ return diagnostics.filter((d) => d.severity !== "info");
46
+ }
47
+
48
+ /**
49
+ * The exit code for a finished import. An `error` always fails (a failed
50
+ * `--validate`); a `warning` fails under `--strict`.
51
+ */
52
+ export function importExitCode(diagnostics: readonly ImportDiagnostic[] | undefined, strict: boolean): number {
53
+ if (!diagnostics) return 0;
54
+ if (diagnostics.some((d) => d.severity === "error")) return 1;
55
+ return strict && diagnostics.some((d) => d.severity === "warning") ? 1 : 0;
56
+ }
57
+
58
+ /** Counts by severity and rule, as the lines printed after an import. */
59
+ export function summarizeImportDiagnostics(diagnostics: readonly ImportDiagnostic[]): string {
60
+ const bySeverity = { error: 0, warning: 0, info: 0 };
61
+ const byRule = new Map<string, number>();
62
+ for (const d of diagnostics) {
63
+ bySeverity[d.severity]++;
64
+ byRule.set(d.ruleId, (byRule.get(d.ruleId) ?? 0) + 1);
65
+ }
66
+ const rules = [...byRule].sort(([a], [b]) => a.localeCompare(b)).map(([id, n]) => `${id} x${String(n)}`);
67
+ return [
68
+ `Review: ${String(bySeverity.warning)} to review, ${String(bySeverity.error)} errors, ${String(bySeverity.info)} notes (${rules.join(", ")}).`,
69
+ "Write them with --report <path> as SARIF; --strict fails while any to review or error is open.",
70
+ ].join("\n");
71
+ }