@intentius/chant 0.56.0 → 0.58.0

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 (515) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +20 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +14 -8
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  34. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  35. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  36. package/dist/cli/commands/import.d.ts.map +1 -1
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  38. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  40. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  41. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/lint.d.ts.map +1 -1
  44. package/dist/cli/commands/onboard.d.ts +2 -0
  45. package/dist/cli/commands/onboard.d.ts.map +1 -1
  46. package/dist/cli/handlers/build.d.ts.map +1 -1
  47. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  48. package/dist/cli/handlers/operator.d.ts +82 -16
  49. package/dist/cli/handlers/operator.d.ts.map +1 -1
  50. package/dist/cli/handlers/run.d.ts +49 -42
  51. package/dist/cli/handlers/run.d.ts.map +1 -1
  52. package/dist/cli/main.d.ts +28 -1
  53. package/dist/cli/main.d.ts.map +1 -1
  54. package/dist/cli/mcp/op-tools.d.ts +16 -1
  55. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  56. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  57. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  58. package/dist/cli/registry.d.ts +26 -9
  59. package/dist/cli/registry.d.ts.map +1 -1
  60. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  61. package/dist/components/auto-release.d.ts +10 -20
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability.d.ts +4 -4
  64. package/dist/components/cli-support.d.ts +20 -21
  65. package/dist/components/cli-support.d.ts.map +1 -1
  66. package/dist/components/component.d.ts +3 -3
  67. package/dist/components/component.d.ts.map +1 -1
  68. package/dist/components/driver-output.d.ts.map +1 -1
  69. package/dist/components/driver.d.ts +66 -36
  70. package/dist/components/driver.d.ts.map +1 -1
  71. package/dist/components/index.d.ts +1 -2
  72. package/dist/components/index.d.ts.map +1 -1
  73. package/dist/components/manifest-persistence.d.ts +1 -9
  74. package/dist/components/manifest-persistence.d.ts.map +1 -1
  75. package/dist/components/run-progress.d.ts +6 -6
  76. package/dist/components/run-progress.d.ts.map +1 -1
  77. package/dist/components/verbs/run-agent.d.ts +9 -15
  78. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  79. package/dist/components/verbs/verify.d.ts +2 -2
  80. package/dist/deep-observation.d.ts +17 -0
  81. package/dist/deep-observation.d.ts.map +1 -1
  82. package/dist/discovery/files.d.ts +4 -4
  83. package/dist/discovery/fold-import.d.ts.map +1 -1
  84. package/dist/discovery/param-deps.d.ts +33 -0
  85. package/dist/discovery/param-deps.d.ts.map +1 -1
  86. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  87. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  88. package/dist/fold/foldable-helpers.d.ts +5 -1
  89. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  90. package/dist/fold-provenance.d.ts +236 -0
  91. package/dist/fold-provenance.d.ts.map +1 -0
  92. package/dist/graph-ops.d.ts +1 -1
  93. package/dist/held-elsewhere.d.ts +85 -0
  94. package/dist/held-elsewhere.d.ts.map +1 -0
  95. package/dist/import/ir-utils.d.ts +1 -1
  96. package/dist/import/ir-utils.d.ts.map +1 -1
  97. package/dist/import/parser.d.ts +33 -0
  98. package/dist/import/parser.d.ts.map +1 -1
  99. package/dist/index.d.ts +3 -0
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/kubectl-context.d.ts +3 -3
  102. package/dist/lexicon-config.d.ts +4 -4
  103. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  104. package/dist/lexicon.d.ts +104 -14
  105. package/dist/lexicon.d.ts.map +1 -1
  106. package/dist/lifecycle/change-set.d.ts +13 -0
  107. package/dist/lifecycle/change-set.d.ts.map +1 -1
  108. package/dist/lifecycle/deep-diff.d.ts +133 -6
  109. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  110. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  111. package/dist/lifecycle/gate-ledger.d.ts +71 -3
  112. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  113. package/dist/lifecycle/index.d.ts +1 -0
  114. package/dist/lifecycle/index.d.ts.map +1 -1
  115. package/dist/lifecycle/release-ledger.d.ts +2 -2
  116. package/dist/lifecycle/run-ledger.d.ts +53 -0
  117. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  118. package/dist/lifecycle/symptoms.d.ts +3 -3
  119. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  120. package/dist/lint/config.d.ts +81 -2
  121. package/dist/lint/config.d.ts.map +1 -1
  122. package/dist/lint/post-synth.d.ts +55 -2
  123. package/dist/lint/post-synth.d.ts.map +1 -1
  124. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  125. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  126. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  127. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  128. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  129. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  130. package/dist/lint/rules/comp/index.d.ts +1 -1
  131. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  132. package/dist/lint/rules/op/index.d.ts +16 -0
  133. package/dist/lint/rules/op/index.d.ts.map +1 -0
  134. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  135. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  136. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  137. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  138. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  139. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  140. package/dist/lint/rules/op/support.d.ts +12 -0
  141. package/dist/lint/rules/op/support.d.ts.map +1 -0
  142. package/dist/lint/suppressions.d.ts +108 -0
  143. package/dist/lint/suppressions.d.ts.map +1 -0
  144. package/dist/live-endpoint.d.ts +1 -1
  145. package/dist/op/activities/activity-contracts.d.ts +54 -0
  146. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  147. package/dist/op/activities/apply.d.ts +262 -0
  148. package/dist/op/activities/apply.d.ts.map +1 -0
  149. package/dist/op/activities/build.d.ts +13 -0
  150. package/dist/op/activities/build.d.ts.map +1 -0
  151. package/dist/op/activities/converge.d.ts +110 -0
  152. package/dist/op/activities/converge.d.ts.map +1 -0
  153. package/dist/op/activities/env-teardown.d.ts +76 -0
  154. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  155. package/dist/op/activities/guard-validate.d.ts +64 -0
  156. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  157. package/dist/op/activities/http-check.d.ts +34 -0
  158. package/dist/op/activities/http-check.d.ts.map +1 -0
  159. package/dist/op/activities/index.d.ts +31 -0
  160. package/dist/op/activities/index.d.ts.map +1 -0
  161. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  162. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  163. package/dist/op/activities/lifecycle.d.ts +42 -0
  164. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  165. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  166. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  167. package/dist/op/activities/policy.d.ts +17 -0
  168. package/dist/op/activities/policy.d.ts.map +1 -0
  169. package/dist/op/activities/reconcile.d.ts +89 -0
  170. package/dist/op/activities/reconcile.d.ts.map +1 -0
  171. package/dist/op/activities/shell.d.ts +13 -0
  172. package/dist/op/activities/shell.d.ts.map +1 -0
  173. package/dist/op/activities/teardown.d.ts +10 -0
  174. package/dist/op/activities/teardown.d.ts.map +1 -0
  175. package/dist/op/activities/util.d.ts +7 -0
  176. package/dist/op/activities/util.d.ts.map +1 -0
  177. package/dist/op/activities/wait.d.ts +28 -0
  178. package/dist/op/activities/wait.d.ts.map +1 -0
  179. package/dist/op/activities/workflow-audit.d.ts +92 -0
  180. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  181. package/dist/op/activity-contract-registry.d.ts +76 -0
  182. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  183. package/dist/op/activity-contract.d.ts +25 -18
  184. package/dist/op/activity-contract.d.ts.map +1 -1
  185. package/dist/op/activity-failure.d.ts +28 -0
  186. package/dist/op/activity-failure.d.ts.map +1 -0
  187. package/dist/op/activity-profiles.d.ts +118 -0
  188. package/dist/op/activity-profiles.d.ts.map +1 -0
  189. package/dist/op/activity-registry.d.ts +22 -38
  190. package/dist/op/activity-registry.d.ts.map +1 -1
  191. package/dist/op/activity-runtime.d.ts +3 -14
  192. package/dist/op/activity-runtime.d.ts.map +1 -1
  193. package/dist/op/builders.d.ts +84 -29
  194. package/dist/op/builders.d.ts.map +1 -1
  195. package/dist/op/composites/apply-op.d.ts +113 -0
  196. package/dist/op/composites/apply-op.d.ts.map +1 -0
  197. package/dist/op/composites/converge-op.d.ts +120 -0
  198. package/dist/op/composites/converge-op.d.ts.map +1 -0
  199. package/dist/op/composites/index.d.ts +26 -0
  200. package/dist/op/composites/index.d.ts.map +1 -0
  201. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  202. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  203. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  204. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  205. package/dist/op/composites/reconcile-op.d.ts +57 -0
  206. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  207. package/dist/op/composites/watch-op.d.ts +60 -0
  208. package/dist/op/composites/watch-op.d.ts.map +1 -0
  209. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  210. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  211. package/dist/op/converge-rule.d.ts +12 -10
  212. package/dist/op/converge-rule.d.ts.map +1 -1
  213. package/dist/op/cron.d.ts +51 -0
  214. package/dist/op/cron.d.ts.map +1 -0
  215. package/dist/op/discover.d.ts +9 -0
  216. package/dist/op/discover.d.ts.map +1 -1
  217. package/dist/op/duration.d.ts +11 -0
  218. package/dist/op/duration.d.ts.map +1 -0
  219. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  220. package/dist/op/gate.d.ts +90 -0
  221. package/dist/op/gate.d.ts.map +1 -0
  222. package/dist/op/generate-pipeline.d.ts +9 -0
  223. package/dist/op/generate-pipeline.d.ts.map +1 -1
  224. package/dist/op/index.d.ts +23 -7
  225. package/dist/op/index.d.ts.map +1 -1
  226. package/dist/op/local-executor.d.ts +114 -28
  227. package/dist/op/local-executor.d.ts.map +1 -1
  228. package/dist/op/local-output.d.ts +11 -1
  229. package/dist/op/local-output.d.ts.map +1 -1
  230. package/dist/op/op-ir.d.ts +184 -0
  231. package/dist/op/op-ir.d.ts.map +1 -0
  232. package/dist/op/op-verb-class.d.ts +10 -2
  233. package/dist/op/op-verb-class.d.ts.map +1 -1
  234. package/dist/op/operator.d.ts +30 -5
  235. package/dist/op/operator.d.ts.map +1 -1
  236. package/dist/op/receipt-store.d.ts +1 -1
  237. package/dist/op/receipt-store.d.ts.map +1 -1
  238. package/dist/op/resource.d.ts +15 -1
  239. package/dist/op/resource.d.ts.map +1 -1
  240. package/dist/op/runtime.d.ts +200 -0
  241. package/dist/op/runtime.d.ts.map +1 -0
  242. package/dist/op/runtimes/local.d.ts +29 -0
  243. package/dist/op/runtimes/local.d.ts.map +1 -0
  244. package/dist/op/step-output-ref.d.ts +15 -13
  245. package/dist/op/step-output-ref.d.ts.map +1 -1
  246. package/dist/op/types.d.ts +79 -27
  247. package/dist/op/types.d.ts.map +1 -1
  248. package/dist/ownership.d.ts +1 -1
  249. package/dist/provenance.d.ts +21 -0
  250. package/dist/provenance.d.ts.map +1 -1
  251. package/dist/serializer-walker.d.ts.map +1 -1
  252. package/dist/stack-output.d.ts +5 -0
  253. package/dist/stack-output.d.ts.map +1 -1
  254. package/package.json +6 -1
  255. package/src/audit/catalog.test.ts +79 -3
  256. package/src/audit/catalog.ts +111 -13
  257. package/src/audit/core.test.ts +26 -0
  258. package/src/audit/core.ts +61 -17
  259. package/src/audit/discover.test.ts +39 -0
  260. package/src/audit/discover.ts +91 -15
  261. package/src/audit/lineage.ts +100 -0
  262. package/src/audit/prior-art.ts +153 -0
  263. package/src/audit/proof.test.ts +67 -0
  264. package/src/audit/proof.ts +70 -0
  265. package/src/audit/report-html.ts +9 -4
  266. package/src/audit/report-model.ts +16 -2
  267. package/src/audit/report.test.ts +33 -0
  268. package/src/audit/report.ts +5 -3
  269. package/src/audit/rules-doc.test.ts +34 -2
  270. package/src/audit/rules-doc.ts +82 -9
  271. package/src/audit/secrets.ts +15 -3
  272. package/src/audit/terraform-state.test.ts +144 -0
  273. package/src/audit/terraform-state.ts +131 -0
  274. package/src/build.ts +31 -1
  275. package/src/claimed-fields.test.ts +145 -0
  276. package/src/claimed-fields.ts +208 -0
  277. package/src/cli/build-params-cli.ts +2 -2
  278. package/src/cli/command-group.ts +14 -0
  279. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  280. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  281. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  282. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  283. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  284. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  285. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  286. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  287. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  288. package/src/cli/commands/audit.test.ts +189 -11
  289. package/src/cli/commands/audit.ts +73 -27
  290. package/src/cli/commands/build.test.ts +292 -9
  291. package/src/cli/commands/build.ts +156 -24
  292. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  293. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  294. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  295. package/src/cli/commands/import.ts +6 -0
  296. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  297. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  298. package/src/cli/commands/init-lexicon.test.ts +97 -2
  299. package/src/cli/commands/init-lexicon.ts +4 -2
  300. package/src/cli/commands/init.test.ts +35 -1
  301. package/src/cli/commands/init.ts +14 -3
  302. package/src/cli/commands/lint.test.ts +48 -0
  303. package/src/cli/commands/lint.ts +123 -0
  304. package/src/cli/commands/onboard.test.ts +75 -0
  305. package/src/cli/commands/onboard.ts +54 -23
  306. package/src/cli/handlers/build.test.ts +81 -1
  307. package/src/cli/handlers/build.ts +15 -1
  308. package/src/cli/handlers/graph.test.ts +3 -3
  309. package/src/cli/handlers/lifecycle.test.ts +195 -12
  310. package/src/cli/handlers/lifecycle.ts +123 -6
  311. package/src/cli/handlers/misc.ts +1 -1
  312. package/src/cli/handlers/operator.test.ts +183 -11
  313. package/src/cli/handlers/operator.ts +260 -55
  314. package/src/cli/handlers/run.test.ts +431 -1287
  315. package/src/cli/handlers/run.ts +365 -915
  316. package/src/cli/main.test.ts +23 -15
  317. package/src/cli/main.ts +88 -33
  318. package/src/cli/mcp/op-tools.ts +147 -88
  319. package/src/cli/mcp/resource-handlers.ts +10 -37
  320. package/src/cli/mcp/resources/context.ts +11 -12
  321. package/src/cli/mcp/server.test.ts +25 -27
  322. package/src/cli/mcp/server.ts +2 -2
  323. package/src/cli/registry.ts +26 -9
  324. package/src/codegen/docs.ts +1 -1
  325. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  326. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  327. package/src/components/README.md +3 -2
  328. package/src/components/auto-release.test.ts +4 -20
  329. package/src/components/auto-release.ts +17 -42
  330. package/src/components/capability.ts +4 -4
  331. package/src/components/cli-support.test.ts +10 -5
  332. package/src/components/cli-support.ts +52 -44
  333. package/src/components/component.schema.json +2 -2
  334. package/src/components/component.ts +3 -3
  335. package/src/components/driver-output.ts +14 -2
  336. package/src/components/driver.test.ts +92 -22
  337. package/src/components/driver.ts +193 -83
  338. package/src/components/index.ts +1 -6
  339. package/src/components/manifest-persistence.test.ts +2 -20
  340. package/src/components/manifest-persistence.ts +4 -24
  341. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  342. package/src/components/run-progress.ts +6 -6
  343. package/src/components/verbs/run-agent.ts +11 -17
  344. package/src/components/verbs/verify.ts +2 -2
  345. package/src/deep-observation.test.ts +75 -0
  346. package/src/deep-observation.ts +48 -0
  347. package/src/discovery/collect.test.ts +3 -3
  348. package/src/discovery/files.ts +4 -4
  349. package/src/discovery/fold-import.ts +105 -2
  350. package/src/discovery/param-deps.test.ts +112 -1
  351. package/src/discovery/param-deps.ts +193 -0
  352. package/src/discovery/sandbox/bundle.ts +15 -1
  353. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  354. package/src/discovery/sandbox/config-wire.ts +2 -2
  355. package/src/fold/fold.test.ts +56 -0
  356. package/src/fold/foldable-helpers.ts +81 -1
  357. package/src/fold-provenance-exclusion.test.ts +186 -0
  358. package/src/fold-provenance.test.ts +495 -0
  359. package/src/fold-provenance.ts +441 -0
  360. package/src/graph-ops.test.ts +2 -2
  361. package/src/graph-ops.ts +1 -1
  362. package/src/held-elsewhere.test.ts +102 -0
  363. package/src/held-elsewhere.ts +114 -0
  364. package/src/import/ir-utils.ts +11 -1
  365. package/src/import/parser.ts +35 -0
  366. package/src/index.ts +3 -0
  367. package/src/kubectl-context.ts +3 -3
  368. package/src/lexicon-config.test.ts +5 -5
  369. package/src/lexicon-config.ts +4 -4
  370. package/src/lexicon-plugin-helpers.ts +1 -1
  371. package/src/lexicon.ts +120 -14
  372. package/src/lifecycle/change-set.test.ts +49 -0
  373. package/src/lifecycle/change-set.ts +67 -0
  374. package/src/lifecycle/converge-ledger.ts +1 -1
  375. package/src/lifecycle/deep-diff.test.ts +267 -14
  376. package/src/lifecycle/deep-diff.ts +217 -14
  377. package/src/lifecycle/deep-observe.test.ts +3 -1
  378. package/src/lifecycle/deep-observe.ts +16 -6
  379. package/src/lifecycle/gate-ledger.test.ts +74 -2
  380. package/src/lifecycle/gate-ledger.ts +143 -36
  381. package/src/lifecycle/index.ts +1 -0
  382. package/src/lifecycle/release-ledger.ts +2 -2
  383. package/src/lifecycle/run-ledger.test.ts +268 -0
  384. package/src/lifecycle/run-ledger.ts +201 -0
  385. package/src/lifecycle/symptoms.ts +3 -3
  386. package/src/lint/config.test.ts +82 -1
  387. package/src/lint/config.ts +112 -3
  388. package/src/lint/policy.test.ts +1 -1
  389. package/src/lint/post-synth.test.ts +31 -0
  390. package/src/lint/post-synth.ts +54 -1
  391. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  392. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  393. package/src/lint/rules/comp/comp.test.ts +1 -1
  394. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
  395. package/src/lint/rules/comp/index.ts +3 -3
  396. package/src/lint/rules/op/index.ts +23 -0
  397. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  398. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  399. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  400. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  401. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  402. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  403. package/src/lint/rules/op/support.ts +11 -0
  404. package/src/lint/suppressions.test.ts +163 -0
  405. package/src/lint/suppressions.ts +204 -0
  406. package/src/live-endpoint.ts +1 -1
  407. package/src/op/activities/activity-contracts.ts +66 -0
  408. package/src/op/activities/apply.test.ts +567 -0
  409. package/src/op/activities/apply.ts +662 -0
  410. package/src/op/activities/build.ts +26 -0
  411. package/src/op/activities/converge.test.ts +330 -0
  412. package/src/op/activities/converge.ts +449 -0
  413. package/src/op/activities/env-teardown.test.ts +187 -0
  414. package/src/op/activities/env-teardown.ts +171 -0
  415. package/src/op/activities/guard-validate.test.ts +139 -0
  416. package/src/op/activities/guard-validate.ts +223 -0
  417. package/src/op/activities/http-check.test.ts +48 -0
  418. package/src/op/activities/http-check.ts +55 -0
  419. package/src/op/activities/index.ts +119 -0
  420. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  421. package/src/op/activities/lexicon-upgrade.ts +673 -0
  422. package/src/op/activities/lifecycle.ts +85 -0
  423. package/src/op/activities/pipeline-audit.test.ts +67 -0
  424. package/src/op/activities/pipeline-audit.ts +201 -0
  425. package/src/op/activities/policy.test.ts +19 -0
  426. package/src/op/activities/policy.ts +37 -0
  427. package/src/op/activities/reconcile.test.ts +81 -0
  428. package/src/op/activities/reconcile.ts +187 -0
  429. package/src/op/activities/shell.ts +26 -0
  430. package/src/op/activities/teardown.ts +22 -0
  431. package/src/op/activities/util.ts +6 -0
  432. package/src/op/activities/wait.ts +69 -0
  433. package/src/op/activities/workflow-audit.test.ts +90 -0
  434. package/src/op/activities/workflow-audit.ts +203 -0
  435. package/src/op/activity-contract-registry.test.ts +98 -0
  436. package/src/op/activity-contract-registry.ts +114 -0
  437. package/src/op/activity-contract.test.ts +1 -1
  438. package/src/op/activity-contract.ts +37 -33
  439. package/src/op/activity-failure.ts +34 -0
  440. package/src/op/activity-profiles.test.ts +56 -0
  441. package/src/op/activity-profiles.ts +116 -0
  442. package/src/op/activity-registry.test.ts +37 -28
  443. package/src/op/activity-registry.ts +27 -56
  444. package/src/op/activity-runtime.ts +3 -47
  445. package/src/op/builders-exports.test.ts +0 -49
  446. package/src/op/builders-typed.test.ts +164 -0
  447. package/src/op/builders.ts +123 -39
  448. package/src/op/composites/apply-op.ts +208 -0
  449. package/src/op/composites/composites.test.ts +366 -0
  450. package/src/op/composites/converge-op.test.ts +168 -0
  451. package/src/op/composites/converge-op.ts +214 -0
  452. package/src/op/composites/index.ts +26 -0
  453. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  454. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  455. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  456. package/src/op/composites/pipeline-audit-op.ts +78 -0
  457. package/src/op/composites/reconcile-op.test.ts +51 -0
  458. package/src/op/composites/reconcile-op.ts +107 -0
  459. package/src/op/composites/watch-op.ts +108 -0
  460. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  461. package/src/op/composites/workflow-audit-op.ts +88 -0
  462. package/src/op/converge-rule.ts +12 -10
  463. package/src/op/cron.test.ts +128 -0
  464. package/src/op/cron.ts +149 -0
  465. package/src/op/discover-root.test.ts +105 -1
  466. package/src/op/discover.test.ts +6 -2
  467. package/src/op/discover.ts +84 -16
  468. package/src/op/duration.ts +21 -0
  469. package/src/op/effect-step.test.ts +26 -11
  470. package/src/op/emulator-lifecycle.ts +1 -2
  471. package/src/op/gate.ts +155 -0
  472. package/src/op/generate-pipeline.test.ts +65 -3
  473. package/src/op/generate-pipeline.ts +19 -2
  474. package/src/op/index.ts +39 -6
  475. package/src/op/local-executor.test.ts +163 -34
  476. package/src/op/local-executor.ts +370 -102
  477. package/src/op/local-output.test.ts +95 -11
  478. package/src/op/local-output.ts +33 -4
  479. package/src/op/op-ir.test.ts +281 -0
  480. package/src/op/op-ir.ts +417 -0
  481. package/src/op/op-verb-class.ts +19 -5
  482. package/src/op/op.test.ts +26 -5
  483. package/src/op/operator.test.ts +175 -6
  484. package/src/op/operator.ts +63 -16
  485. package/src/op/receipt-store.ts +1 -1
  486. package/src/op/resource.ts +20 -2
  487. package/src/op/runtime.ts +203 -0
  488. package/src/op/runtimes/local.test.ts +181 -0
  489. package/src/op/runtimes/local.ts +212 -0
  490. package/src/op/step-output-ref.ts +15 -13
  491. package/src/op/types.ts +84 -24
  492. package/src/ownership.ts +1 -1
  493. package/src/provenance.test.ts +6 -0
  494. package/src/provenance.ts +21 -1
  495. package/src/serializer-walker.test.ts +42 -0
  496. package/src/serializer-walker.ts +21 -2
  497. package/src/stack-output.ts +6 -1
  498. package/dist/cli/handlers/op-progress.d.ts +0 -90
  499. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  500. package/dist/cli/handlers/run-client.d.ts +0 -127
  501. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  502. package/dist/cli/handlers/run-report.d.ts +0 -5
  503. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  504. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  505. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  506. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  507. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  508. package/src/cli/handlers/op-progress.test.ts +0 -268
  509. package/src/cli/handlers/op-progress.ts +0 -248
  510. package/src/cli/handlers/run-client.test.ts +0 -82
  511. package/src/cli/handlers/run-client.ts +0 -219
  512. package/src/cli/handlers/run-report.test.ts +0 -62
  513. package/src/cli/handlers/run-report.ts +0 -122
  514. package/src/components/temporal-codegen-loader.ts +0 -41
  515. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -0,0 +1,164 @@
1
+ /**
2
+ * The typed step-builder wrappers over core's own base activities (chant #1288
3
+ * Stage 2, moved here from a hosting lexicon by #2114). `opts` in each is
4
+ * the activity's own `*Args` interface (`./activities/*.ts`) via `Omit`/
5
+ * `WithStepRefs`, never a hand-restated mirror, so a signature change in the
6
+ * activity is a compile error at the builder rather than a silently-dropped arg.
7
+ *
8
+ * These are asserted against the `ActivityStep` they emit — the fixed profiles
9
+ * (`policyGate`/`guardValidate` on `policyCheck`, `teardown` on `longInfra`)
10
+ * and defaults (`waitForStack` → `k8sWait`, `httpCheck`/`envTeardown`) are
11
+ * pinned here, since there is no longer a second, untyped implementation to
12
+ * compare against.
13
+ */
14
+
15
+ import { describe, test, expect } from "vitest";
16
+ import {
17
+ build,
18
+ shell,
19
+ waitForStack,
20
+ lifecycleSnapshot,
21
+ teardown,
22
+ envTeardown,
23
+ httpCheck,
24
+ policyGate,
25
+ guardValidate,
26
+ stepOutput,
27
+ type StepOutputRef,
28
+ } from "./index";
29
+
30
+ describe("typed step builders over the base activities", () => {
31
+ test("build: names chantBuild, path is positional, opts spread into args", () => {
32
+ expect(build("examples/gitlab-aws-alb-infra")).toMatchObject({
33
+ kind: "activity",
34
+ fn: "chantBuild",
35
+ args: { path: "examples/gitlab-aws-alb-infra" },
36
+ });
37
+ expect(build(".", { script: "build:aws", env: { NODE_ENV: "production" } })).toMatchObject({
38
+ fn: "chantBuild",
39
+ args: { path: ".", script: "build:aws", env: { NODE_ENV: "production" } },
40
+ });
41
+ });
42
+
43
+ test("shell: names shellCmd; env and profile route where they belong", () => {
44
+ expect(shell("npm run db:seed")).toMatchObject({ fn: "shellCmd", args: { cmd: "npm run db:seed" } });
45
+ const step = shell("docker push image", { env: { FOO: "bar" }, profile: "longInfra" });
46
+ expect(step.args).toEqual({ cmd: "docker push image", env: { FOO: "bar" } });
47
+ expect(step.profile).toBe("longInfra");
48
+ });
49
+
50
+ test("shell: cwd is reachable (the untyped builder this replaced dropped it)", () => {
51
+ const step = shell("ls", { cwd: "/tmp" });
52
+ expect(step.args?.cwd).toBe("/tmp");
53
+ });
54
+
55
+ test("waitForStack: defaults to the k8sWait profile", () => {
56
+ const step = waitForStack("alb-api", { namespace: "alb" });
57
+ expect(step).toMatchObject({ fn: "waitForStack", args: { name: "alb-api", namespace: "alb" } });
58
+ expect(step.profile).toBe("k8sWait");
59
+ });
60
+
61
+ test("lifecycleSnapshot: env is the only arg", () => {
62
+ expect(lifecycleSnapshot("staging")).toMatchObject({
63
+ fn: "lifecycleSnapshot",
64
+ args: { env: "staging" },
65
+ });
66
+ });
67
+
68
+ test("lifecycleSnapshot: .out is reachable via an id", () => {
69
+ const step = lifecycleSnapshot("staging", { id: "snap" });
70
+ const ref: StepOutputRef = step.out.env;
71
+ expect(ref.step).toBe("snap");
72
+ expect(ref.path).toBe("env");
73
+ });
74
+
75
+ test("teardown: fixed longInfra profile", () => {
76
+ const step = teardown("examples/getting-started");
77
+ expect(step).toMatchObject({ fn: "chantTeardown", args: { path: "examples/getting-started" } });
78
+ expect(step.profile).toBe("longInfra");
79
+ });
80
+
81
+ test("envTeardown: defaults to longInfra, confirmProd passes through", () => {
82
+ const step = envTeardown("prod", { confirmProd: true });
83
+ expect(step.args).toEqual({ env: "prod", confirmProd: true });
84
+ expect(step.profile).toBe("longInfra");
85
+ });
86
+
87
+ test("httpCheck: defaults to fastIdempotent", () => {
88
+ const step = httpCheck("https://example.com/health", { status: 200, contains: "ok" });
89
+ expect(step.args).toEqual({ url: "https://example.com/health", status: 200, contains: "ok" });
90
+ expect(step.profile).toBe("fastIdempotent");
91
+ });
92
+
93
+ test("policyGate: fixed policyCheck profile, path defaults to '.'", () => {
94
+ expect(policyGate()).toMatchObject({ fn: "policyGate", args: { path: "." }, profile: "policyCheck" });
95
+ expect(policyGate({ env: "staging" }).args).toEqual({ path: ".", env: "staging" });
96
+ });
97
+
98
+ test("waitForStack: accepts a StepOutputRef in a typed slot", () => {
99
+ const ref = stepOutput("build-step", "namespace");
100
+ const step = waitForStack("alb-api", { namespace: ref });
101
+ expect(step.args?.namespace).toBe(ref);
102
+ });
103
+
104
+ test("guardValidate: builds an activity step naming the guardValidate activity", () => {
105
+ const step = guardValidate("rules.guard");
106
+ expect(step.kind).toBe("activity");
107
+ expect(step.fn).toBe("guardValidate");
108
+ expect(step.args).toEqual({ rules: "rules.guard" });
109
+ expect(step.profile).toBe("policyCheck");
110
+ });
111
+
112
+ test("guardValidate: template/binary/onFinding pass through as args; id routes to the step, not args", () => {
113
+ const step = guardValidate("rules.guard", { template: "dist/out.json", binary: "/opt/bin/cfn-guard", onFinding: "report", id: "guard" });
114
+ expect(step.args).toEqual({
115
+ rules: "rules.guard",
116
+ template: "dist/out.json",
117
+ binary: "/opt/bin/cfn-guard",
118
+ onFinding: "report",
119
+ });
120
+ expect(step.id).toBe("guard");
121
+ expect(step.profile).toBe("policyCheck");
122
+ });
123
+
124
+ test("guardValidate: .out is reachable once the step is given an id", () => {
125
+ const step = guardValidate("rules.guard", { id: "guard" });
126
+ const ref: StepOutputRef = step.out.findings;
127
+ expect(ref.step).toBe("guard");
128
+ expect(ref.path).toBe("findings");
129
+ });
130
+
131
+ test("guardValidate: accepts a StepOutputRef in a typed slot", () => {
132
+ const ref = stepOutput("build-step", "outPath");
133
+ const step = guardValidate("rules.guard", { template: ref });
134
+ expect(step.args?.template).toBe(ref);
135
+ });
136
+ });
137
+
138
+ // ── Compile-time-only: authoring-time type errors (never executed) ──────────
139
+ function _typeChecksOnly(): void {
140
+ // @ts-expect-error — "environment" is not a key of ChantBuildArgs (the
141
+ // exact typo class chant #1288 names: `env` is the field, not
142
+ // `environment` — e.g. activity("lifecycleDiff", { environment: "prod" })
143
+ // silently ignored the whole arg before this).
144
+ build(".", { environment: "prod" });
145
+
146
+ // @ts-expect-error — waitForStack's intervalMs must be a number.
147
+ waitForStack("alb-api", { intervalMs: "5000" });
148
+
149
+ // @ts-expect-error — httpCheck's status must be a number.
150
+ httpCheck("https://example.com", { status: "200" });
151
+
152
+ // @ts-expect-error — policyGate has no `profile` override (fixed to
153
+ // policyCheck, single-attempt).
154
+ policyGate({ profile: "fastIdempotent" });
155
+
156
+ // @ts-expect-error — guardValidate has no `profile` override either
157
+ // (fixed to policyCheck, same reasoning as policyGate).
158
+ guardValidate("rules.guard", { profile: "fastIdempotent" });
159
+
160
+ // @ts-expect-error — onFinding only admits "report" today (#522 leaves
161
+ // issue/pull-request modes to a follow-up).
162
+ guardValidate("rules.guard", { onFinding: "issue" });
163
+ }
164
+ void _typeChecksOnly;
@@ -2,7 +2,17 @@ import { OpResource } from "./resource";
2
2
  import type { OpConfig, PhaseDefinition, StepDefinition, ActivityStep, GateStep, EffectStep } from "./types";
3
3
  import { isEffectReceipt, type EffectReceiptDeclaration } from "../effect-receipt";
4
4
  import { receiptCheckInput } from "./receipt-store";
5
- import { makeOutProxy, type StepOutputRef } from "./step-output-ref";
5
+ import { makeOutProxy, type StepOutputRef, type WithStepRefs } from "./step-output-ref";
6
+ import type { ChantBuildArgs } from "./activities/build";
7
+ import type { ShellCmdArgs } from "./activities/shell";
8
+ import type { WaitForStackArgs } from "./activities/wait";
9
+ import type { LifecycleSnapshotArgs } from "./activities/lifecycle";
10
+ import type { ChantTeardownArgs } from "./activities/teardown";
11
+ import type { EnvTeardownArgs } from "./activities/env-teardown";
12
+ import type { HttpCheckArgs } from "./activities/http-check";
13
+ import type { PolicyGateArgs } from "./activities/policy";
14
+ import type { GuardValidateArgs } from "./activities/guard-validate";
15
+ import { isValidCronExpression, cronSyntaxMessage } from "./cron";
6
16
 
7
17
  /** An `activity()` result — the plain `ActivityStep` shape plus the `.out` reference sugar (#1290). */
8
18
  export interface NamedActivityStep extends ActivityStep {
@@ -18,7 +28,7 @@ export interface NamedActivityStep extends ActivityStep {
18
28
  // ── Core builders ─────────────────────────────────────────────────────────────
19
29
 
20
30
  /**
21
- * Declare a named, phased Temporal workflow.
31
+ * Declare a named, phased Op.
22
32
  *
23
33
  * @example
24
34
  * ```ts
@@ -31,8 +41,15 @@ export interface NamedActivityStep extends ActivityStep {
31
41
  * ],
32
42
  * });
33
43
  * ```
44
+ *
45
+ * A `schedule` may be supplied for an Op that runs on a cadence (#2120); its
46
+ * cron is validated here, at construction, so a typo fails on `chant build`
47
+ * rather than becoming a schedule that silently never fires.
34
48
  */
35
49
  export function Op(config: OpConfig): InstanceType<typeof OpResource> {
50
+ if (config.schedule && !isValidCronExpression(config.schedule.cron)) {
51
+ throw new Error(`Op "${config.name}": ${cronSyntaxMessage(config.schedule.cron)}`);
52
+ }
36
53
  return new OpResource(config as unknown as Record<string, unknown>);
37
54
  }
38
55
 
@@ -85,7 +102,12 @@ export function activity(
85
102
  return step;
86
103
  }
87
104
 
88
- /** Insert a human gate — the workflow pauses until the named signal is received. */
105
+ /**
106
+ * Insert a human gate. A gate is a fact on the gate ledger, not a wait: a run
107
+ * that reaches this step with no resolution newer than its pending fact
108
+ * records the pending fact and ends `gated`. `chant approve <op> <signalName>`
109
+ * writes the resolution, and the next run walks through carrying the approver.
110
+ */
89
111
  export function gate(
90
112
  signalName: string,
91
113
  opts?: { timeout?: string; description?: string },
@@ -113,9 +135,10 @@ export function gate(
113
135
  * would sever the step from the declaration that lint, plan, and the lexicon
114
136
  * row all key on.
115
137
  *
116
- * A gate authored inside `steps` pauses only when the effect will fire (the
117
- * matched path never reaches it). The receipt-store activities (`receiptRead`,
118
- * `receiptWrite`) are provided by the receipt row's lexicon (#1835, aws).
138
+ * A gate authored inside `steps` is reached only when the effect will fire
139
+ * (the matched path never reaches it). The receipt-store activities
140
+ * (`receiptRead`, `receiptWrite`) are provided by the receipt row's lexicon
141
+ * (#1835, aws).
119
142
  *
120
143
  * @example
121
144
  * ```ts
@@ -190,10 +213,25 @@ export function takeProfileAndId(
190
213
  return { args, profile, id };
191
214
  }
192
215
 
193
- /** Run an npm build script in the given project directory. `opts.script` selects the script (default `build`, e.g. `build:aws`); `opts.env` adds env vars. */
194
- export const build = (path: string, opts?: Record<string, unknown>): ActivityStep => {
195
- const { args, profile } = takeProfile(opts);
196
- return activity("chantBuild", { path, ...args }, profile);
216
+ /**
217
+ * Extra opts every typed base-activity wrapper below accepts alongside its
218
+ * activity's own fields: the step's `profile` override and its `id` (which
219
+ * routes to the step, never into args, so `.out` works — chant #1290).
220
+ */
221
+ type StepOpts = { profile?: ActivityStep["profile"]; id?: string };
222
+
223
+ /**
224
+ * Run an npm build script in the given project directory. `opts` is
225
+ * {@link ChantBuildArgs} itself, minus the positional `path` — `script`
226
+ * selects the npm script (default `build`, e.g. `build:aws`), `env` adds
227
+ * env vars.
228
+ */
229
+ export const build = (
230
+ path: string,
231
+ opts?: WithStepRefs<Omit<ChantBuildArgs, "path">> & StepOpts,
232
+ ): NamedActivityStep => {
233
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
234
+ return activity("chantBuild", { path, ...args }, { ...(profile ? { profile } : {}), ...(id ? { id } : {}) });
197
235
  };
198
236
 
199
237
  /** Run `kubectl apply -f <manifest>`. Defaults to the `longInfra` profile (override via `opts.profile`). */
@@ -228,10 +266,17 @@ export const helmInstallPinned = (
228
266
  return activity("helmInstall", { name, contentDigest, ...args }, profile ?? "longInfra");
229
267
  };
230
268
 
231
- /** Poll for stack readiness (kubectl rollout, CloudFormation complete, etc). Defaults to the `k8sWait` profile (override via `opts.profile`). */
232
- export const waitForStack = (name: string, opts?: Record<string, unknown>): ActivityStep => {
233
- const { args, profile } = takeProfile(opts);
234
- return activity("waitForStack", { name, ...args }, profile ?? "k8sWait");
269
+ /**
270
+ * Poll until a Kubernetes Deployment/StatefulSet is fully rolled out. `opts` is
271
+ * {@link WaitForStackArgs} itself, minus the positional `name`. Defaults to the
272
+ * `k8sWait` profile (override via `opts.profile`).
273
+ */
274
+ export const waitForStack = (
275
+ name: string,
276
+ opts?: WithStepRefs<Omit<WaitForStackArgs, "name">> & StepOpts,
277
+ ): NamedActivityStep => {
278
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
279
+ return activity("waitForStack", { name, ...args }, { profile: profile ?? "k8sWait", ...(id ? { id } : {}) });
235
280
  };
236
281
 
237
282
  /** Poll any operator-backed Kubernetes resource until it reports ready, driven by a data-only readiness spec (CRD-aware; #365). Defaults to the `k8sWait` profile (override via `opts.profile`). */
@@ -246,20 +291,26 @@ export const gitlabPipeline = (name: string, opts?: Record<string, unknown>): Ac
246
291
  return activity("gitlabPipeline", { name, ...args }, profile ?? "longInfra");
247
292
  };
248
293
 
249
- /** Take a chant lifecycle snapshot for the given environment. */
250
- export const lifecycleSnapshot = (env: string): ActivityStep =>
251
- activity("lifecycleSnapshot", { env });
294
+ /**
295
+ * Take a chant lifecycle snapshot for the given environment.
296
+ * {@link LifecycleSnapshotArgs} has only `env`, which is positional here, so
297
+ * `opts` carries nothing but the step's `id` (for `.out`).
298
+ */
299
+ export const lifecycleSnapshot = (env: string, opts?: { id?: string }): NamedActivityStep =>
300
+ activity("lifecycleSnapshot", { env } satisfies LifecycleSnapshotArgs, opts?.id ? { id: opts.id } : undefined);
252
301
 
253
302
  /**
254
303
  * Run an arbitrary shell command. Tag long-running commands with a `profile`
255
304
  * (e.g. `longInfra` for a multi-GB image push) so they get the right
256
- * start-to-close timeout under both the local executor and Temporal.
305
+ * start-to-close timeout on whichever runtime hosts the run.
257
306
  */
258
307
  export const shell = (
259
308
  cmd: string,
260
- opts?: { env?: Record<string, string>; profile?: ActivityStep["profile"] },
261
- ): ActivityStep =>
262
- activity("shellCmd", { cmd, ...(opts?.env ? { env: opts.env } : {}) }, opts?.profile);
309
+ opts?: WithStepRefs<Omit<ShellCmdArgs, "cmd">> & StepOpts,
310
+ ): NamedActivityStep => {
311
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
312
+ return activity("shellCmd", { cmd, ...args }, { ...(profile ? { profile } : {}), ...(id ? { id } : {}) });
313
+ };
263
314
 
264
315
  /**
265
316
  * Ensure a `generated-once` secret exists in the target store (#1829, epic
@@ -283,9 +334,17 @@ export const ensureSecret = (
283
334
  return activity("ensureSecret", { name, keys, ...args }, profile);
284
335
  };
285
336
 
286
- /** Run `chant teardown` in the given project directory. Uses `longInfra` profile. */
287
- export const teardown = (path: string): ActivityStep =>
288
- activity("chantTeardown", { path }, "longInfra");
337
+ /**
338
+ * Run `chant teardown` in the given project directory. Fixed `longInfra`
339
+ * profile (not overridable). {@link ChantTeardownArgs} has only `path`
340
+ * (positional), so `opts` is just the step's `id` (for `.out`).
341
+ */
342
+ export const teardown = (path: string, opts?: { id?: string }): NamedActivityStep =>
343
+ activity(
344
+ "chantTeardown",
345
+ { path } satisfies ChantTeardownArgs,
346
+ { profile: "longInfra", ...(opts?.id ? { id: opts.id } : {}) },
347
+ );
289
348
 
290
349
  /**
291
350
  * Tear down one environment's marker-owned resources — the durable form of
@@ -309,13 +368,16 @@ export const teardown = (path: string): ActivityStep =>
309
368
  * ]),
310
369
  * ```
311
370
  *
312
- * `opts` also accepts `path` (the chant project directory, default the
313
- * worker's cwd). Defaults to the `longInfra` profile (override via
371
+ * `opts` also accepts `path` (the chant project directory, default the chant
372
+ * process's cwd). Defaults to the `longInfra` profile (override via
314
373
  * `opts.profile`).
315
374
  */
316
- export const envTeardown = (env: string, opts?: Record<string, unknown>): ActivityStep => {
317
- const { args, profile } = takeProfile(opts);
318
- return activity("envTeardown", { env, ...args }, profile ?? "longInfra");
375
+ export const envTeardown = (
376
+ env: string,
377
+ opts?: WithStepRefs<Omit<EnvTeardownArgs, "env">> & StepOpts,
378
+ ): NamedActivityStep => {
379
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
380
+ return activity("envTeardown", { env, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
319
381
  };
320
382
 
321
383
  /**
@@ -455,9 +517,12 @@ export const flociGcpDown = (opts?: Record<string, unknown>): ActivityStep => {
455
517
  * Defaults to the `fastIdempotent` profile. `opts` accepts `method`, `status`
456
518
  * (default any 2xx), `contains` (body substring), `retries`, `intervalMs`.
457
519
  */
458
- export const httpCheck = (url: string, opts?: Record<string, unknown>): ActivityStep => {
459
- const { args, profile } = takeProfile(opts);
460
- return activity("httpCheck", { url, ...args }, profile ?? "fastIdempotent");
520
+ export const httpCheck = (
521
+ url: string,
522
+ opts?: WithStepRefs<Omit<HttpCheckArgs, "url">> & StepOpts,
523
+ ): NamedActivityStep => {
524
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
525
+ return activity("httpCheck", { url, ...args }, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
461
526
  };
462
527
 
463
528
  /**
@@ -546,7 +611,7 @@ export const gcpDelete = (manifestPath: string, opts?: Record<string, unknown>):
546
611
  // The builder and the executor-side activity function share a name (e.g.
547
612
  // `spriteCreate`), and that is intentional: the builder here returns an
548
613
  // `activity("spriteCreate", ...)` step; `loadActivities` loads the function of
549
- // the same name from the temporal lexicon to run the HTTP. They live in
614
+ // the same name from the fly lexicon to run the HTTP. They live in
550
615
  // different modules and are both exported — exactly how `flapsUp`/`flapsDown`
551
616
  // already work. Op files import these builders; the executor resolves the
552
617
  // function by name. Endpoint override + bearer are read by the activity from
@@ -806,14 +871,33 @@ export const spritesDown = (args: {
806
871
 
807
872
  /**
808
873
  * Gate an apply on organizational policy: build the project and run its
809
- * `lint.policies` over the resolved resources, blocking the workflow on any
810
- * violation. Place it before the apply phase. `env` (or `ownership.env`) lets a
874
+ * `lint.policies` over the resolved resources, failing the step on any
875
+ * violation so no later phase runs. Place it before the apply phase. `env` (or `ownership.env`) lets a
811
876
  * policy branch on environment. Single-attempt (`policyCheck` profile) — a
812
877
  * deterministic violation is not retried.
813
878
  */
814
- export const policyGate = (opts?: { env?: string; path?: string }): ActivityStep =>
815
- activity(
879
+ export const policyGate = (opts?: WithStepRefs<PolicyGateArgs> & { id?: string }): NamedActivityStep => {
880
+ const path = (opts?.path as PolicyGateArgs["path"] | undefined) ?? ".";
881
+ const env = opts?.env;
882
+ return activity(
816
883
  "policyGate",
817
- { path: opts?.path ?? ".", ...(opts?.env ? { env: opts.env } : {}) },
818
- "policyCheck",
884
+ { path, ...(env !== undefined ? { env } : {}) },
885
+ { profile: "policyCheck", ...(opts?.id ? { id: opts.id } : {}) },
819
886
  );
887
+ };
888
+
889
+ /**
890
+ * Run an external CloudFormation Guard rules pack against the project's built
891
+ * CloudFormation template (chant #522). `opts` is {@link GuardValidateArgs}
892
+ * itself, minus the positional `rules`; `template` defaults (inside the
893
+ * activity) to `<path>/template.json`. Fixed `policyCheck` profile — same
894
+ * reasoning as {@link policyGate}: a deterministic policy check is
895
+ * single-attempt — and not overridable.
896
+ */
897
+ export const guardValidate = (
898
+ rules: string,
899
+ opts?: WithStepRefs<Omit<GuardValidateArgs, "rules">> & { id?: string },
900
+ ): NamedActivityStep => {
901
+ const { id, ...rest } = (opts ?? {}) as Omit<GuardValidateArgs, "rules"> & { id?: string };
902
+ return activity("guardValidate", { rules, ...rest }, { profile: "policyCheck", ...(id ? { id } : {}) });
903
+ };
@@ -0,0 +1,208 @@
1
+ /**
2
+ * ApplyOp composite — the code → cloud workflow as an Op.
3
+ *
4
+ * Compute the plan, then apply via the target's native mechanism. Authority
5
+ * stays with the platform (the CloudFormation stack, the Kubernetes API
6
+ * server, the ARM resource group) — chant never hosts a state file.
7
+ *
8
+ * Phases: build → plan → [approve] → apply. Deletes ride the native
9
+ * prune path, whose bound is per target: the ownership marker on `kubectl`,
10
+ * the ownership tag on `arm` (chant #1448 — previously `--mode Complete`, which
11
+ * removed resources chant never applied), the ownership label on `gcp`
12
+ * (chant #1449), the metadata marker (machines) and managed app
13
+ * (volumes/ips/certs/secrets) on `fly` (chant #1449), and the stack itself on
14
+ * `cloudformation`, which a resource CFN did not create is not in. All of
15
+ * them are owned-only. See {@link DeleteMode}.
16
+ *
17
+ * A gate is a fact, not a wait (#2119): the local executor reads the gate
18
+ * ledger, and a run that finds no resolution ends `gated` with the `chant
19
+ * approve <op> <gate>` line to run. Approve, run again, and the same Op
20
+ * converges — no durable workflow engine is involved.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // additive, local executor
25
+ * export const { op } = ApplyOp({ name: "prod-apply", env: "prod", target: "kubectl" });
26
+ *
27
+ * // gated destructive apply — `chant approve prod-apply approve-apply`, then re-run
28
+ * export const { op } = ApplyOp({
29
+ * name: "prod-apply",
30
+ * env: "prod",
31
+ * target: "kubectl",
32
+ * delete: "gated",
33
+ * gate: { signalName: "approve-apply", description: "Approve prod apply with deletes" },
34
+ * });
35
+ * ```
36
+ *
37
+ * @see #112 — stateless-authoritative state model + live import
38
+ */
39
+
40
+ import { Op, phase, activity, gate } from "../builders";
41
+ import type { OpResource } from "../resource";
42
+ import { defaultOutput, hasNativeRollback, type ApplyTarget, type DeleteMode } from "../activities/apply";
43
+
44
+ export interface ApplyOpConfig {
45
+ /** Op name (kebab-case). */
46
+ name: string;
47
+ /** Environment — CFN stack name / ARM resource group / kube context env;
48
+ * a log label on `gcp` and `fly`. */
49
+ env: string;
50
+ /** Native apply mechanism. Default: "kubectl". */
51
+ target?: ApplyTarget;
52
+ /** Built manifest/template path. Default per target: `dist` (dir) for kubectl,
53
+ * `template.json` (file) for CloudFormation/ARM, `dist/gcp.yaml` for gcp,
54
+ * `dist/fly.json` for fly. Must match your build output. */
55
+ output?: string;
56
+ /** Project directory to build. Default: ".". */
57
+ path?: string;
58
+ /** Delete handling. Default: "never". */
59
+ delete?: DeleteMode;
60
+ /**
61
+ * Effect handling (#1834, epic #1703 decision 6). `"gated"` routes the run
62
+ * through the approval gate whenever the plan proposes an effect, so the Plan
63
+ * phase's effect-will-fire rows (#1832) are reviewed before any effect
64
+ * runs. A run that reaches the gate unapproved ends `gated` and is answered
65
+ * by `chant approve`, the same shape `delete: "gated"` has. The generic
66
+ * apply itself never writes a receipt regardless (#1832); only an
67
+ * `effect()` step does, on success, last.
68
+ */
69
+ effects?: "gated";
70
+ /**
71
+ * Approval gate before the apply. Implied when `delete: "gated"`; may also be
72
+ * set explicitly. Omit `signalName` to default to `approve-<name>`. The gate
73
+ * is resolved by `chant approve` on the ledger (#2119), which the next run
74
+ * reads; nothing waits in the meantime.
75
+ */
76
+ gate?: { signalName?: string; timeout?: string; description?: string };
77
+ /**
78
+ * Saga-style rollback on partial apply failure, run as an `onFailure` phase.
79
+ *
80
+ * Compensation is total or refused (#1449): it only builds when the target
81
+ * has a rollback to run — a mapped native one (`cloudformation`, the aws
82
+ * lexicon's `rollbackStack`) or an explicit `{ command }`. Asking for it
83
+ * (`true`, or an object without a `command`) on any other target fails at
84
+ * build time rather than warning at rollback time.
85
+ *
86
+ * Defaults on for a destructive apply (`delete !== "never"`) when the target
87
+ * has a native rollback; a destructive apply on a target without one gets no
88
+ * compensation phase unless a `{ command }` supplies the rollback. Pass
89
+ * `false` to disable.
90
+ */
91
+ compensate?: boolean | { command?: string };
92
+ /**
93
+ * kubectl target only (chant #1075). Let the server-side apply take
94
+ * ownership of fields another field manager already owns, instead of failing
95
+ * with a conflict naming them.
96
+ *
97
+ * Off unless set, and chant never turns it on by itself — a conflict means
98
+ * something else in the cluster believes it owns that field, and deciding
99
+ * otherwise is a deliberate act. Set it when chant is meant to be the
100
+ * authority for those fields (adopting objects a previous `kubectl apply`
101
+ * created is the usual case).
102
+ */
103
+ forceConflicts?: boolean;
104
+ }
105
+
106
+ export interface ApplyOpResources {
107
+ /** Op resource — the build→plan→[approve]→apply Op. */
108
+ op: InstanceType<typeof OpResource>;
109
+ }
110
+
111
+ export function ApplyOp(config: ApplyOpConfig): ApplyOpResources {
112
+ const target = config.target ?? "kubectl";
113
+ const output = config.output ?? defaultOutput(target);
114
+ const deleteMode = config.delete ?? "never";
115
+ const gated = deleteMode === "gated" || config.effects === "gated" || config.gate !== undefined;
116
+
117
+ const phases = [
118
+ phase("Build", [activity("chantBuild", { path: config.path ?? "." })]),
119
+ phase("Plan", [
120
+ {
121
+ kind: "activity" as const,
122
+ fn: "lifecycleDiff",
123
+ args: { env: config.env, live: true },
124
+ outcomeAttribute: { name: "Drift", from: "drifted" },
125
+ },
126
+ ]),
127
+ ];
128
+
129
+ if (gated) {
130
+ phases.push(
131
+ phase("Approve", [
132
+ gate(config.gate?.signalName ?? `approve-${config.name}`, {
133
+ ...(config.gate?.timeout ? { timeout: config.gate.timeout } : {}),
134
+ description:
135
+ config.gate?.description ??
136
+ `Approve apply to ${config.env} (delete mode: ${deleteMode}` +
137
+ `${config.effects === "gated" ? ", effects: gated" : ""})`,
138
+ }),
139
+ ]),
140
+ );
141
+ }
142
+
143
+ phases.push(
144
+ phase("Apply", [
145
+ activity(
146
+ "nativeApply",
147
+ {
148
+ target,
149
+ env: config.env,
150
+ output,
151
+ deleteMode,
152
+ // Only present when the author asked for it, so an Op that does not
153
+ // mention conflicts serializes exactly as it always has.
154
+ ...(config.forceConflicts !== undefined ? { forceConflicts: config.forceConflicts } : {}),
155
+ },
156
+ "longInfra",
157
+ ),
158
+ ]),
159
+ );
160
+
161
+ // Compensation is total or refused (#1449). A rollback path is either the
162
+ // target's mapped native rollback (cloudformation's rollbackStack) or an
163
+ // explicit command; without one there is nothing a Rollback phase could run,
164
+ // so asking for one is refused here — at build time, with the op named —
165
+ // rather than surfacing as a warn when the rollback is already needed.
166
+ const compensateCommand =
167
+ typeof config.compensate === "object" ? config.compensate.command : undefined;
168
+ const rollbackAvailable = hasNativeRollback(target) || compensateCommand !== undefined;
169
+ if (config.compensate !== undefined && config.compensate !== false && !rollbackAvailable) {
170
+ throw new Error(
171
+ `ApplyOp "${config.name}": compensate is enabled, but target "${target}" has no automatic ` +
172
+ `rollback — the only mapped one today is cloudformation's rollbackStack. Either supply ` +
173
+ `compensate: { command: "..." } with a rollback of your own, or set compensate: false.`,
174
+ );
175
+ }
176
+
177
+ // Compensation defaults on for destructive applies — a partial failure should
178
+ // unwind rather than leave the cloud half-applied — but only where a rollback
179
+ // path exists; a destructive apply on a rollback-less target gets no
180
+ // compensation phase rather than one that could only warn.
181
+ const compensateDefault = deleteMode !== "never" && rollbackAvailable;
182
+ const compensateEnabled = config.compensate === undefined ? compensateDefault : config.compensate !== false;
183
+
184
+ const op = Op({
185
+ name: config.name,
186
+ overview: `Apply declared source to the ${config.env} environment (code → cloud)`,
187
+ labels: {
188
+ Apply: "true",
189
+ Env: config.env,
190
+ },
191
+ phases,
192
+ ...(compensateEnabled
193
+ ? {
194
+ onFailure: [
195
+ phase("Rollback", [
196
+ activity("compensateApply", {
197
+ target,
198
+ env: config.env,
199
+ ...(compensateCommand ? { command: compensateCommand } : {}),
200
+ }),
201
+ ]),
202
+ ],
203
+ }
204
+ : {}),
205
+ });
206
+
207
+ return { op };
208
+ }