@intentius/chant 0.124.45 → 0.124.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) 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/capabilities/aws.paths +148 -0
  47. package/dist/capabilities/base-mappings.json +122 -0
  48. package/dist/capabilities/catalog.d.ts +89 -0
  49. package/dist/capabilities/catalog.d.ts.map +1 -0
  50. package/dist/capabilities/catalog.js +204 -0
  51. package/dist/capabilities/language.d.ts +103 -0
  52. package/dist/capabilities/language.d.ts.map +1 -0
  53. package/dist/capabilities/language.js +335 -0
  54. package/dist/capabilities/matcher.d.ts +65 -0
  55. package/dist/capabilities/matcher.d.ts.map +1 -0
  56. package/dist/capabilities/matcher.js +299 -0
  57. package/dist/capabilities/view.d.ts +207 -0
  58. package/dist/capabilities/view.d.ts.map +1 -0
  59. package/dist/capabilities/view.js +484 -0
  60. package/dist/cli/commands/carve.d.ts +3 -0
  61. package/dist/cli/commands/carve.d.ts.map +1 -1
  62. package/dist/cli/commands/carve.js +36 -7
  63. package/dist/cli/commands/import-report.d.ts +26 -0
  64. package/dist/cli/commands/import-report.d.ts.map +1 -0
  65. package/dist/cli/commands/import-report.js +65 -0
  66. package/dist/cli/commands/import.d.ts +11 -1
  67. package/dist/cli/commands/import.d.ts.map +1 -1
  68. package/dist/cli/commands/import.js +22 -3
  69. package/dist/cli/commands/lint.d.ts.map +1 -1
  70. package/dist/cli/commands/lint.js +1 -0
  71. package/dist/cli/commands/migrate.d.ts +13 -1
  72. package/dist/cli/commands/migrate.d.ts.map +1 -1
  73. package/dist/cli/commands/migrate.js +134 -10
  74. package/dist/cli/handlers/approve.d.ts.map +1 -1
  75. package/dist/cli/handlers/approve.js +21 -2
  76. package/dist/cli/handlers/build.d.ts.map +1 -1
  77. package/dist/cli/handlers/build.js +6 -1
  78. package/dist/cli/handlers/declared-graph.d.ts +44 -0
  79. package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
  80. package/dist/cli/handlers/declared-graph.js +87 -0
  81. package/dist/cli/handlers/graph.d.ts +25 -0
  82. package/dist/cli/handlers/graph.d.ts.map +1 -1
  83. package/dist/cli/handlers/graph.js +93 -87
  84. package/dist/cli/handlers/ledger.d.ts +3 -0
  85. package/dist/cli/handlers/ledger.d.ts.map +1 -0
  86. package/dist/cli/handlers/ledger.js +55 -0
  87. package/dist/cli/handlers/migrate.d.ts.map +1 -1
  88. package/dist/cli/handlers/migrate.js +18 -11
  89. package/dist/cli/handlers/misc.d.ts.map +1 -1
  90. package/dist/cli/handlers/misc.js +12 -1
  91. package/dist/cli/handlers/pr-env.d.ts.map +1 -1
  92. package/dist/cli/handlers/pr-env.js +4 -3
  93. package/dist/cli/handlers/pr.d.ts +15 -1
  94. package/dist/cli/handlers/pr.d.ts.map +1 -1
  95. package/dist/cli/handlers/pr.js +143 -39
  96. package/dist/cli/handlers/query.d.ts +7 -2
  97. package/dist/cli/handlers/query.d.ts.map +1 -1
  98. package/dist/cli/handlers/query.js +16 -4
  99. package/dist/cli/handlers/release.d.ts.map +1 -1
  100. package/dist/cli/handlers/release.js +6 -3
  101. package/dist/cli/handlers/search-count.d.ts +89 -0
  102. package/dist/cli/handlers/search-count.d.ts.map +1 -0
  103. package/dist/cli/handlers/search-count.js +132 -0
  104. package/dist/cli/handlers/search.d.ts +356 -6
  105. package/dist/cli/handlers/search.d.ts.map +1 -1
  106. package/dist/cli/handlers/search.js +1039 -155
  107. package/dist/cli/main.d.ts.map +1 -1
  108. package/dist/cli/main.js +88 -17
  109. package/dist/cli/mcp/server.d.ts.map +1 -1
  110. package/dist/cli/mcp/server.js +3 -0
  111. package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
  112. package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
  113. package/dist/cli/mcp/tools/capabilities.js +27 -0
  114. package/dist/cli/mcp/workspace-tools.d.ts +3 -1
  115. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  116. package/dist/cli/mcp/workspace-tools.js +47 -2
  117. package/dist/cli/parse-args.d.ts.map +1 -1
  118. package/dist/cli/parse-args.js +100 -19
  119. package/dist/cli/registry.d.ts +36 -4
  120. package/dist/cli/registry.d.ts.map +1 -1
  121. package/dist/components/builders.d.ts +5 -1
  122. package/dist/components/builders.d.ts.map +1 -1
  123. package/dist/components/builders.js +5 -0
  124. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  125. package/dist/components/capability-plugin-loader.js +16 -1
  126. package/dist/components/capability-plugin.d.ts +14 -0
  127. package/dist/components/capability-plugin.d.ts.map +1 -1
  128. package/dist/components/pr-env-ports.d.ts +29 -0
  129. package/dist/components/pr-env-ports.d.ts.map +1 -0
  130. package/dist/components/pr-env-ports.js +77 -0
  131. package/dist/components/pr-env-run.d.ts +5 -21
  132. package/dist/components/pr-env-run.d.ts.map +1 -1
  133. package/dist/components/pr-env-run.js +6 -70
  134. package/dist/components/pr-environment.d.ts +2 -1
  135. package/dist/components/pr-environment.d.ts.map +1 -1
  136. package/dist/components/pr-environment.js +1 -1
  137. package/dist/components/pr-hooks.d.ts +21 -1
  138. package/dist/components/pr-hooks.d.ts.map +1 -1
  139. package/dist/components/pr-hooks.js +72 -4
  140. package/dist/components/pr-pipeline.d.ts +45 -10
  141. package/dist/components/pr-pipeline.d.ts.map +1 -1
  142. package/dist/components/pr-pipeline.js +47 -14
  143. package/dist/components/pr-policy.d.ts +36 -0
  144. package/dist/components/pr-policy.d.ts.map +1 -1
  145. package/dist/components/pr-policy.js +36 -0
  146. package/dist/components/starter-plugin.d.ts +1 -0
  147. package/dist/components/starter-plugin.d.ts.map +1 -1
  148. package/dist/components/starter-plugin.js +5 -1
  149. package/dist/components/verbs/index.d.ts +2 -0
  150. package/dist/components/verbs/index.d.ts.map +1 -1
  151. package/dist/components/verbs/index.js +2 -0
  152. package/dist/components/verbs/publish-artifact.d.ts +65 -0
  153. package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
  154. package/dist/components/verbs/publish-artifact.js +74 -0
  155. package/dist/components/verbs/publish-image.d.ts +129 -0
  156. package/dist/components/verbs/publish-image.d.ts.map +1 -0
  157. package/dist/components/verbs/publish-image.js +145 -0
  158. package/dist/config-environments.d.ts +112 -0
  159. package/dist/config-environments.d.ts.map +1 -0
  160. package/dist/config-environments.js +114 -0
  161. package/dist/config.d.ts +32 -84
  162. package/dist/config.d.ts.map +1 -1
  163. package/dist/config.js +13 -96
  164. package/dist/gate-decision.d.ts +11 -2
  165. package/dist/gate-decision.d.ts.map +1 -1
  166. package/dist/gate-decision.js +15 -3
  167. package/dist/graph-detail.d.ts.map +1 -1
  168. package/dist/graph-detail.js +15 -3
  169. package/dist/graph-effective.d.ts +33 -2
  170. package/dist/graph-effective.d.ts.map +1 -1
  171. package/dist/graph-effective.js +215 -68
  172. package/dist/graph-ir.d.ts +48 -0
  173. package/dist/graph-ir.d.ts.map +1 -1
  174. package/dist/graph-ir.js +130 -0
  175. package/dist/graph-sub-template.d.ts +11 -0
  176. package/dist/graph-sub-template.d.ts.map +1 -0
  177. package/dist/graph-sub-template.js +19 -0
  178. package/dist/graph-walk.d.ts +66 -0
  179. package/dist/graph-walk.d.ts.map +1 -0
  180. package/dist/graph-walk.js +70 -0
  181. package/dist/import/parser.d.ts +19 -0
  182. package/dist/import/parser.d.ts.map +1 -1
  183. package/dist/lexicon.d.ts +80 -6
  184. package/dist/lexicon.d.ts.map +1 -1
  185. package/dist/lifecycle/gate-ledger.d.ts +11 -0
  186. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  187. package/dist/lifecycle/git.d.ts +2 -5
  188. package/dist/lifecycle/git.d.ts.map +1 -1
  189. package/dist/lifecycle/ledger-read.d.ts +65 -0
  190. package/dist/lifecycle/ledger-read.d.ts.map +1 -0
  191. package/dist/lifecycle/ledger-read.js +160 -0
  192. package/dist/lifecycle/observe.d.ts +28 -0
  193. package/dist/lifecycle/observe.d.ts.map +1 -1
  194. package/dist/lifecycle/observe.js +23 -1
  195. package/dist/lifecycle/release-workstation.d.ts +7 -0
  196. package/dist/lifecycle/release-workstation.d.ts.map +1 -1
  197. package/dist/lifecycle/release-workstation.js +25 -0
  198. package/dist/lifecycle/run-ledger.d.ts +4 -3
  199. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  200. package/dist/lifecycle/run-ledger.js +1 -0
  201. package/dist/lint/discover.js +3 -1
  202. package/dist/lint/post-synth.d.ts +127 -1
  203. package/dist/lint/post-synth.d.ts.map +1 -1
  204. package/dist/lint/post-synth.js +84 -2
  205. package/dist/lint/rule.d.ts +6 -0
  206. package/dist/lint/rule.d.ts.map +1 -1
  207. package/dist/lint/rules/op/index.d.ts +1 -0
  208. package/dist/lint/rules/op/index.d.ts.map +1 -1
  209. package/dist/lint/rules/op/index.js +2 -0
  210. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
  211. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
  212. package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
  213. package/dist/live-endpoint.d.ts +1 -1
  214. package/dist/live-endpoint.d.ts.map +1 -1
  215. package/dist/live-endpoint.js +1 -1
  216. package/dist/observation.d.ts +48 -1
  217. package/dist/observation.d.ts.map +1 -1
  218. package/dist/observation.js +21 -5
  219. package/dist/op/activities/activity-contracts.d.ts +9 -6
  220. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  221. package/dist/op/activities/activity-contracts.js +5 -2
  222. package/dist/op/activities/index.d.ts +2 -2
  223. package/dist/op/activities/index.d.ts.map +1 -1
  224. package/dist/op/activities/index.js +1 -1
  225. package/dist/op/activities/review-agent.d.ts +90 -4
  226. package/dist/op/activities/review-agent.d.ts.map +1 -1
  227. package/dist/op/activities/review-agent.js +217 -19
  228. package/dist/op/activities/work-evidence.d.ts +8 -1
  229. package/dist/op/activities/work-evidence.d.ts.map +1 -1
  230. package/dist/op/activities/work-evidence.js +1 -0
  231. package/dist/op/builders.d.ts +9 -5
  232. package/dist/op/builders.d.ts.map +1 -1
  233. package/dist/op/builders.js +9 -5
  234. package/dist/op/composites/apply-op.d.ts +29 -2
  235. package/dist/op/composites/apply-op.d.ts.map +1 -1
  236. package/dist/op/composites/apply-op.js +20 -1
  237. package/dist/op/gate-approval.d.ts +11 -5
  238. package/dist/op/gate-approval.d.ts.map +1 -1
  239. package/dist/op/gate-approval.js +11 -6
  240. package/dist/op/gate-quorum.d.ts +100 -3
  241. package/dist/op/gate-quorum.d.ts.map +1 -1
  242. package/dist/op/gate-quorum.js +108 -6
  243. package/dist/op/gate-review.d.ts +9 -0
  244. package/dist/op/gate-review.d.ts.map +1 -1
  245. package/dist/op/gate-review.js +13 -0
  246. package/dist/op/gate.d.ts +44 -3
  247. package/dist/op/gate.d.ts.map +1 -1
  248. package/dist/op/gate.js +25 -4
  249. package/dist/op/index.d.ts +3 -3
  250. package/dist/op/index.d.ts.map +1 -1
  251. package/dist/op/index.js +1 -1
  252. package/dist/op/local-executor.d.ts +38 -3
  253. package/dist/op/local-executor.d.ts.map +1 -1
  254. package/dist/op/local-executor.js +48 -6
  255. package/dist/op/op-waves-run.d.ts +26 -1
  256. package/dist/op/op-waves-run.d.ts.map +1 -1
  257. package/dist/op/op-waves-run.js +259 -13
  258. package/dist/op/op-waves.d.ts +72 -5
  259. package/dist/op/op-waves.d.ts.map +1 -1
  260. package/dist/op/op-waves.js +110 -15
  261. package/dist/op/runtime.d.ts +11 -0
  262. package/dist/op/runtime.d.ts.map +1 -1
  263. package/dist/op/schedule-overdue.d.ts +16 -0
  264. package/dist/op/schedule-overdue.d.ts.map +1 -1
  265. package/dist/op/schedule-overdue.js +36 -0
  266. package/dist/op/stage-hooks.d.ts +9 -2
  267. package/dist/op/stage-hooks.d.ts.map +1 -1
  268. package/dist/op/stage-hooks.js +7 -5
  269. package/dist/op/workspace-run-env.d.ts +22 -0
  270. package/dist/op/workspace-run-env.d.ts.map +1 -0
  271. package/dist/op/workspace-run-env.js +21 -0
  272. package/dist/pr-forge.d.ts +24 -0
  273. package/dist/pr-forge.d.ts.map +1 -1
  274. package/dist/pr-forge.js +47 -0
  275. package/dist/pr-post.d.ts +42 -0
  276. package/dist/pr-post.d.ts.map +1 -1
  277. package/dist/pr-post.js +67 -1
  278. package/dist/read-filter.d.ts +65 -0
  279. package/dist/read-filter.d.ts.map +1 -0
  280. package/dist/read-filter.js +179 -0
  281. package/dist/run-event.d.ts +1 -1
  282. package/dist/run-event.d.ts.map +1 -1
  283. package/dist/terraform/carve.d.ts +24 -3
  284. package/dist/terraform/carve.d.ts.map +1 -1
  285. package/dist/terraform/carve.js +32 -14
  286. package/dist/terraform/cuts.d.ts +97 -0
  287. package/dist/terraform/cuts.d.ts.map +1 -0
  288. package/dist/terraform/cuts.js +138 -0
  289. package/dist/terraform/folds.d.ts +26 -0
  290. package/dist/terraform/folds.d.ts.map +1 -0
  291. package/dist/terraform/folds.js +38 -0
  292. package/dist/terraform/graph.d.ts.map +1 -1
  293. package/dist/terraform/graph.js +10 -0
  294. package/dist/terraform/reach.d.ts +140 -0
  295. package/dist/terraform/reach.d.ts.map +1 -0
  296. package/dist/terraform/reach.js +170 -0
  297. package/dist/terraform/score.d.ts +14 -0
  298. package/dist/terraform/score.d.ts.map +1 -1
  299. package/dist/terraform/score.js +14 -31
  300. package/dist/terraform/state.d.ts.map +1 -1
  301. package/dist/terraform/state.js +4 -2
  302. package/dist/terraform/types.d.ts +8 -0
  303. package/dist/terraform/types.d.ts.map +1 -1
  304. package/dist/wave-blocked.d.ts +10 -1
  305. package/dist/wave-blocked.d.ts.map +1 -1
  306. package/dist/wave-blocked.js +31 -3
  307. package/dist/wave-runtime.mjs +266 -256
  308. package/dist/workspace/capabilities-contract.d.ts +66 -0
  309. package/dist/workspace/capabilities-contract.d.ts.map +1 -0
  310. package/dist/workspace/capabilities-contract.js +107 -0
  311. package/dist/workspace/capabilities.schema.json +229 -0
  312. package/dist/workspace/check.schema.json +11 -2
  313. package/dist/workspace/checks/ci-branch.d.ts +44 -0
  314. package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
  315. package/dist/workspace/checks/ci-branch.js +133 -0
  316. package/dist/workspace/checks/links.d.ts +3 -0
  317. package/dist/workspace/checks/links.d.ts.map +1 -1
  318. package/dist/workspace/checks/links.js +12 -1
  319. package/dist/workspace/checks/org.d.ts +48 -0
  320. package/dist/workspace/checks/org.d.ts.map +1 -0
  321. package/dist/workspace/checks/org.js +156 -0
  322. package/dist/workspace/checks.d.ts +11 -1
  323. package/dist/workspace/checks.d.ts.map +1 -1
  324. package/dist/workspace/checks.js +59 -7
  325. package/dist/workspace/ci-branches.d.ts +16 -0
  326. package/dist/workspace/ci-branches.d.ts.map +1 -1
  327. package/dist/workspace/ci-branches.js +27 -0
  328. package/dist/workspace/ci-green-cli.js +7 -7
  329. package/dist/workspace/ci-green-workflow.d.ts +1 -1
  330. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  331. package/dist/workspace/ci-green-workflow.js +13 -8
  332. package/dist/workspace/ci-green.d.ts +14 -0
  333. package/dist/workspace/ci-green.d.ts.map +1 -1
  334. package/dist/workspace/ci-green.js +44 -11
  335. package/dist/workspace/ci-run.d.ts +9 -1
  336. package/dist/workspace/ci-run.d.ts.map +1 -1
  337. package/dist/workspace/ci-run.js +67 -6
  338. package/dist/workspace/ci-serve.d.ts +9 -0
  339. package/dist/workspace/ci-serve.d.ts.map +1 -1
  340. package/dist/workspace/ci-serve.js +114 -76
  341. package/dist/workspace/compose-graph.d.ts +23 -0
  342. package/dist/workspace/compose-graph.d.ts.map +1 -1
  343. package/dist/workspace/compose-graph.js +3 -1
  344. package/dist/workspace/composites.d.ts +4 -1
  345. package/dist/workspace/composites.d.ts.map +1 -1
  346. package/dist/workspace/composites.js +5 -2
  347. package/dist/workspace/composites.schema.json +22 -0
  348. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  349. package/dist/workspace/conformance/index.d.ts +1 -1
  350. package/dist/workspace/conformance/index.d.ts.map +1 -1
  351. package/dist/workspace/conformance/index.js +39 -2
  352. package/dist/workspace/cross-root-lint.d.ts +56 -0
  353. package/dist/workspace/cross-root-lint.d.ts.map +1 -0
  354. package/dist/workspace/cross-root-lint.js +111 -0
  355. package/dist/workspace/dbt-models-reader.d.ts +44 -0
  356. package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
  357. package/dist/workspace/dbt-models-reader.js +356 -0
  358. package/dist/workspace/dbt-project-common.d.ts +40 -0
  359. package/dist/workspace/dbt-project-common.d.ts.map +1 -0
  360. package/dist/workspace/dbt-project-common.js +106 -0
  361. package/dist/workspace/dbt-project-reader.d.ts +4 -3
  362. package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
  363. package/dist/workspace/dbt-project-reader.js +14 -108
  364. package/dist/workspace/decision-rank.d.ts +26 -0
  365. package/dist/workspace/decision-rank.d.ts.map +1 -0
  366. package/dist/workspace/decision-rank.js +16 -0
  367. package/dist/workspace/declaration.d.ts +43 -2
  368. package/dist/workspace/declaration.d.ts.map +1 -1
  369. package/dist/workspace/declaration.js +45 -11
  370. package/dist/workspace/declaration.schema.json +133 -24
  371. package/dist/workspace/environments.d.ts +26 -2
  372. package/dist/workspace/environments.d.ts.map +1 -1
  373. package/dist/workspace/environments.js +26 -2
  374. package/dist/workspace/flyway-dir.d.ts +39 -0
  375. package/dist/workspace/flyway-dir.d.ts.map +1 -0
  376. package/dist/workspace/flyway-dir.js +104 -0
  377. package/dist/workspace/flyway-layout.d.ts +96 -0
  378. package/dist/workspace/flyway-layout.d.ts.map +1 -0
  379. package/dist/workspace/flyway-layout.js +308 -0
  380. package/dist/workspace/graph-cache.d.ts +8 -0
  381. package/dist/workspace/graph-cache.d.ts.map +1 -1
  382. package/dist/workspace/graph-cache.js +27 -3
  383. package/dist/workspace/graph-cli.d.ts +39 -2
  384. package/dist/workspace/graph-cli.d.ts.map +1 -1
  385. package/dist/workspace/graph-cli.js +92 -32
  386. package/dist/workspace/graph.schema.json +182 -0
  387. package/dist/workspace/intent.d.ts +2 -3
  388. package/dist/workspace/intent.d.ts.map +1 -1
  389. package/dist/workspace/intent.js +5 -9
  390. package/dist/workspace/kind-link-readers.d.ts +59 -2
  391. package/dist/workspace/kind-link-readers.d.ts.map +1 -1
  392. package/dist/workspace/kind-link-readers.js +17 -1
  393. package/dist/workspace/kind-readers.d.ts +3 -0
  394. package/dist/workspace/kind-readers.d.ts.map +1 -1
  395. package/dist/workspace/kind-readers.js +7 -1
  396. package/dist/workspace/kinds.d.ts +66 -2
  397. package/dist/workspace/kinds.d.ts.map +1 -1
  398. package/dist/workspace/kinds.js +98 -4
  399. package/dist/workspace/ledger.schema.json +158 -0
  400. package/dist/workspace/lexicon-outputs.d.ts +20 -1
  401. package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
  402. package/dist/workspace/lexicon-outputs.js +102 -10
  403. package/dist/workspace/lineage-check.d.ts +3 -0
  404. package/dist/workspace/lineage-check.d.ts.map +1 -1
  405. package/dist/workspace/lineage-check.js +23 -4
  406. package/dist/workspace/links.d.ts +8 -1
  407. package/dist/workspace/links.d.ts.map +1 -1
  408. package/dist/workspace/links.js +25 -1
  409. package/dist/workspace/ls.d.ts +8 -0
  410. package/dist/workspace/ls.d.ts.map +1 -1
  411. package/dist/workspace/ls.js +7 -1
  412. package/dist/workspace/ls.schema.json +7 -0
  413. package/dist/workspace/member-commands.d.ts +10 -1
  414. package/dist/workspace/member-commands.d.ts.map +1 -1
  415. package/dist/workspace/member-commands.js +71 -6
  416. package/dist/workspace/migrate-links.d.ts +45 -0
  417. package/dist/workspace/migrate-links.d.ts.map +1 -0
  418. package/dist/workspace/migrate-links.js +100 -0
  419. package/dist/workspace/migration-dirs.d.ts +74 -0
  420. package/dist/workspace/migration-dirs.d.ts.map +1 -0
  421. package/dist/workspace/migration-dirs.js +254 -0
  422. package/dist/workspace/nested-graph.d.ts +2 -0
  423. package/dist/workspace/nested-graph.d.ts.map +1 -1
  424. package/dist/workspace/nested-graph.js +32 -1
  425. package/dist/workspace/reason-codes.d.ts +18 -0
  426. package/dist/workspace/reason-codes.d.ts.map +1 -1
  427. package/dist/workspace/reason-codes.js +23 -0
  428. package/dist/workspace/records-cli.d.ts +11 -0
  429. package/dist/workspace/records-cli.d.ts.map +1 -1
  430. package/dist/workspace/records-cli.js +57 -5
  431. package/dist/workspace/records.schema.json +5 -0
  432. package/dist/workspace/release-candidates.d.ts +2 -0
  433. package/dist/workspace/release-candidates.d.ts.map +1 -1
  434. package/dist/workspace/release-candidates.js +5 -2
  435. package/dist/workspace/release-train.d.ts +53 -0
  436. package/dist/workspace/release-train.d.ts.map +1 -0
  437. package/dist/workspace/release-train.js +134 -0
  438. package/dist/workspace/release-workflow.d.ts.map +1 -1
  439. package/dist/workspace/release-workflow.js +4 -3
  440. package/dist/workspace/repo-ref.d.ts +45 -0
  441. package/dist/workspace/repo-ref.d.ts.map +1 -0
  442. package/dist/workspace/repo-ref.js +114 -0
  443. package/dist/workspace/run-event.schema.json +2 -2
  444. package/dist/workspace/runs-cli.d.ts +9 -0
  445. package/dist/workspace/runs-cli.d.ts.map +1 -1
  446. package/dist/workspace/runs-cli.js +48 -3
  447. package/dist/workspace/runs.schema.json +7 -0
  448. package/dist/workspace/search-cli.d.ts +204 -0
  449. package/dist/workspace/search-cli.d.ts.map +1 -0
  450. package/dist/workspace/search-cli.js +466 -0
  451. package/dist/workspace/search-contract.d.ts +56 -0
  452. package/dist/workspace/search-contract.d.ts.map +1 -0
  453. package/dist/workspace/search-contract.js +70 -0
  454. package/dist/workspace/search.schema.json +822 -0
  455. package/dist/workspace/status-decisions.d.ts +37 -0
  456. package/dist/workspace/status-decisions.d.ts.map +1 -0
  457. package/dist/workspace/status-decisions.js +147 -0
  458. package/dist/workspace/status-gates.d.ts +9 -0
  459. package/dist/workspace/status-gates.d.ts.map +1 -1
  460. package/dist/workspace/status.d.ts +4 -0
  461. package/dist/workspace/status.d.ts.map +1 -1
  462. package/dist/workspace/status.js +14 -2
  463. package/dist/workspace/status.schema.json +6 -0
  464. package/dist/workspace/work-cli.d.ts.map +1 -1
  465. package/dist/workspace/work-cli.js +5 -3
  466. package/dist/workspace/work-evidence-ops.d.ts +83 -0
  467. package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
  468. package/dist/workspace/work-evidence-ops.js +169 -0
  469. package/dist/workspace/work-evidence.d.ts +12 -2
  470. package/dist/workspace/work-evidence.d.ts.map +1 -1
  471. package/dist/workspace/work-evidence.js +21 -3
  472. package/dist/workspace/work-evidence.schema.json +49 -2
  473. package/dist/workspace/workspace-gates.d.ts +110 -0
  474. package/dist/workspace/workspace-gates.d.ts.map +1 -0
  475. package/dist/workspace/workspace-gates.js +140 -0
  476. package/dist/workspace/workspace-kinds.schema.json +58 -3
  477. package/dist/workspace/workspace-ledger.d.ts +76 -0
  478. package/dist/workspace/workspace-ledger.d.ts.map +1 -0
  479. package/dist/workspace/workspace-ledger.js +91 -0
  480. package/dist/workspace/workspace-run.d.ts +112 -0
  481. package/dist/workspace/workspace-run.d.ts.map +1 -0
  482. package/dist/workspace/workspace-run.js +432 -0
  483. package/package.json +1 -1
  484. package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  485. package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  486. package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  487. package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  488. package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  489. package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  490. package/src/__golden__/wave-loop/op-cost-member.json +13 -0
  491. package/src/__golden__/wave-loop/op-denied-source.json +16 -0
  492. package/src/__golden__/wave-loop/op-denied.json +16 -0
  493. package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  494. package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  495. package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
  496. package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
  497. package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
  498. package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  499. package/src/__golden__/wave-loop/op-held-on.json +16 -0
  500. package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  501. package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  502. package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  503. package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  504. package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
  505. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  506. package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
  507. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  508. package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
  509. package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
  510. package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  511. package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  512. package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
  513. package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  514. package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  515. package/src/__golden__/wave-loop/op-overridden.json +16 -0
  516. package/src/__golden__/wave-loop/op-per-run.json +20 -0
  517. package/src/__golden__/wave-loop/op-point.json +13 -0
  518. package/src/__golden__/wave-loop/op-pr-review.json +10 -0
  519. package/src/__golden__/wave-loop/op-sealed.json +10 -0
  520. package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
  521. package/src/__golden__/wave-loop/op-spend.json +10 -0
  522. package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
  523. package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
  524. package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
  525. package/src/__golden__/wave-loop/op-wide.json +39 -0
  526. package/src/__snapshots__/okf.test.ts.snap +10 -0
  527. package/src/action-pins.test.ts +78 -0
  528. package/src/action-pins.ts +92 -0
  529. package/src/capabilities/aws.paths +148 -0
  530. package/src/capabilities/base-mappings.json +122 -0
  531. package/src/capabilities/catalog.ts +230 -0
  532. package/src/capabilities/language.test.ts +191 -0
  533. package/src/capabilities/language.ts +373 -0
  534. package/src/capabilities/matcher.ts +315 -0
  535. package/src/capabilities/view-compose.test.ts +76 -0
  536. package/src/capabilities/view.ts +631 -0
  537. package/src/cli/commands/carve-score-once.test.ts +99 -0
  538. package/src/cli/commands/carve.ts +37 -6
  539. package/src/cli/commands/check-lexicon.test.ts +2 -2
  540. package/src/cli/commands/import-report.ts +71 -0
  541. package/src/cli/commands/import.ts +33 -3
  542. package/src/cli/commands/lint.ts +1 -0
  543. package/src/cli/commands/migrate-dialect.test.ts +145 -0
  544. package/src/cli/commands/migrate.ts +132 -11
  545. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
  546. package/src/cli/handlers/approve.ts +23 -2
  547. package/src/cli/handlers/build.ts +7 -1
  548. package/src/cli/handlers/declared-graph.ts +99 -0
  549. package/src/cli/handlers/graph.test.ts +94 -3
  550. package/src/cli/handlers/graph.ts +123 -96
  551. package/src/cli/handlers/ledger.ts +54 -0
  552. package/src/cli/handlers/migrate.ts +21 -12
  553. package/src/cli/handlers/misc.ts +10 -1
  554. package/src/cli/handlers/pr-env.ts +3 -4
  555. package/src/cli/handlers/pr.ts +138 -36
  556. package/src/cli/handlers/query.ts +16 -4
  557. package/src/cli/handlers/release.ts +6 -3
  558. package/src/cli/handlers/search-build-roots.test.ts +144 -0
  559. package/src/cli/handlers/search-count.test.ts +191 -0
  560. package/src/cli/handlers/search-count.ts +165 -0
  561. package/src/cli/handlers/search-json.test.ts +333 -0
  562. package/src/cli/handlers/search-live.test.ts +387 -0
  563. package/src/cli/handlers/search-paths.test.ts +235 -0
  564. package/src/cli/handlers/search.ts +1291 -166
  565. package/src/cli/main.test.ts +43 -3
  566. package/src/cli/main.ts +88 -17
  567. package/src/cli/mcp/server.test.ts +3 -3
  568. package/src/cli/mcp/server.ts +3 -0
  569. package/src/cli/mcp/tools/capabilities.ts +32 -0
  570. package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
  571. package/src/cli/mcp/workspace-tools.ts +47 -2
  572. package/src/cli/parse-args.ts +79 -15
  573. package/src/cli/registry.ts +36 -4
  574. package/src/components/builders.ts +8 -0
  575. package/src/components/capability-plugin-loader.ts +13 -1
  576. package/src/components/capability-plugin.ts +16 -0
  577. package/src/components/pr-env-ports.ts +89 -0
  578. package/src/components/pr-env-run-bundle.test.ts +54 -0
  579. package/src/components/pr-env-run.ts +5 -76
  580. package/src/components/pr-environment.ts +2 -1
  581. package/src/components/pr-hooks.test.ts +73 -5
  582. package/src/components/pr-hooks.ts +95 -5
  583. package/src/components/pr-pipeline.ts +64 -16
  584. package/src/components/pr-policy.test.ts +64 -1
  585. package/src/components/pr-policy.ts +53 -0
  586. package/src/components/registry.test.ts +1 -1
  587. package/src/components/starter-plugin.ts +6 -0
  588. package/src/components/verbs/index.ts +2 -0
  589. package/src/components/verbs/publish-artifact.test.ts +60 -0
  590. package/src/components/verbs/publish-artifact.ts +122 -0
  591. package/src/components/verbs/publish-image.test.ts +101 -0
  592. package/src/components/verbs/publish-image.ts +265 -0
  593. package/src/config-environments.ts +160 -0
  594. package/src/config.ts +44 -124
  595. package/src/gate-decision-bundle.test.ts +1 -0
  596. package/src/gate-decision-identity.test.ts +9 -0
  597. package/src/gate-decision.ts +26 -3
  598. package/src/graph-detail.ts +15 -3
  599. package/src/graph-effective.ts +226 -75
  600. package/src/graph-ir.test.ts +163 -0
  601. package/src/graph-ir.ts +174 -0
  602. package/src/graph-sub-template.ts +22 -0
  603. package/src/graph-walk.test.ts +44 -0
  604. package/src/graph-walk.ts +102 -0
  605. package/src/import/parser.ts +20 -0
  606. package/src/lexicon.ts +84 -6
  607. package/src/lifecycle/gate-ledger.ts +8 -0
  608. package/src/lifecycle/git.ts +2 -2
  609. package/src/lifecycle/ledger-read.test.ts +107 -0
  610. package/src/lifecycle/ledger-read.ts +195 -0
  611. package/src/lifecycle/observe.test.ts +27 -1
  612. package/src/lifecycle/observe.ts +43 -1
  613. package/src/lifecycle/release-workstation.ts +24 -0
  614. package/src/lifecycle/run-ledger.ts +5 -2
  615. package/src/lint/cross-root.test.ts +122 -0
  616. package/src/lint/discover.ts +3 -1
  617. package/src/lint/post-synth.ts +212 -2
  618. package/src/lint/rule.ts +6 -0
  619. package/src/lint/rules/op/index.ts +2 -0
  620. package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
  621. package/src/live-endpoint.ts +1 -1
  622. package/src/observation.test.ts +25 -0
  623. package/src/observation.ts +69 -5
  624. package/src/op/activities/activity-contracts.ts +5 -2
  625. package/src/op/activities/index.ts +2 -2
  626. package/src/op/activities/review-agent.test.ts +221 -4
  627. package/src/op/activities/review-agent.ts +265 -22
  628. package/src/op/activities/work-evidence.ts +9 -1
  629. package/src/op/builders.ts +9 -5
  630. package/src/op/composites/apply-op.test.ts +108 -0
  631. package/src/op/composites/apply-op.ts +37 -2
  632. package/src/op/gate-approval.test.ts +6 -1
  633. package/src/op/gate-approval.ts +12 -6
  634. package/src/op/gate-quorum-at-base.test.ts +211 -0
  635. package/src/op/gate-quorum.ts +156 -8
  636. package/src/op/gate-review.ts +14 -0
  637. package/src/op/gate.ts +67 -8
  638. package/src/op/index.ts +3 -2
  639. package/src/op/local-executor.ts +69 -9
  640. package/src/op/op-waves-depends-on.test.ts +81 -0
  641. package/src/op/op-waves-hook-targets.test.ts +4 -2
  642. package/src/op/op-waves-quorum-product.test.ts +158 -0
  643. package/src/op/op-waves-run.ts +288 -14
  644. package/src/op/op-waves.ts +143 -14
  645. package/src/op/runtime.ts +8 -0
  646. package/src/op/schedule-overdue.ts +33 -0
  647. package/src/op/stage-hooks.ts +13 -5
  648. package/src/op/workspace-run-env.ts +29 -0
  649. package/src/pr-forge-bundle.test.ts +2 -2
  650. package/src/pr-forge.test.ts +47 -0
  651. package/src/pr-forge.ts +68 -0
  652. package/src/pr-post-open.e2e.test.ts +36 -0
  653. package/src/pr-post.test.ts +102 -3
  654. package/src/pr-post.ts +89 -1
  655. package/src/read-filter.test.ts +54 -0
  656. package/src/read-filter.ts +193 -0
  657. package/src/run-event.ts +1 -1
  658. package/src/stage-hooks-bundle.test.ts +1 -0
  659. package/src/terraform/carve.ts +52 -15
  660. package/src/terraform/cuts.test.ts +173 -0
  661. package/src/terraform/cuts.ts +188 -0
  662. package/src/terraform/folds.ts +44 -0
  663. package/src/terraform/graph.ts +9 -0
  664. package/src/terraform/radius.test.ts +90 -0
  665. package/src/terraform/reach.test.ts +146 -0
  666. package/src/terraform/reach.ts +247 -0
  667. package/src/terraform/score.ts +27 -29
  668. package/src/terraform/state.ts +3 -1
  669. package/src/terraform/types.ts +8 -0
  670. package/src/wave-blocked.ts +28 -3
  671. package/src/wave-loop-golden.test.ts +4 -3
  672. package/src/workspace/behold-kinds.test.ts +1 -1
  673. package/src/workspace/capabilities-contract.test.ts +88 -0
  674. package/src/workspace/capabilities-contract.ts +132 -0
  675. package/src/workspace/capabilities.schema.json +229 -0
  676. package/src/workspace/check-contract.test.ts +7 -6
  677. package/src/workspace/check.schema.json +11 -2
  678. package/src/workspace/checks/ci-branch.test.ts +128 -0
  679. package/src/workspace/checks/ci-branch.ts +141 -0
  680. package/src/workspace/checks/links.ts +12 -1
  681. package/src/workspace/checks/org.ts +169 -0
  682. package/src/workspace/checks.ts +64 -7
  683. package/src/workspace/ci-branches.ts +31 -0
  684. package/src/workspace/ci-green-branches.test.ts +153 -0
  685. package/src/workspace/ci-green-cli.ts +7 -7
  686. package/src/workspace/ci-green-workflow.test.ts +4 -3
  687. package/src/workspace/ci-green-workflow.ts +13 -9
  688. package/src/workspace/ci-green.ts +49 -12
  689. package/src/workspace/ci-run.test.ts +72 -1
  690. package/src/workspace/ci-run.ts +68 -8
  691. package/src/workspace/ci-serve.test.ts +95 -0
  692. package/src/workspace/ci-serve.ts +106 -65
  693. package/src/workspace/component-environments.test.ts +25 -2
  694. package/src/workspace/compose-graph.ts +19 -3
  695. package/src/workspace/composites.schema.json +22 -0
  696. package/src/workspace/composites.test.ts +39 -8
  697. package/src/workspace/composites.ts +6 -2
  698. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  699. package/src/workspace/conformance/conformance.e2e.test.ts +14 -1
  700. package/src/workspace/conformance/index.ts +31 -2
  701. package/src/workspace/cross-root-lint.test.ts +90 -0
  702. package/src/workspace/cross-root-lint.ts +126 -0
  703. package/src/workspace/dbt-kind.test.ts +3 -2
  704. package/src/workspace/dbt-models-reader.ts +362 -0
  705. package/src/workspace/dbt-models.test.ts +248 -0
  706. package/src/workspace/dbt-project-common.ts +113 -0
  707. package/src/workspace/dbt-project-reader.ts +29 -112
  708. package/src/workspace/decision-rank.ts +40 -0
  709. package/src/workspace/declaration.schema.json +133 -24
  710. package/src/workspace/declaration.ts +84 -15
  711. package/src/workspace/environments.ts +40 -4
  712. package/src/workspace/flyway-dir.ts +113 -0
  713. package/src/workspace/flyway-layout.ts +337 -0
  714. package/src/workspace/graph-cache.ts +27 -3
  715. package/src/workspace/graph-cli.ts +119 -32
  716. package/src/workspace/graph-contract.test.ts +4 -2
  717. package/src/workspace/graph.schema.json +182 -0
  718. package/src/workspace/identity.test.ts +14 -2
  719. package/src/workspace/intent.ts +6 -14
  720. package/src/workspace/kind-link-readers.ts +68 -3
  721. package/src/workspace/kind-readers.e2e.test.ts +28 -0
  722. package/src/workspace/kind-readers.test.ts +1 -1
  723. package/src/workspace/kind-readers.ts +7 -1
  724. package/src/workspace/kinds.test.ts +12 -7
  725. package/src/workspace/kinds.ts +132 -7
  726. package/src/workspace/ledger.schema.json +158 -0
  727. package/src/workspace/lexicon-outputs.ts +132 -13
  728. package/src/workspace/lineage-check.ts +30 -7
  729. package/src/workspace/links.ts +24 -1
  730. package/src/workspace/ls-contract.test.ts +1 -1
  731. package/src/workspace/ls.schema.json +7 -0
  732. package/src/workspace/ls.ts +10 -1
  733. package/src/workspace/member-commands.ts +82 -3
  734. package/src/workspace/member-file-schema.test.ts +124 -0
  735. package/src/workspace/migrate-links.test.ts +99 -0
  736. package/src/workspace/migrate-links.ts +108 -0
  737. package/src/workspace/migration-dirs.test.ts +272 -0
  738. package/src/workspace/migration-dirs.ts +267 -0
  739. package/src/workspace/nested-graph.ts +32 -1
  740. package/src/workspace/org-scope.test.ts +238 -0
  741. package/src/workspace/reason-codes.test.ts +13 -1
  742. package/src/workspace/reason-codes.ts +23 -0
  743. package/src/workspace/records-cli.ts +58 -5
  744. package/src/workspace/records.schema.json +5 -0
  745. package/src/workspace/release-candidates.ts +7 -2
  746. package/src/workspace/release-train.ts +157 -0
  747. package/src/workspace/release-workflow.ts +4 -3
  748. package/src/workspace/repo-ref.ts +113 -0
  749. package/src/workspace/run-event.schema.json +2 -2
  750. package/src/workspace/runs-cli.ts +48 -4
  751. package/src/workspace/runs.schema.json +7 -0
  752. package/src/workspace/search-cli.e2e.test.ts +305 -0
  753. package/src/workspace/search-cli.ts +591 -0
  754. package/src/workspace/search-contract.ts +95 -0
  755. package/src/workspace/search.schema.json +822 -0
  756. package/src/workspace/status-contract.test.ts +46 -1
  757. package/src/workspace/status-decisions.test.ts +100 -0
  758. package/src/workspace/status-decisions.ts +151 -0
  759. package/src/workspace/status-gates.ts +9 -0
  760. package/src/workspace/status.schema.json +6 -0
  761. package/src/workspace/status.ts +17 -3
  762. package/src/workspace/where-filters.test.ts +39 -0
  763. package/src/workspace/work-cli.ts +5 -3
  764. package/src/workspace/work-evidence-ops.test.ts +176 -0
  765. package/src/workspace/work-evidence-ops.ts +189 -0
  766. package/src/workspace/work-evidence.schema.json +49 -2
  767. package/src/workspace/work-evidence.ts +22 -3
  768. package/src/workspace/workspace-gates.ts +200 -0
  769. package/src/workspace/workspace-kinds.schema.json +58 -3
  770. package/src/workspace/workspace-ledger.ts +130 -0
  771. package/src/workspace/workspace-run.test.ts +322 -0
  772. package/src/workspace/workspace-run.ts +461 -0
@@ -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
+ }
@@ -1,13 +1,14 @@
1
1
  import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from "fs";
2
2
  import { join, resolve, basename, dirname } from "path";
3
3
  import { formatSuccess, formatWarning, formatError } from "../format";
4
- import type { TemplateIR, ResourceIR, ParameterIR, ParseContext } from "../../import/parser";
4
+ import type { TemplateIR, ResourceIR, ParameterIR, ParseContext, ImportDiagnostic } from "../../import/parser";
5
5
  import type { GeneratedFile, TypeScriptGenerator } from "../../import/generator";
6
6
  import { listInstalledLexicons, loadPlugin, loadPlugins, resolveProjectLexicons } from "../plugins";
7
7
  import type { ExportedTemplate, LexiconPlugin, ResourceSelector } from "../../lexicon";
8
8
  import { parseYAMLDocument, splitYAMLDocuments } from "../../yaml";
9
9
  import { importLexiconPackage } from "../../lexicon-module";
10
10
  import { resolveParserOptions } from "../../import/parser-options";
11
+ import { summarizeImportDiagnostics } from "./import-report";
11
12
  import { EmbeddedImports, type EmbeddedContent, type RegisteredEmbeddedImporter } from "../../import/embedded";
12
13
 
13
14
  /**
@@ -31,6 +32,8 @@ export interface ImportOptions {
31
32
  * fails the import before anything is parsed.
32
33
  */
33
34
  parserOptions?: string[];
35
+ /** `--validate` (#4398): check the parsed template on the lexicon's emulator before writing. */
36
+ validate?: boolean;
34
37
  }
35
38
 
36
39
  /**
@@ -52,6 +55,12 @@ export interface ImportResult {
52
55
  * it was named (`--lexicon`, `--kustomize`) (#2965).
53
56
  */
54
57
  detected?: boolean;
58
+ /**
59
+ * What the parser flagged for review (#4398), then what `--validate`
60
+ * rejected. `--report` writes them as SARIF and `--strict` fails while a
61
+ * `warning` or `error` is open; see `./import-report.ts`.
62
+ */
63
+ diagnostics?: ImportDiagnostic[];
55
64
  }
56
65
 
57
66
  /**
@@ -353,6 +362,7 @@ export async function importCommand(options: ImportOptions): Promise<ImportResul
353
362
  output: options.output,
354
363
  force: options.force,
355
364
  parserOptions: options.parserOptions,
365
+ validate: options.validate,
356
366
  });
357
367
  }
358
368
 
@@ -391,7 +401,7 @@ export async function importCommand(options: ImportOptions): Promise<ImportResul
391
401
  );
392
402
  }
393
403
 
394
- const result = await parseAndWrite(plugin, content, outputDir, options.force, warnings, generatedFiles, plugin.name, projectDir, options.parserOptions);
404
+ const result = await parseAndWrite(plugin, content, outputDir, options.force, warnings, generatedFiles, plugin.name, projectDir, options.parserOptions, options.validate);
395
405
  return { ...result, detected: true };
396
406
  }
397
407
 
@@ -412,6 +422,8 @@ export interface ContentImportOptions {
412
422
  force?: boolean;
413
423
  /** `--parser-option` entries for the lexicon's parser (#2994); see {@link ImportOptions.parserOptions}. */
414
424
  parserOptions?: string[];
425
+ /** `--validate`; see {@link ImportOptions.validate}. */
426
+ validate?: boolean;
415
427
  }
416
428
 
417
429
  export async function importFromContent(options: ContentImportOptions): Promise<ImportResult> {
@@ -432,7 +444,7 @@ export async function importFromContent(options: ContentImportOptions): Promise<
432
444
  return { success: false, generatedFiles: [], warnings: [], error: `Lexicon "${options.lexicon}" not available.` };
433
445
  }
434
446
  const projectDir = resolve(options.output ? dirname(options.output) : ".");
435
- return parseAndWrite(plugin, options.content, outputDir, options.force, [], [], plugin.name, projectDir, options.parserOptions);
447
+ return parseAndWrite(plugin, options.content, outputDir, options.force, [], [], plugin.name, projectDir, options.parserOptions, options.validate);
436
448
  }
437
449
 
438
450
  /**
@@ -568,6 +580,7 @@ async function parseAndWrite(
568
580
  lexicon: string,
569
581
  projectDir: string,
570
582
  parserOptionEntries?: readonly string[],
583
+ validate?: boolean,
571
584
  ): Promise<ImportResult> {
572
585
  // A lexicon can recognize a template (detectTemplate) without being able to
573
586
  // import it (grafana had no parser until #2945). Every path funnels through here, so
@@ -609,6 +622,18 @@ async function parseAndWrite(
609
622
  if (ir.warnings) {
610
623
  warnings.push(...ir.warnings);
611
624
  }
625
+ // Findings for review (#4398), and what the lexicon's emulator rejects.
626
+ const diagnostics: ImportDiagnostic[] = [...(ir.diagnostics ?? [])];
627
+ if (validate) {
628
+ if (!plugin.validateImport) {
629
+ return { success: false, generatedFiles: [], warnings: [], error: `lexicon "${plugin.name}" has no emulator to validate an import against`, lexicon: plugin.name };
630
+ }
631
+ try {
632
+ diagnostics.push(...(await plugin.validateImport(ir, resolved.options)));
633
+ } catch (err) {
634
+ return { success: false, generatedFiles: [], warnings: [], error: `--validate failed to run: ${err instanceof Error ? err.message : String(err)}`, lexicon: plugin.name };
635
+ }
636
+ }
612
637
  // Embedded content the owner could not carry, or that no installed lexicon imports.
613
638
  if (embedded) warnings.push(...embedded.warnings);
614
639
 
@@ -660,6 +685,7 @@ async function parseAndWrite(
660
685
  generatedFiles,
661
686
  warnings,
662
687
  lexicon,
688
+ ...(diagnostics.length > 0 ? { diagnostics } : {}),
663
689
  };
664
690
  }
665
691
 
@@ -894,6 +920,10 @@ export function printImportResult(result: ImportResult): void {
894
920
  console.log(`${result.detected ? "Detected lexicon" : "Lexicon"}: ${result.lexicon}`);
895
921
  }
896
922
 
923
+ if (result.diagnostics && result.diagnostics.length > 0) {
924
+ console.error(summarizeImportDiagnostics(result.diagnostics));
925
+ }
926
+
897
927
  if (result.generatedFiles.length > 0) {
898
928
  console.log(formatSuccess("Generated files:"));
899
929
  for (const file of result.generatedFiles) {
@@ -785,6 +785,7 @@ async function runLexiconPostSynthDiagnostics(
785
785
  ruleId: d.checkId,
786
786
  severity: d.severity,
787
787
  message: `${d.entity ? `[${d.entity}] ` : ""}${d.message}`,
788
+ ...(d.entity ? { entity: d.entity } : {}),
788
789
  });
789
790
 
790
791
  for (const { plugin, diagnostics: raw } of runLexiconPostSynthChecks(withChecks, result, env, { activityContracts, telemetry, projectDir: configDir, ...(loadedConfig ? { projectConfig: loadedConfig } : {}) })) {
@@ -0,0 +1,145 @@
1
+ /**
2
+ * `chant migrate` naming and the target-server `--validate` (#4399): a side is
3
+ * `lexicon` or `lexicon/dialect`, a directory is a source only when the
4
+ * lexicon says so, and a result's own `validate` replaces the external linter.
5
+ */
6
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
7
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { lexiconOfSide, migrateCommand } from "./migrate";
11
+ import type { LexiconPlugin, MigrationResult, MigrationSource } from "../../lexicon";
12
+
13
+ const seen: Array<{ from: string; to: string | undefined }> = [];
14
+
15
+ function sqlPlugin(over: { directory?: boolean; result?: Partial<MigrationResult>; transform?: MigrationSource["transform"] } = {}): LexiconPlugin {
16
+ return {
17
+ name: "sql",
18
+ serializer: { name: "sql", rulePrefix: "SQL", serialize: () => "" },
19
+ async generate() {},
20
+ async validate() {},
21
+ async coverage() {},
22
+ async package() {},
23
+ migrationSource(from: string, to?: string) {
24
+ seen.push({ from, to });
25
+ if (from !== "sql/postgres" || (to !== undefined && to !== "sql/clickhouse")) return undefined;
26
+ return {
27
+ detect: (content: string) => content.includes("CREATE TABLE"),
28
+ ...(over.directory ? { directory: true } : {}),
29
+ transform: over.transform ?? (async () => ({ output: "-- ddl\n", provenance: [], diagnostics: [], ...over.result })),
30
+ };
31
+ },
32
+ };
33
+ }
34
+
35
+ const base = { emit: "sql" as const, strict: false, validate: false, useComposites: false };
36
+
37
+ describe("lexiconOfSide", () => {
38
+ test("is the part before the slash", () => {
39
+ expect(lexiconOfSide("sql/clickhouse")).toBe("sql");
40
+ expect(lexiconOfSide("gitlab")).toBe("gitlab");
41
+ });
42
+ });
43
+
44
+ describe("migrateCommand with lexicon/dialect sides", () => {
45
+ let dir: string;
46
+ beforeEach(() => {
47
+ dir = mkdtempSync(join(tmpdir(), "chant-migrate-dialect-"));
48
+ seen.length = 0;
49
+ });
50
+ afterEach(() => rmSync(dir, { recursive: true, force: true }));
51
+ const file = () => {
52
+ const f = join(dir, "schema.sql");
53
+ writeFileSync(f, "CREATE TABLE t (id int);");
54
+ return f;
55
+ };
56
+
57
+ test("finds the plugin by the lexicon part, and hands the source both sides as written", async () => {
58
+ const r = await migrateCommand({ ...base, sourceFile: file(), from: "sql/postgres", to: "sql/clickhouse", output: join(dir, "out.sql"), plugins: [sqlPlugin()] });
59
+ expect(r.exitCode).toBe(0);
60
+ expect(seen).toEqual([{ from: "sql/postgres", to: "sql/clickhouse" }]);
61
+ expect(readFileSync(join(dir, "out.sql"), "utf8")).toBe("-- ddl\n");
62
+ });
63
+
64
+ test("a dialect the lexicon does not know is refused by name", async () => {
65
+ const r = await migrateCommand({ ...base, sourceFile: file(), from: "sql/postgres", to: "sql/mysql", plugins: [sqlPlugin()] });
66
+ expect(r.exitCode).toBe(1);
67
+ expect(r.error).toContain('Lexicon "sql/mysql" does not support migration from "sql/postgres"');
68
+ });
69
+
70
+ test("creates the output's directory", async () => {
71
+ const out = join(dir, "a/b/out.sql");
72
+ const r = await migrateCommand({ ...base, sourceFile: file(), from: "sql/postgres", to: "sql/clickhouse", output: out, plugins: [sqlPlugin()] });
73
+ expect(r.exitCode).toBe(0);
74
+ expect(readFileSync(out, "utf8")).toBe("-- ddl\n");
75
+ });
76
+
77
+ test("a directory is refused unless the source reads directories; then detect is skipped and content is empty", async () => {
78
+ const member = join(dir, "db");
79
+ mkdirSync(member);
80
+ const refused = await migrateCommand({ ...base, sourceFile: member, from: "sql/postgres", to: "sql/clickhouse", plugins: [sqlPlugin()] });
81
+ expect(refused.exitCode).toBe(1);
82
+ expect(refused.error).toContain("is a directory");
83
+ let got: { content: string; sourceFile?: string } | undefined;
84
+ const ok = await migrateCommand({
85
+ ...base,
86
+ sourceFile: member,
87
+ from: "sql/postgres",
88
+ to: "sql/clickhouse",
89
+ output: join(dir, "o.sql"),
90
+ plugins: [sqlPlugin({ directory: true, transform: async (content, opts) => ((got = { content, sourceFile: opts.sourceFile }), { output: "x", provenance: [], diagnostics: [] }) })],
91
+ });
92
+ expect(ok.exitCode).toBe(0);
93
+ expect(got).toEqual({ content: "", sourceFile: member });
94
+ });
95
+ });
96
+
97
+ describe("--validate with a result that checks itself", () => {
98
+ let dir: string;
99
+ beforeEach(() => {
100
+ dir = mkdtempSync(join(tmpdir(), "chant-migrate-validate-"));
101
+ });
102
+ afterEach(() => rmSync(dir, { recursive: true, force: true }));
103
+ const run = (result: Partial<MigrationResult>, extra: { strict?: boolean } = {}) => {
104
+ const f = join(dir, "schema.sql");
105
+ writeFileSync(f, "CREATE TABLE t (id int);");
106
+ return migrateCommand({ ...base, ...extra, validate: true, sourceFile: f, from: "sql/postgres", to: "sql/clickhouse", output: join(dir, "o.sql"), plugins: [sqlPlugin({ result })] });
107
+ };
108
+
109
+ test("a clean check passes and its diagnostics join the result", async () => {
110
+ const r = await run({ validate: async () => [] });
111
+ expect(r.exitCode).toBe(0);
112
+ });
113
+
114
+ test("a refused statement fails the run without --strict, and is in the diagnostics", async () => {
115
+ const r = await run({ validate: async () => [{ ruleId: "SQLRV012", severity: "error", message: "t: the emulator rejected the statement." }] });
116
+ expect(r.exitCode).toBe(1);
117
+ expect(r.diagnostics.map((d) => d.ruleId)).toEqual(["SQLRV012"]);
118
+ });
119
+
120
+ test("a server that cannot start is a validation that did not run, which fails", async () => {
121
+ const r = await run({
122
+ validate: async () => {
123
+ throw new Error("Docker is not available, so the ClickHouse emulator cannot start");
124
+ },
125
+ });
126
+ expect(r.exitCode).toBe(1);
127
+ expect(r.error).toContain("--validate did not run: Docker is not available");
128
+ });
129
+
130
+ test("without --validate the check is not run", async () => {
131
+ let ran = false;
132
+ const f = join(dir, "schema.sql");
133
+ writeFileSync(f, "CREATE TABLE t (id int);");
134
+ const r = await migrateCommand({
135
+ ...base,
136
+ sourceFile: f,
137
+ from: "sql/postgres",
138
+ to: "sql/clickhouse",
139
+ output: join(dir, "o.sql"),
140
+ plugins: [sqlPlugin({ result: { validate: async () => ((ran = true), []) } })],
141
+ });
142
+ expect(r.exitCode).toBe(0);
143
+ expect(ran).toBe(false);
144
+ });
145
+ });