@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
@@ -0,0 +1,159 @@
1
+ /**
2
+ * `chant workspace exit` (#3177): leave a member, or the workspace, in one
3
+ * step, and prove on every commit that leaving still works.
4
+ *
5
+ * Per member kind:
6
+ *
7
+ * - `chant`: build once per lexicon and commit the native output under
8
+ * `native/`, rewrite the member's CI files to call the platform's own CLI,
9
+ * drop the chant dependencies and `chant.config.*`, and set the member to
10
+ * `other` with its outputs listed. Where an Op's `op.json` sits in the
11
+ * member and the Op is linear (shell steps only), a plain CI job is written
12
+ * beside it. The `op.json` stays.
13
+ * - `choudoufu`: the roundtrip in choudoufu's `live/MIGRATE.md`. It needs
14
+ * stock OpenTofu and the estate's state, so the exit lists its steps and
15
+ * changes no file.
16
+ * - every other kind (`other`, records, ledgers, `workspace`, `repo`): kept
17
+ * as files.
18
+ *
19
+ * The functions here work on a plain directory, so the same code runs in the
20
+ * staging worktree (`exit-cli.ts`) and in the drill's scratch copy.
21
+ * {@link runExitDrill} runs the exit on a scratch copy of a workspace and
22
+ * checks the result statically: it proves each member holds what a stock
23
+ * tool needs and nothing that needs chant. It never installs chant or calls
24
+ * a cloud, so it is a unit-level check CI can run on every commit.
25
+ */
26
+ /** Runs `chant build` in a directory. The same shape as `ChantRunner` in lineage-upgrade.ts. */
27
+ export type ExitBuildRunner = (command: "build", cwd: string, args: readonly string[]) => Promise<{
28
+ exitCode: number;
29
+ output: string;
30
+ }>;
31
+ export interface NativeTarget {
32
+ /** What the output is. */
33
+ describes: string;
34
+ /** The file under the member's `native/` directory, or a path from the member's directory when `inMember`. */
35
+ file: string;
36
+ /** The file is written at this path from the member's directory rather than under `native/`. */
37
+ inMember?: boolean;
38
+ /** The stock command that deploys it, given the committed file's path from the member's directory and the member name. Null when there is nothing to deploy (CI files, collector config). */
39
+ deploy: ((file: string, member: string) => string) | null;
40
+ }
41
+ /** The lexicons `workspace exit` knows a native target for. */
42
+ export declare const NATIVE_TARGETS: Record<string, NativeTarget>;
43
+ /** The lexicons a member's `chant.config.*` or `package.json` names, in order. */
44
+ export declare function memberLexicons(dir: string): string[];
45
+ export type ExitAction = "native-build" | "choudoufu-roundtrip" | "keep";
46
+ /** Why a chant member cannot be exited. Closed; each is in `reason-codes.ts`. */
47
+ export declare const EXIT_REFUSAL_CODES: readonly ["missing-dir", "no-lexicon", "lexicon-unsupported"];
48
+ export type ExitRefusalCode = (typeof EXIT_REFUSAL_CODES)[number];
49
+ export interface MemberPlan {
50
+ name: string;
51
+ dir: string;
52
+ kind: string;
53
+ action: ExitAction;
54
+ lexicons: string[];
55
+ /** Set when the member cannot be exited, with the reason code. */
56
+ refused?: {
57
+ code: ExitRefusalCode;
58
+ message: string;
59
+ };
60
+ }
61
+ export interface ExitPlan {
62
+ root: string;
63
+ members: MemberPlan[];
64
+ }
65
+ export declare class ExitError extends Error {
66
+ }
67
+ /** What exiting `names` (every exitable member when none are named) does, read from the declaration. */
68
+ export declare function planExit(root: string, names?: readonly string[]): ExitPlan;
69
+ export interface MemberResult {
70
+ name: string;
71
+ dir: string;
72
+ kind: string;
73
+ status: "exited" | "kept" | "manual" | "refused" | "failed";
74
+ /** Why the member was refused; set only with status `refused`. */
75
+ code?: ExitRefusalCode;
76
+ /** Native files written, relative to the workspace root. */
77
+ native: string[];
78
+ /** The stock command for each native file, relative to the member's directory. */
79
+ deploy: string[];
80
+ /** CI files rewritten or written, relative to the workspace root. */
81
+ ci: string[];
82
+ /** `op.json` files left in place, relative to the workspace root. */
83
+ ops: string[];
84
+ /** Steps a person runs, for a member the exit cannot do alone. */
85
+ steps: string[];
86
+ detail?: string;
87
+ }
88
+ export interface ExitResult {
89
+ members: MemberResult[];
90
+ }
91
+ /** The choudoufu roundtrip, in order (`live/MIGRATE.md`). Run with stock OpenTofu. */
92
+ export declare function choudoufuSteps(member: string, dir: string): string[];
93
+ /**
94
+ * Exit the planned members in the tree at `plan.root`, editing it in place.
95
+ * Builds through `runBuild`, so a test can supply output without chant.
96
+ */
97
+ export declare function exitInDir(plan: ExitPlan, runBuild: ExitBuildRunner): Promise<ExitResult>;
98
+ interface OpJson {
99
+ name?: string;
100
+ phases?: {
101
+ parallel?: boolean;
102
+ steps?: {
103
+ kind?: string;
104
+ fn?: string;
105
+ args?: {
106
+ cmd?: unknown;
107
+ };
108
+ }[];
109
+ }[];
110
+ onFailure?: unknown[];
111
+ }
112
+ /** The plain commands of a linear Op, or undefined when the Op is not linear. */
113
+ export declare function linearCommands(op: OpJson): string[] | undefined;
114
+ /** What the exit drill finds wrong with an exited member. Closed; each is in `reason-codes.ts`. */
115
+ export declare const DRILL_CODES: readonly ["native-missing", "native-unreadable", "chant-dependency", "chant-config-left", "chant-in-ci", "no-deploy-command", "declaration-not-other", "exit-failed", "choudoufu-steps-missing"];
116
+ export type DrillCode = (typeof DRILL_CODES)[number];
117
+ /** Every code `workspace exit` prints: why a member was refused, and what the drill found. */
118
+ export declare const EXIT_CODES: readonly ["missing-dir", "no-lexicon", "lexicon-unsupported", "native-missing", "native-unreadable", "chant-dependency", "chant-config-left", "chant-in-ci", "no-deploy-command", "declaration-not-other", "exit-failed", "choudoufu-steps-missing"];
119
+ export interface DrillFinding {
120
+ code: DrillCode;
121
+ message: string;
122
+ }
123
+ export interface DrillMember {
124
+ name: string;
125
+ kind: string;
126
+ status: "passed" | "failed" | "not-run" | "kept";
127
+ /** Why it is `not-run` or `kept`. */
128
+ note?: string;
129
+ findings: DrillFinding[];
130
+ native: string[];
131
+ deploy: string[];
132
+ }
133
+ export interface DrillReport {
134
+ /** True when no member failed. A `not-run` member does not fail the drill; it is listed. */
135
+ ok: boolean;
136
+ members: DrillMember[];
137
+ }
138
+ export interface DrillOptions {
139
+ /** The workspace root to drill. It is copied; the tree is not touched. */
140
+ root: string;
141
+ /** Limit to these members. */
142
+ members?: readonly string[];
143
+ /** Builds a member's native output. */
144
+ runBuild: ExitBuildRunner;
145
+ }
146
+ /** Copy a workspace, leaving out `node_modules`, `.git` and chant's own scratch. */
147
+ export declare function copyWorkspace(from: string, to: string): void;
148
+ /**
149
+ * Run the exit on a scratch copy and check each member for what a stock tool
150
+ * needs. Nothing here runs chant or a cloud; the build is the one injected
151
+ * step, and its output is read as text.
152
+ */
153
+ export declare function runExitDrill(opts: DrillOptions): Promise<DrillReport>;
154
+ /** Check an exited tree at `root` against what {@link exitInDir} reported. */
155
+ export declare function verifyExit(root: string, result: ExitResult): DrillReport;
156
+ /** The drill report as lines for a terminal. */
157
+ export declare function describeDrill(report: DrillReport): string[];
158
+ export {};
159
+ //# sourceMappingURL=exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit.d.ts","sourceRoot":"","sources":["../../src/workspace/exit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,480 @@
1
+ /**
2
+ * `chant workspace exit` (#3177): leave a member, or the workspace, in one
3
+ * step, and prove on every commit that leaving still works.
4
+ *
5
+ * Per member kind:
6
+ *
7
+ * - `chant`: build once per lexicon and commit the native output under
8
+ * `native/`, rewrite the member's CI files to call the platform's own CLI,
9
+ * drop the chant dependencies and `chant.config.*`, and set the member to
10
+ * `other` with its outputs listed. Where an Op's `op.json` sits in the
11
+ * member and the Op is linear (shell steps only), a plain CI job is written
12
+ * beside it. The `op.json` stays.
13
+ * - `choudoufu`: the roundtrip in choudoufu's `live/MIGRATE.md`. It needs
14
+ * stock OpenTofu and the estate's state, so the exit lists its steps and
15
+ * changes no file.
16
+ * - every other kind (`other`, records, ledgers, `workspace`, `repo`): kept
17
+ * as files.
18
+ *
19
+ * The functions here work on a plain directory, so the same code runs in the
20
+ * staging worktree (`exit-cli.ts`) and in the drill's scratch copy.
21
+ * {@link runExitDrill} runs the exit on a scratch copy of a workspace and
22
+ * checks the result statically: it proves each member holds what a stock
23
+ * tool needs and nothing that needs chant. It never installs chant or calls
24
+ * a cloud, so it is a unit-level check CI can run on every commit.
25
+ */
26
+ import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
27
+ import { tmpdir } from "node:os";
28
+ import { dirname, join, relative, resolve } from "node:path";
29
+ import { readDeclaration } from "./declaration.js";
30
+ import { setProperty } from "./json-edit.js";
31
+ import { workingTree } from "./tree.js";
32
+ /** The lexicons `workspace exit` knows a native target for. */
33
+ export const NATIVE_TARGETS = {
34
+ aws: {
35
+ describes: "CloudFormation template",
36
+ file: "template.json",
37
+ deploy: (f, m) => `aws cloudformation deploy --template-file ${f} --stack-name ${m} --capabilities CAPABILITY_NAMED_IAM`,
38
+ },
39
+ azure: {
40
+ describes: "ARM template",
41
+ file: "azuredeploy.json",
42
+ deploy: (f, m) => `az deployment group create --resource-group ${m} --template-file ${f}`,
43
+ },
44
+ gcp: { describes: "Config Connector objects", file: "config-connector.yaml", deploy: (f) => `kubectl apply -f ${f}` },
45
+ k8s: { describes: "Kubernetes YAML", file: "k8s.yaml", deploy: (f) => `kubectl apply -f ${f}` },
46
+ docker: { describes: "Compose file", file: "docker-compose.yml", deploy: (f) => `docker compose -f ${f} up -d` },
47
+ otel: { describes: "OpenTelemetry collector config", file: "otel-collector.yaml", deploy: null },
48
+ github: { describes: "GitHub Actions workflow", file: ".github/workflows/chant-exit.yml", inMember: true, deploy: null },
49
+ gitlab: { describes: "GitLab CI file", file: ".gitlab-ci.yml", inMember: true, deploy: null },
50
+ };
51
+ /** The lexicons a member's `chant.config.*` or `package.json` names, in order. */
52
+ export function memberLexicons(dir) {
53
+ for (const name of ["chant.config.ts", "chant.config.js", "chant.config.mjs"]) {
54
+ const file = join(dir, name);
55
+ if (!existsSync(file))
56
+ continue;
57
+ const m = /lexicons\s*:\s*\[([^\]]*)\]/.exec(readFileSync(file, "utf-8"));
58
+ if (m)
59
+ return [...m[1].matchAll(/["'`]([\w-]+)["'`]/g)].map((x) => x[1]);
60
+ }
61
+ const pkg = readJson(join(dir, "package.json"));
62
+ const found = [];
63
+ for (const section of ["dependencies", "devDependencies"]) {
64
+ for (const dep of Object.keys(pkg?.[section] ?? {})) {
65
+ const m = /^@intentius\/chant-lexicon-([\w-]+)$/.exec(dep);
66
+ if (m && !found.includes(m[1]))
67
+ found.push(m[1]);
68
+ }
69
+ }
70
+ return found;
71
+ }
72
+ /** Why a chant member cannot be exited. Closed; each is in `reason-codes.ts`. */
73
+ export const EXIT_REFUSAL_CODES = ["missing-dir", "no-lexicon", "lexicon-unsupported"];
74
+ export class ExitError extends Error {
75
+ }
76
+ /** What exiting `names` (every exitable member when none are named) does, read from the declaration. */
77
+ export function planExit(root, names = []) {
78
+ const dec = readDeclaration(workingTree(root));
79
+ const real = dec.members.filter((m) => m.type === "member");
80
+ for (const n of names) {
81
+ if (!real.some((m) => m.name === n))
82
+ throw new ExitError(`no member named "${n}" (members: ${real.map((m) => m.name).join(", ") || "none"})`);
83
+ }
84
+ const chosen = names.length > 0 ? real.filter((m) => names.includes(m.name)) : real;
85
+ return { root, members: chosen.map((m) => planMember(root, m)) };
86
+ }
87
+ function planMember(root, m) {
88
+ const base = { name: m.name, dir: m.dir, kind: m.kind };
89
+ if (m.kind === "choudoufu")
90
+ return { ...base, action: "choudoufu-roundtrip", lexicons: [] };
91
+ if (m.kind !== "chant")
92
+ return { ...base, action: "keep", lexicons: [] };
93
+ const abs = resolve(root, m.dir);
94
+ if (!existsSync(abs))
95
+ return { ...base, action: "native-build", lexicons: [], refused: { code: "missing-dir", message: `${m.dir} does not exist` } };
96
+ const lexicons = memberLexicons(abs);
97
+ if (lexicons.length === 0) {
98
+ return { ...base, action: "native-build", lexicons, refused: { code: "no-lexicon", message: "no lexicon is named in chant.config.* or package.json, so there is nothing to build" } };
99
+ }
100
+ const unknown = lexicons.filter((l) => !NATIVE_TARGETS[l]);
101
+ if (unknown.length > 0) {
102
+ return {
103
+ ...base,
104
+ action: "native-build",
105
+ lexicons,
106
+ refused: { code: "lexicon-unsupported", message: `no native target for lexicon ${unknown.join(", ")} (supported: ${Object.keys(NATIVE_TARGETS).join(", ")})` },
107
+ };
108
+ }
109
+ return { ...base, action: "native-build", lexicons };
110
+ }
111
+ const CHANT_FILES = ["chant.config.ts", "chant.config.js", "chant.config.mjs", "chant.config.json"];
112
+ const CI_GLOBS = [".github/workflows", "ci", ".circleci"];
113
+ const CI_ROOT_FILES = [".gitlab-ci.yml", ".gitlab-ci.yaml"];
114
+ /** The choudoufu roundtrip, in order (`live/MIGRATE.md`). Run with stock OpenTofu. */
115
+ export function choudoufuSteps(member, dir) {
116
+ return [
117
+ `cd ${dir}`,
118
+ "copy the cache to terraform.tfstate",
119
+ "remove the live block from the estate",
120
+ `CHOUDOUFU_UNMIGRATE=${member} tofu plan # stock's first plan removes the two marker tags`,
121
+ "tofu apply",
122
+ ];
123
+ }
124
+ /**
125
+ * Exit the planned members in the tree at `plan.root`, editing it in place.
126
+ * Builds through `runBuild`, so a test can supply output without chant.
127
+ */
128
+ export async function exitInDir(plan, runBuild) {
129
+ const results = [];
130
+ for (const m of plan.members) {
131
+ const result = { name: m.name, dir: m.dir, kind: m.kind, status: "kept", native: [], deploy: [], ci: [], ops: [], steps: [] };
132
+ results.push(result);
133
+ if (m.refused) {
134
+ result.status = "refused";
135
+ result.code = m.refused.code;
136
+ result.detail = `${m.refused.code}: ${m.refused.message}`;
137
+ continue;
138
+ }
139
+ if (m.action === "choudoufu-roundtrip") {
140
+ result.status = "manual";
141
+ result.steps = choudoufuSteps(m.name, m.dir);
142
+ result.detail = "needs stock OpenTofu and the estate's state; the exit changes no file";
143
+ continue;
144
+ }
145
+ if (m.action === "keep")
146
+ continue;
147
+ const abs = resolve(plan.root, m.dir);
148
+ const outputs = [];
149
+ for (const lexicon of m.lexicons) {
150
+ const target = NATIVE_TARGETS[lexicon];
151
+ const rel = target.inMember ? target.file : `native/${target.file}`;
152
+ const out = join(abs, rel);
153
+ mkdirSync(dirname(out), { recursive: true });
154
+ const run = await runBuild("build", abs, [".", "--lexicon", lexicon, "--output", out]);
155
+ if (run.exitCode !== 0 || !existsSync(out) || statSync(out).size === 0) {
156
+ result.status = "failed";
157
+ result.detail = `chant build --lexicon ${lexicon} failed${run.output ? `: ${run.output.trim().split("\n").slice(-5).join("\n")}` : ""}`;
158
+ break;
159
+ }
160
+ result.native.push(relPath(plan.root, out));
161
+ if (target.deploy)
162
+ result.deploy.push(target.deploy(rel, m.name));
163
+ outputs.push(rel);
164
+ }
165
+ if (result.status === "failed")
166
+ continue;
167
+ result.ci = rewriteCi(plan.root, abs, result.deploy);
168
+ result.ops = collectOps(plan.root, abs);
169
+ for (const op of linearOpJobs(plan.root, abs))
170
+ result.ci.push(op);
171
+ dropChant(abs);
172
+ result.status = "exited";
173
+ }
174
+ setKindOther(plan.root, results.filter((r) => r.status === "exited"));
175
+ return { members: results };
176
+ }
177
+ function relPath(root, p) {
178
+ return relative(root, p).split("\\").join("/");
179
+ }
180
+ function readJson(file) {
181
+ try {
182
+ return JSON.parse(readFileSync(file, "utf-8"));
183
+ }
184
+ catch {
185
+ return undefined;
186
+ }
187
+ }
188
+ function walk(dir, visit) {
189
+ if (!existsSync(dir))
190
+ return;
191
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
192
+ if (e.name === "node_modules" || e.name === ".git" || e.name === "native")
193
+ continue;
194
+ const p = join(dir, e.name);
195
+ if (e.isDirectory())
196
+ walk(p, visit);
197
+ else
198
+ visit(p);
199
+ }
200
+ }
201
+ function ciFiles(abs) {
202
+ const out = [];
203
+ for (const d of CI_GLOBS)
204
+ walk(join(abs, d), (f) => /\.ya?ml$/.test(f) && out.push(f));
205
+ for (const f of CI_ROOT_FILES)
206
+ if (existsSync(join(abs, f)))
207
+ out.push(join(abs, f));
208
+ return out;
209
+ }
210
+ const CHANT_CALL = /^(\s*(?:-\s+)?(?:run:\s*)?)(?:npx\s+|pnpm\s+exec\s+|npm\s+exec\s+(?:--\s+)?)?chant\s+(?:build|deploy|apply)\b.*$/;
211
+ /**
212
+ * Replace each `chant build|deploy|apply` line of the member's CI files with
213
+ * the stock commands that deploy its native output. A line with no stock
214
+ * command to replace it (CI output, a collector config) is removed.
215
+ */
216
+ function rewriteCi(root, abs, deploy) {
217
+ const changed = [];
218
+ for (const file of ciFiles(abs)) {
219
+ const lines = readFileSync(file, "utf-8").split("\n");
220
+ let touched = false;
221
+ const next = [];
222
+ for (const line of lines) {
223
+ const m = CHANT_CALL.exec(line);
224
+ if (!m) {
225
+ next.push(line);
226
+ continue;
227
+ }
228
+ touched = true;
229
+ const lead = m[1];
230
+ if (deploy.length === 0)
231
+ continue;
232
+ const inline = /run:/.test(lead);
233
+ if (inline) {
234
+ next.push(`${lead}${deploy.join(" && ")}`);
235
+ }
236
+ else {
237
+ const indent = lead.replace(/-\s+$/, "").replace(/\S.*$/, "");
238
+ deploy.forEach((d, i) => next.push(i === 0 ? `${lead}${d}` : `${indent}${d}`));
239
+ }
240
+ }
241
+ if (touched) {
242
+ writeFileSync(file, next.join("\n"));
243
+ changed.push(relPath(root, file));
244
+ }
245
+ }
246
+ return changed;
247
+ }
248
+ /** `op.json` files under the member's `dist/ops/<name>/` or anywhere beside generated Ops. They stay. */
249
+ function collectOps(root, abs) {
250
+ const out = [];
251
+ walk(abs, (f) => f.endsWith(`${"/"}op.json`) && out.push(relPath(root, f)));
252
+ return out.sort();
253
+ }
254
+ /** The plain commands of a linear Op, or undefined when the Op is not linear. */
255
+ export function linearCommands(op) {
256
+ const cmds = [];
257
+ for (const phase of op.phases ?? []) {
258
+ if (phase.parallel)
259
+ return undefined;
260
+ for (const step of phase.steps ?? []) {
261
+ if (step.kind !== "activity" || step.fn !== "shellCmd" || typeof step.args?.cmd !== "string")
262
+ return undefined;
263
+ cmds.push(step.args.cmd);
264
+ }
265
+ }
266
+ if ((op.onFailure ?? []).length > 0)
267
+ return undefined;
268
+ return cmds.length > 0 ? cmds : undefined;
269
+ }
270
+ /** For each linear Op, a plain GitHub Actions job beside its `op.json`. */
271
+ function linearOpJobs(root, abs) {
272
+ const written = [];
273
+ walk(abs, (f) => {
274
+ if (!f.endsWith("/op.json"))
275
+ return;
276
+ const op = readJson(f);
277
+ const cmds = op && linearCommands(op);
278
+ if (!op || !cmds)
279
+ return;
280
+ const out = join(dirname(f), "job.yml");
281
+ const name = op.name ?? "op";
282
+ writeFileSync(out, [
283
+ `# Written by chant workspace exit from ${name}'s op.json. The op is linear, so it is one job.`,
284
+ `name: ${name}`,
285
+ "on: workflow_dispatch",
286
+ "jobs:",
287
+ ` ${name.replace(/[^\w-]/g, "-")}:`,
288
+ " runs-on: ubuntu-latest",
289
+ " steps:",
290
+ " - uses: actions/checkout@v4",
291
+ ...cmds.map((c, i) => ` - name: step ${i + 1}\n run: ${JSON.stringify(c)}`),
292
+ "",
293
+ ].join("\n"));
294
+ written.push(relPath(root, out));
295
+ });
296
+ return written;
297
+ }
298
+ /** Remove chant.config.* and the chant dependencies and scripts from the member's package.json. */
299
+ function dropChant(abs) {
300
+ for (const f of CHANT_FILES)
301
+ rmSync(join(abs, f), { force: true });
302
+ const file = join(abs, "package.json");
303
+ const pkg = readJson(file);
304
+ if (!pkg)
305
+ return;
306
+ for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
307
+ const deps = pkg[section];
308
+ if (!deps)
309
+ continue;
310
+ for (const d of Object.keys(deps))
311
+ if (d === "@intentius/chant" || d.startsWith("@intentius/chant-"))
312
+ delete deps[d];
313
+ if (Object.keys(deps).length === 0)
314
+ delete pkg[section];
315
+ }
316
+ const scripts = pkg.scripts;
317
+ if (scripts) {
318
+ for (const [k, v] of Object.entries(scripts))
319
+ if (/\bchant\b/.test(v))
320
+ delete scripts[k];
321
+ if (Object.keys(scripts).length === 0)
322
+ delete pkg.scripts;
323
+ }
324
+ writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\n`);
325
+ }
326
+ /** Set each exited member to kind `other` in the declaration, with `because` and its outputs. */
327
+ function setKindOther(root, exited) {
328
+ if (exited.length === 0)
329
+ return;
330
+ const dec = readDeclaration(workingTree(root));
331
+ const file = ["chant.workspace.json", "chant.workspace.jsonc"].find((f) => existsSync(join(root, f)));
332
+ const jsonc = file.endsWith("c");
333
+ let text = readFileSync(join(root, file), "utf-8");
334
+ const raw = JSON.parse(jsonc ? text.replace(/^\s*\/\/.*$/gm, "") : text).members;
335
+ for (const r of exited) {
336
+ const i = raw.findIndex((e) => e.name === r.name);
337
+ if (i < 0)
338
+ continue;
339
+ const ptr = `/members/${i}`;
340
+ const member = dec.members.find((m) => m.type === "member" && m.name === r.name);
341
+ text = setProperty(text, jsonc, ptr, "kind", "other");
342
+ text = setProperty(text, jsonc, ptr, "because", `left chant with chant workspace exit; its native output is committed under ${r.native.map((n) => relPath(join(root, r.dir), join(root, n))).join(", ")}`);
343
+ const outputs = member?.outputs ?? [];
344
+ if (outputs.length > 0)
345
+ text = setProperty(text, jsonc, ptr, "outputs", outputs);
346
+ }
347
+ writeFileSync(join(root, file), text);
348
+ }
349
+ // ── The drill ────────────────────────────────────────────────────────────────
350
+ /** What the exit drill finds wrong with an exited member. Closed; each is in `reason-codes.ts`. */
351
+ export const DRILL_CODES = [
352
+ "native-missing",
353
+ "native-unreadable",
354
+ "chant-dependency",
355
+ "chant-config-left",
356
+ "chant-in-ci",
357
+ "no-deploy-command",
358
+ "declaration-not-other",
359
+ "exit-failed",
360
+ "choudoufu-steps-missing",
361
+ ];
362
+ /** Every code `workspace exit` prints: why a member was refused, and what the drill found. */
363
+ export const EXIT_CODES = [...EXIT_REFUSAL_CODES, ...DRILL_CODES];
364
+ /** Copy a workspace, leaving out `node_modules`, `.git` and chant's own scratch. */
365
+ export function copyWorkspace(from, to) {
366
+ const skip = new Set(["node_modules", ".git", ".chant"]);
367
+ const copy = (src, dst) => {
368
+ mkdirSync(dst, { recursive: true });
369
+ for (const e of readdirSync(src, { withFileTypes: true })) {
370
+ if (skip.has(e.name))
371
+ continue;
372
+ const s = join(src, e.name);
373
+ const d = join(dst, e.name);
374
+ if (e.isDirectory())
375
+ copy(s, d);
376
+ else if (e.isFile())
377
+ copyFileSync(s, d);
378
+ }
379
+ };
380
+ copy(from, to);
381
+ }
382
+ const CHANT_IN_CI = /\bchant\s+(?:build|lint|deploy|apply|run|workspace|ci)\b|@intentius\/chant\b/;
383
+ /**
384
+ * Run the exit on a scratch copy and check each member for what a stock tool
385
+ * needs. Nothing here runs chant or a cloud; the build is the one injected
386
+ * step, and its output is read as text.
387
+ */
388
+ export async function runExitDrill(opts) {
389
+ const scratch = mkdtempSync(join(tmpdir(), "chant-exit-drill-"));
390
+ try {
391
+ copyWorkspace(opts.root, scratch);
392
+ const plan = planExit(scratch, opts.members ?? []);
393
+ const result = await exitInDir(plan, opts.runBuild);
394
+ return verifyExit(scratch, result);
395
+ }
396
+ finally {
397
+ rmSync(scratch, { recursive: true, force: true });
398
+ }
399
+ }
400
+ /** Check an exited tree at `root` against what {@link exitInDir} reported. */
401
+ export function verifyExit(root, result) {
402
+ const declared = new Map(readDeclaration(workingTree(root)).members.filter((m) => m.type === "member").map((m) => [m.name, m]));
403
+ const members = result.members.map((r) => checkMember(root, r, declared.get(r.name)));
404
+ return { ok: members.every((m) => m.status !== "failed"), members };
405
+ }
406
+ function checkMember(root, r, declared) {
407
+ const base = { name: r.name, kind: r.kind, native: r.native, deploy: r.deploy };
408
+ const findings = [];
409
+ if (r.status === "kept")
410
+ return { ...base, status: "kept", note: `kind ${r.kind} stays as files`, findings };
411
+ if (r.status === "manual") {
412
+ if (r.steps.length === 0)
413
+ findings.push({ code: "choudoufu-steps-missing", message: "the roundtrip steps were not listed" });
414
+ return findings.length > 0
415
+ ? { ...base, status: "failed", findings }
416
+ : { ...base, status: "not-run", note: "the stock OpenTofu roundtrip (copy the cache to terraform.tfstate, remove the live block, plan) is not run, needs the maintainer", findings };
417
+ }
418
+ if (r.status !== "exited") {
419
+ return { ...base, status: "failed", findings: [{ code: "exit-failed", message: r.detail ?? `exit ${r.status}` }] };
420
+ }
421
+ const abs = resolve(root, r.dir);
422
+ for (const n of r.native) {
423
+ const p = join(root, n);
424
+ if (!existsSync(p) || statSync(p).size === 0) {
425
+ findings.push({ code: "native-missing", message: `${n} is missing or empty` });
426
+ continue;
427
+ }
428
+ const text = readFileSync(p, "utf-8");
429
+ if (p.endsWith(".json")) {
430
+ try {
431
+ JSON.parse(text);
432
+ }
433
+ catch (e) {
434
+ findings.push({ code: "native-unreadable", message: `${n} is not valid JSON: ${e.message}` });
435
+ }
436
+ }
437
+ else if (/^\s*$/.test(text) || /^\s*[{[]?\s*[}\]]?\s*$/.test(text)) {
438
+ findings.push({ code: "native-unreadable", message: `${n} has no content` });
439
+ }
440
+ }
441
+ const deployable = r.native.filter((n) => !/\.github\/|\.gitlab-ci|otel-collector/.test(n));
442
+ if (deployable.length > 0 && r.deploy.length === 0)
443
+ findings.push({ code: "no-deploy-command", message: "a native file has no stock deploy command" });
444
+ for (const f of CHANT_FILES)
445
+ if (existsSync(join(abs, f)))
446
+ findings.push({ code: "chant-config-left", message: `${join(r.dir, f)} is still there` });
447
+ const pkg = readJson(join(abs, "package.json"));
448
+ if (pkg) {
449
+ for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
450
+ for (const d of Object.keys(pkg[section] ?? {})) {
451
+ if (d === "@intentius/chant" || d.startsWith("@intentius/chant-"))
452
+ findings.push({ code: "chant-dependency", message: `package.json ${section} still has ${d}` });
453
+ }
454
+ }
455
+ for (const [k, v] of Object.entries(pkg.scripts ?? {})) {
456
+ if (/\bchant\b/.test(v))
457
+ findings.push({ code: "chant-dependency", message: `package.json script "${k}" still calls chant` });
458
+ }
459
+ }
460
+ for (const f of ciFiles(abs)) {
461
+ const text = readFileSync(f, "utf-8");
462
+ const bad = text.split("\n").find((l) => CHANT_IN_CI.test(l) && !l.trim().startsWith("#"));
463
+ if (bad)
464
+ findings.push({ code: "chant-in-ci", message: `${relPath(root, f)} still calls chant: ${bad.trim()}` });
465
+ }
466
+ if (declared && declared.kind !== "other")
467
+ findings.push({ code: "declaration-not-other", message: `the declaration still has kind ${declared.kind}` });
468
+ return { ...base, status: findings.length > 0 ? "failed" : "passed", findings };
469
+ }
470
+ /** The drill report as lines for a terminal. */
471
+ export function describeDrill(report) {
472
+ const lines = [];
473
+ for (const m of report.members) {
474
+ lines.push(`${m.name} ${m.kind} ${m.status}${m.note ? ` (${m.note})` : ""}`);
475
+ for (const f of m.findings)
476
+ lines.push(` ${f.code}: ${f.message}`);
477
+ }
478
+ lines.push(report.ok ? "exit drill passed" : "exit drill failed");
479
+ return lines;
480
+ }