@intentius/chant 0.57.0 → 0.59.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 (558) 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 +36 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +26 -9
  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/carve-bridge.d.ts.map +1 -1
  34. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  35. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  36. package/dist/cli/commands/check-lexicon-examples.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 +13 -0
  44. package/dist/cli/commands/lint.d.ts.map +1 -1
  45. package/dist/cli/commands/onboard.d.ts +2 -0
  46. package/dist/cli/commands/onboard.d.ts.map +1 -1
  47. package/dist/cli/handlers/build.d.ts.map +1 -1
  48. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  49. package/dist/cli/handlers/operator.d.ts +82 -16
  50. package/dist/cli/handlers/operator.d.ts.map +1 -1
  51. package/dist/cli/handlers/run.d.ts +49 -42
  52. package/dist/cli/handlers/run.d.ts.map +1 -1
  53. package/dist/cli/main.d.ts +12 -1
  54. package/dist/cli/main.d.ts.map +1 -1
  55. package/dist/cli/mcp/op-tools.d.ts +16 -1
  56. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  57. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  58. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  59. package/dist/cli/plugins.d.ts +22 -0
  60. package/dist/cli/plugins.d.ts.map +1 -1
  61. package/dist/cli/registry.d.ts +40 -9
  62. package/dist/cli/registry.d.ts.map +1 -1
  63. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  64. package/dist/components/auto-release.d.ts +10 -20
  65. package/dist/components/auto-release.d.ts.map +1 -1
  66. package/dist/components/capability.d.ts +4 -4
  67. package/dist/components/cli-support.d.ts +24 -22
  68. package/dist/components/cli-support.d.ts.map +1 -1
  69. package/dist/components/component.d.ts +21 -6
  70. package/dist/components/component.d.ts.map +1 -1
  71. package/dist/components/driver-output.d.ts.map +1 -1
  72. package/dist/components/driver.d.ts +73 -37
  73. package/dist/components/driver.d.ts.map +1 -1
  74. package/dist/components/index.d.ts +1 -2
  75. package/dist/components/index.d.ts.map +1 -1
  76. package/dist/components/manifest-persistence.d.ts +1 -9
  77. package/dist/components/manifest-persistence.d.ts.map +1 -1
  78. package/dist/components/run-progress.d.ts +6 -6
  79. package/dist/components/run-progress.d.ts.map +1 -1
  80. package/dist/components/verbs/run-agent.d.ts +10 -22
  81. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  82. package/dist/components/verbs/verify.d.ts +2 -2
  83. package/dist/deep-observation.d.ts +17 -0
  84. package/dist/deep-observation.d.ts.map +1 -1
  85. package/dist/detectLexicon.d.ts +13 -0
  86. package/dist/detectLexicon.d.ts.map +1 -1
  87. package/dist/discovery/files.d.ts +4 -4
  88. package/dist/discovery/fold-import.d.ts.map +1 -1
  89. package/dist/discovery/param-deps.d.ts +33 -0
  90. package/dist/discovery/param-deps.d.ts.map +1 -1
  91. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  92. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  93. package/dist/fold/foldable-helpers.d.ts +5 -1
  94. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  95. package/dist/fold-provenance.d.ts +236 -0
  96. package/dist/fold-provenance.d.ts.map +1 -0
  97. package/dist/graph-ops.d.ts +1 -1
  98. package/dist/held-elsewhere.d.ts +85 -0
  99. package/dist/held-elsewhere.d.ts.map +1 -0
  100. package/dist/index.d.ts +3 -0
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/kubectl-context.d.ts +3 -3
  103. package/dist/lexicon-config.d.ts +4 -4
  104. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  105. package/dist/lexicon.d.ts +273 -16
  106. package/dist/lexicon.d.ts.map +1 -1
  107. package/dist/lifecycle/change-set.d.ts +13 -0
  108. package/dist/lifecycle/change-set.d.ts.map +1 -1
  109. package/dist/lifecycle/deep-diff.d.ts +133 -6
  110. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  111. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  112. package/dist/lifecycle/gate-ledger.d.ts +79 -3
  113. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  114. package/dist/lifecycle/index.d.ts +1 -0
  115. package/dist/lifecycle/index.d.ts.map +1 -1
  116. package/dist/lifecycle/release-ledger.d.ts +2 -2
  117. package/dist/lifecycle/run-ledger.d.ts +53 -0
  118. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  119. package/dist/lifecycle/symptoms.d.ts +3 -3
  120. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  121. package/dist/lint/config.d.ts +81 -2
  122. package/dist/lint/config.d.ts.map +1 -1
  123. package/dist/lint/post-synth.d.ts +55 -2
  124. package/dist/lint/post-synth.d.ts.map +1 -1
  125. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  126. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  127. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  128. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  129. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  130. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  131. package/dist/lint/rules/comp/index.d.ts +1 -1
  132. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  133. package/dist/lint/rules/op/index.d.ts +16 -0
  134. package/dist/lint/rules/op/index.d.ts.map +1 -0
  135. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  136. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  137. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  138. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  139. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  140. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  141. package/dist/lint/rules/op/support.d.ts +12 -0
  142. package/dist/lint/rules/op/support.d.ts.map +1 -0
  143. package/dist/lint/suppressions.d.ts +108 -0
  144. package/dist/lint/suppressions.d.ts.map +1 -0
  145. package/dist/live-endpoint.d.ts +1 -1
  146. package/dist/op/activities/activity-contracts.d.ts +54 -0
  147. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  148. package/dist/op/activities/apply.d.ts +262 -0
  149. package/dist/op/activities/apply.d.ts.map +1 -0
  150. package/dist/op/activities/build.d.ts +13 -0
  151. package/dist/op/activities/build.d.ts.map +1 -0
  152. package/dist/op/activities/converge.d.ts +110 -0
  153. package/dist/op/activities/converge.d.ts.map +1 -0
  154. package/dist/op/activities/env-teardown.d.ts +76 -0
  155. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  156. package/dist/op/activities/guard-validate.d.ts +64 -0
  157. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  158. package/dist/op/activities/http-check.d.ts +34 -0
  159. package/dist/op/activities/http-check.d.ts.map +1 -0
  160. package/dist/op/activities/index.d.ts +31 -0
  161. package/dist/op/activities/index.d.ts.map +1 -0
  162. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  163. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  164. package/dist/op/activities/lifecycle.d.ts +42 -0
  165. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  166. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  167. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  168. package/dist/op/activities/policy.d.ts +17 -0
  169. package/dist/op/activities/policy.d.ts.map +1 -0
  170. package/dist/op/activities/reconcile.d.ts +149 -0
  171. package/dist/op/activities/reconcile.d.ts.map +1 -0
  172. package/dist/op/activities/shell.d.ts +13 -0
  173. package/dist/op/activities/shell.d.ts.map +1 -0
  174. package/dist/op/activities/teardown.d.ts +10 -0
  175. package/dist/op/activities/teardown.d.ts.map +1 -0
  176. package/dist/op/activities/util.d.ts +7 -0
  177. package/dist/op/activities/util.d.ts.map +1 -0
  178. package/dist/op/activities/wait.d.ts +28 -0
  179. package/dist/op/activities/wait.d.ts.map +1 -0
  180. package/dist/op/activities/workflow-audit.d.ts +92 -0
  181. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  182. package/dist/op/activity-contract-registry.d.ts +76 -0
  183. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  184. package/dist/op/activity-contract.d.ts +25 -18
  185. package/dist/op/activity-contract.d.ts.map +1 -1
  186. package/dist/op/activity-failure.d.ts +28 -0
  187. package/dist/op/activity-failure.d.ts.map +1 -0
  188. package/dist/op/activity-profiles.d.ts +118 -0
  189. package/dist/op/activity-profiles.d.ts.map +1 -0
  190. package/dist/op/activity-registry.d.ts +22 -38
  191. package/dist/op/activity-registry.d.ts.map +1 -1
  192. package/dist/op/activity-runtime.d.ts +3 -14
  193. package/dist/op/activity-runtime.d.ts.map +1 -1
  194. package/dist/op/builders.d.ts +85 -30
  195. package/dist/op/builders.d.ts.map +1 -1
  196. package/dist/op/change-signal.d.ts +91 -0
  197. package/dist/op/change-signal.d.ts.map +1 -0
  198. package/dist/op/composites/apply-op.d.ts +118 -0
  199. package/dist/op/composites/apply-op.d.ts.map +1 -0
  200. package/dist/op/composites/converge-op.d.ts +120 -0
  201. package/dist/op/composites/converge-op.d.ts.map +1 -0
  202. package/dist/op/composites/index.d.ts +26 -0
  203. package/dist/op/composites/index.d.ts.map +1 -0
  204. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  205. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  206. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  207. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  208. package/dist/op/composites/reconcile-op.d.ts +57 -0
  209. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  210. package/dist/op/composites/watch-op.d.ts +60 -0
  211. package/dist/op/composites/watch-op.d.ts.map +1 -0
  212. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  213. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  214. package/dist/op/converge-rule.d.ts +12 -10
  215. package/dist/op/converge-rule.d.ts.map +1 -1
  216. package/dist/op/cron.d.ts +51 -0
  217. package/dist/op/cron.d.ts.map +1 -0
  218. package/dist/op/discover.d.ts +9 -0
  219. package/dist/op/discover.d.ts.map +1 -1
  220. package/dist/op/duration.d.ts +11 -0
  221. package/dist/op/duration.d.ts.map +1 -0
  222. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  223. package/dist/op/gate-name.d.ts +40 -0
  224. package/dist/op/gate-name.d.ts.map +1 -0
  225. package/dist/op/gate-summary.d.ts +43 -0
  226. package/dist/op/gate-summary.d.ts.map +1 -0
  227. package/dist/op/gate.d.ts +90 -0
  228. package/dist/op/gate.d.ts.map +1 -0
  229. package/dist/op/generate-pipeline.d.ts +9 -0
  230. package/dist/op/generate-pipeline.d.ts.map +1 -1
  231. package/dist/op/index.d.ts +29 -9
  232. package/dist/op/index.d.ts.map +1 -1
  233. package/dist/op/local-executor.d.ts +114 -28
  234. package/dist/op/local-executor.d.ts.map +1 -1
  235. package/dist/op/local-output.d.ts +11 -1
  236. package/dist/op/local-output.d.ts.map +1 -1
  237. package/dist/op/op-ir.d.ts +185 -0
  238. package/dist/op/op-ir.d.ts.map +1 -0
  239. package/dist/op/op-verb-class.d.ts +10 -2
  240. package/dist/op/op-verb-class.d.ts.map +1 -1
  241. package/dist/op/operator.d.ts +93 -5
  242. package/dist/op/operator.d.ts.map +1 -1
  243. package/dist/op/receipt-store.d.ts +1 -1
  244. package/dist/op/receipt-store.d.ts.map +1 -1
  245. package/dist/op/resource.d.ts +15 -1
  246. package/dist/op/resource.d.ts.map +1 -1
  247. package/dist/op/runtime.d.ts +200 -0
  248. package/dist/op/runtime.d.ts.map +1 -0
  249. package/dist/op/runtimes/local.d.ts +29 -0
  250. package/dist/op/runtimes/local.d.ts.map +1 -0
  251. package/dist/op/step-output-ref.d.ts +15 -13
  252. package/dist/op/step-output-ref.d.ts.map +1 -1
  253. package/dist/op/types.d.ts +96 -29
  254. package/dist/op/types.d.ts.map +1 -1
  255. package/dist/ownership.d.ts +1 -1
  256. package/dist/provenance.d.ts +21 -0
  257. package/dist/provenance.d.ts.map +1 -1
  258. package/dist/serializer-walker.d.ts.map +1 -1
  259. package/dist/terraform/bridge.d.ts +26 -7
  260. package/dist/terraform/bridge.d.ts.map +1 -1
  261. package/dist/terraform/carve-provider.d.ts +28 -2
  262. package/dist/terraform/carve-provider.d.ts.map +1 -1
  263. package/dist/terraform/data-source-shape.d.ts +77 -0
  264. package/dist/terraform/data-source-shape.d.ts.map +1 -0
  265. package/dist/terraform/graph.d.ts.map +1 -1
  266. package/dist/terraform/providers/kubernetes.d.ts +5 -0
  267. package/dist/terraform/providers/kubernetes.d.ts.map +1 -1
  268. package/dist/terraform/tier-map.d.ts +16 -4
  269. package/dist/terraform/tier-map.d.ts.map +1 -1
  270. package/dist/terraform/types.d.ts +8 -0
  271. package/dist/terraform/types.d.ts.map +1 -1
  272. package/package.json +6 -1
  273. package/src/audit/catalog.test.ts +79 -3
  274. package/src/audit/catalog.ts +111 -13
  275. package/src/audit/core.test.ts +26 -0
  276. package/src/audit/core.ts +84 -18
  277. package/src/audit/discover.test.ts +39 -0
  278. package/src/audit/discover.ts +202 -18
  279. package/src/audit/lineage.ts +100 -0
  280. package/src/audit/prior-art.ts +153 -0
  281. package/src/audit/proof.test.ts +67 -0
  282. package/src/audit/proof.ts +70 -0
  283. package/src/audit/report-html.ts +9 -4
  284. package/src/audit/report-model.ts +16 -2
  285. package/src/audit/report.test.ts +33 -0
  286. package/src/audit/report.ts +5 -3
  287. package/src/audit/rules-doc.test.ts +34 -2
  288. package/src/audit/rules-doc.ts +82 -9
  289. package/src/audit/secrets.ts +15 -3
  290. package/src/audit/terraform-state.test.ts +144 -0
  291. package/src/audit/terraform-state.ts +131 -0
  292. package/src/build.ts +31 -1
  293. package/src/claimed-fields.test.ts +145 -0
  294. package/src/claimed-fields.ts +208 -0
  295. package/src/cli/build-params-cli.ts +2 -2
  296. package/src/cli/command-group.ts +14 -0
  297. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  298. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  299. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  300. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  301. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  302. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  303. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  304. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  305. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  306. package/src/cli/commands/audit.test.ts +191 -11
  307. package/src/cli/commands/audit.ts +78 -28
  308. package/src/cli/commands/build.test.ts +330 -9
  309. package/src/cli/commands/build.ts +170 -24
  310. package/src/cli/commands/carve-bridge.test.ts +237 -14
  311. package/src/cli/commands/carve-bridge.ts +21 -17
  312. package/src/cli/commands/carve-emit-k8s.test.ts +17 -10
  313. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  314. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  315. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  316. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  317. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  318. package/src/cli/commands/init-lexicon.test.ts +97 -2
  319. package/src/cli/commands/init-lexicon.ts +4 -2
  320. package/src/cli/commands/init.test.ts +35 -1
  321. package/src/cli/commands/init.ts +14 -3
  322. package/src/cli/commands/lint.test.ts +194 -1
  323. package/src/cli/commands/lint.ts +205 -7
  324. package/src/cli/commands/onboard.test.ts +75 -0
  325. package/src/cli/commands/onboard.ts +54 -23
  326. package/src/cli/handlers/build.test.ts +81 -1
  327. package/src/cli/handlers/build.ts +15 -1
  328. package/src/cli/handlers/graph.test.ts +3 -3
  329. package/src/cli/handlers/lifecycle.test.ts +195 -12
  330. package/src/cli/handlers/lifecycle.ts +123 -6
  331. package/src/cli/handlers/misc.ts +1 -1
  332. package/src/cli/handlers/operator.test.ts +183 -11
  333. package/src/cli/handlers/operator.ts +341 -55
  334. package/src/cli/handlers/run.test.ts +568 -1295
  335. package/src/cli/handlers/run.ts +446 -912
  336. package/src/cli/main.test.ts +22 -16
  337. package/src/cli/main.ts +66 -33
  338. package/src/cli/mcp/op-tools.ts +147 -88
  339. package/src/cli/mcp/resource-handlers.ts +10 -37
  340. package/src/cli/mcp/resources/context.ts +11 -12
  341. package/src/cli/mcp/server.test.ts +25 -27
  342. package/src/cli/mcp/server.ts +2 -2
  343. package/src/cli/plugins.test.ts +68 -2
  344. package/src/cli/plugins.ts +39 -0
  345. package/src/cli/registry.ts +40 -9
  346. package/src/codegen/docs.ts +1 -1
  347. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  348. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  349. package/src/components/README.md +4 -3
  350. package/src/components/__fixtures__/neo4j-fanout.json +1 -1
  351. package/src/components/auto-release.test.ts +4 -20
  352. package/src/components/auto-release.ts +17 -42
  353. package/src/components/capability.ts +4 -4
  354. package/src/components/cli-support.test.ts +28 -12
  355. package/src/components/cli-support.ts +60 -47
  356. package/src/components/component-schema.test.ts +18 -2
  357. package/src/components/component.schema.json +18 -5
  358. package/src/components/component.test.ts +2 -2
  359. package/src/components/component.ts +27 -7
  360. package/src/components/config-defaults.test.ts +2 -2
  361. package/src/components/driver-output.ts +14 -2
  362. package/src/components/driver.test.ts +109 -20
  363. package/src/components/driver.ts +201 -84
  364. package/src/components/index.ts +1 -6
  365. package/src/components/manifest-persistence.test.ts +2 -20
  366. package/src/components/manifest-persistence.ts +4 -24
  367. package/src/components/pilots/neo4j-fanout.pilot.ts +3 -3
  368. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  369. package/src/components/run-progress.ts +6 -6
  370. package/src/components/verbs/run-agent.test.ts +19 -0
  371. package/src/components/verbs/run-agent.ts +12 -24
  372. package/src/components/verbs/verify.ts +2 -2
  373. package/src/deep-observation.test.ts +75 -0
  374. package/src/deep-observation.ts +48 -0
  375. package/src/detectLexicon.ts +18 -1
  376. package/src/discovery/collect.test.ts +3 -3
  377. package/src/discovery/files.ts +4 -4
  378. package/src/discovery/fold-import.test.ts +1 -1
  379. package/src/discovery/fold-import.ts +105 -2
  380. package/src/discovery/param-deps.test.ts +112 -1
  381. package/src/discovery/param-deps.ts +193 -0
  382. package/src/discovery/sandbox/bundle.ts +15 -1
  383. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  384. package/src/discovery/sandbox/config-wire.ts +2 -2
  385. package/src/fold/fold.test.ts +56 -0
  386. package/src/fold/foldable-helpers.ts +82 -2
  387. package/src/fold-provenance-exclusion.test.ts +186 -0
  388. package/src/fold-provenance.test.ts +495 -0
  389. package/src/fold-provenance.ts +441 -0
  390. package/src/graph-ops.test.ts +3 -3
  391. package/src/graph-ops.ts +1 -1
  392. package/src/held-elsewhere.test.ts +102 -0
  393. package/src/held-elsewhere.ts +114 -0
  394. package/src/index.ts +3 -0
  395. package/src/kubectl-context.ts +3 -3
  396. package/src/lexicon-config.test.ts +5 -5
  397. package/src/lexicon-config.ts +4 -4
  398. package/src/lexicon-plugin-helpers.ts +1 -1
  399. package/src/lexicon.ts +296 -16
  400. package/src/lifecycle/change-set.test.ts +49 -0
  401. package/src/lifecycle/change-set.ts +67 -0
  402. package/src/lifecycle/converge-ledger.ts +1 -1
  403. package/src/lifecycle/deep-diff.test.ts +267 -14
  404. package/src/lifecycle/deep-diff.ts +217 -14
  405. package/src/lifecycle/deep-observe.test.ts +3 -1
  406. package/src/lifecycle/deep-observe.ts +16 -6
  407. package/src/lifecycle/gate-ledger.test.ts +74 -2
  408. package/src/lifecycle/gate-ledger.ts +154 -36
  409. package/src/lifecycle/index.ts +1 -0
  410. package/src/lifecycle/release-ledger.ts +2 -2
  411. package/src/lifecycle/run-ledger.test.ts +268 -0
  412. package/src/lifecycle/run-ledger.ts +201 -0
  413. package/src/lifecycle/symptoms.ts +3 -3
  414. package/src/lint/config.test.ts +82 -1
  415. package/src/lint/config.ts +112 -3
  416. package/src/lint/pipeline-change-gate.test.ts +2 -2
  417. package/src/lint/policy.test.ts +1 -1
  418. package/src/lint/post-synth.test.ts +31 -0
  419. package/src/lint/post-synth.ts +54 -1
  420. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  421. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  422. package/src/lint/rules/comp/comp.test.ts +27 -1
  423. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +76 -0
  424. package/src/lint/rules/comp/index.ts +3 -3
  425. package/src/lint/rules/op/index.ts +23 -0
  426. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  427. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  428. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  429. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  430. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  431. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  432. package/src/lint/rules/op/support.ts +11 -0
  433. package/src/lint/suppressions.test.ts +163 -0
  434. package/src/lint/suppressions.ts +204 -0
  435. package/src/live-endpoint.ts +1 -1
  436. package/src/op/activities/activity-contracts.ts +66 -0
  437. package/src/op/activities/apply.test.ts +567 -0
  438. package/src/op/activities/apply.ts +662 -0
  439. package/src/op/activities/build.ts +26 -0
  440. package/src/op/activities/converge.test.ts +330 -0
  441. package/src/op/activities/converge.ts +449 -0
  442. package/src/op/activities/env-teardown.test.ts +187 -0
  443. package/src/op/activities/env-teardown.ts +171 -0
  444. package/src/op/activities/guard-validate.test.ts +139 -0
  445. package/src/op/activities/guard-validate.ts +223 -0
  446. package/src/op/activities/http-check.test.ts +48 -0
  447. package/src/op/activities/http-check.ts +55 -0
  448. package/src/op/activities/index.ts +119 -0
  449. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  450. package/src/op/activities/lexicon-upgrade.ts +673 -0
  451. package/src/op/activities/lifecycle.ts +85 -0
  452. package/src/op/activities/pipeline-audit.test.ts +67 -0
  453. package/src/op/activities/pipeline-audit.ts +201 -0
  454. package/src/op/activities/policy.test.ts +19 -0
  455. package/src/op/activities/policy.ts +37 -0
  456. package/src/op/activities/reconcile.test.ts +161 -0
  457. package/src/op/activities/reconcile.ts +354 -0
  458. package/src/op/activities/shell.ts +26 -0
  459. package/src/op/activities/teardown.ts +22 -0
  460. package/src/op/activities/util.ts +6 -0
  461. package/src/op/activities/wait.ts +69 -0
  462. package/src/op/activities/workflow-audit.test.ts +90 -0
  463. package/src/op/activities/workflow-audit.ts +203 -0
  464. package/src/op/activity-contract-registry.test.ts +98 -0
  465. package/src/op/activity-contract-registry.ts +114 -0
  466. package/src/op/activity-contract.test.ts +1 -1
  467. package/src/op/activity-contract.ts +37 -33
  468. package/src/op/activity-failure.ts +34 -0
  469. package/src/op/activity-profiles.test.ts +56 -0
  470. package/src/op/activity-profiles.ts +116 -0
  471. package/src/op/activity-registry.test.ts +37 -28
  472. package/src/op/activity-registry.ts +27 -56
  473. package/src/op/activity-runtime.ts +3 -47
  474. package/src/op/builders-exports.test.ts +0 -49
  475. package/src/op/builders-typed.test.ts +164 -0
  476. package/src/op/builders.ts +125 -41
  477. package/src/op/change-signal.test.ts +117 -0
  478. package/src/op/change-signal.ts +169 -0
  479. package/src/op/composites/apply-op.ts +218 -0
  480. package/src/op/composites/composites.test.ts +379 -0
  481. package/src/op/composites/converge-op.test.ts +168 -0
  482. package/src/op/composites/converge-op.ts +214 -0
  483. package/src/op/composites/index.ts +26 -0
  484. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  485. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  486. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  487. package/src/op/composites/pipeline-audit-op.ts +78 -0
  488. package/src/op/composites/reconcile-op.test.ts +51 -0
  489. package/src/op/composites/reconcile-op.ts +110 -0
  490. package/src/op/composites/watch-op.ts +108 -0
  491. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  492. package/src/op/composites/workflow-audit-op.ts +88 -0
  493. package/src/op/converge-rule.ts +12 -10
  494. package/src/op/cron.test.ts +128 -0
  495. package/src/op/cron.ts +149 -0
  496. package/src/op/discover-root.test.ts +105 -1
  497. package/src/op/discover.test.ts +6 -2
  498. package/src/op/discover.ts +84 -16
  499. package/src/op/duration.ts +21 -0
  500. package/src/op/effect-step.test.ts +29 -14
  501. package/src/op/emulator-lifecycle.ts +1 -2
  502. package/src/op/gate-name.test.ts +65 -0
  503. package/src/op/gate-name.ts +60 -0
  504. package/src/op/gate-summary.ts +84 -0
  505. package/src/op/gate.ts +155 -0
  506. package/src/op/generate-pipeline.test.ts +65 -3
  507. package/src/op/generate-pipeline.ts +19 -2
  508. package/src/op/index.ts +48 -8
  509. package/src/op/local-executor.test.ts +178 -34
  510. package/src/op/local-executor.ts +371 -102
  511. package/src/op/local-output.test.ts +95 -11
  512. package/src/op/local-output.ts +33 -4
  513. package/src/op/op-ir.test.ts +292 -0
  514. package/src/op/op-ir.ts +419 -0
  515. package/src/op/op-verb-class.test.ts +2 -2
  516. package/src/op/op-verb-class.ts +19 -5
  517. package/src/op/op.test.ts +28 -7
  518. package/src/op/operator.test.ts +543 -6
  519. package/src/op/operator.ts +203 -20
  520. package/src/op/receipt-store.ts +1 -1
  521. package/src/op/resource.ts +20 -2
  522. package/src/op/runtime.ts +203 -0
  523. package/src/op/runtimes/local.test.ts +181 -0
  524. package/src/op/runtimes/local.ts +212 -0
  525. package/src/op/step-output-ref.ts +15 -13
  526. package/src/op/types.ts +106 -26
  527. package/src/ownership.ts +1 -1
  528. package/src/provenance.test.ts +6 -0
  529. package/src/provenance.ts +21 -1
  530. package/src/serializer-walker.test.ts +42 -0
  531. package/src/serializer-walker.ts +21 -2
  532. package/src/terraform/aws-resources.test.ts +13 -4
  533. package/src/terraform/bridge.test.ts +22 -9
  534. package/src/terraform/bridge.ts +89 -28
  535. package/src/terraform/carve-provider.ts +38 -2
  536. package/src/terraform/data-source-shape.ts +95 -0
  537. package/src/terraform/graph.ts +35 -7
  538. package/src/terraform/providers/kubernetes.ts +48 -2
  539. package/src/terraform/tier-map.ts +21 -6
  540. package/src/terraform/types.ts +8 -0
  541. package/dist/cli/handlers/op-progress.d.ts +0 -90
  542. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  543. package/dist/cli/handlers/run-client.d.ts +0 -127
  544. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  545. package/dist/cli/handlers/run-report.d.ts +0 -5
  546. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  547. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  548. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  549. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  550. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  551. package/src/cli/handlers/op-progress.test.ts +0 -268
  552. package/src/cli/handlers/op-progress.ts +0 -248
  553. package/src/cli/handlers/run-client.test.ts +0 -82
  554. package/src/cli/handlers/run-client.ts +0 -219
  555. package/src/cli/handlers/run-report.test.ts +0 -62
  556. package/src/cli/handlers/run-report.ts +0 -122
  557. package/src/components/temporal-codegen-loader.ts +0 -41
  558. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -22,7 +22,6 @@ vi.mock("../lifecycle/release-ledger", async () => {
22
22
  const {
23
23
  maybeRecordAutoRelease,
24
24
  extractRunDigest,
25
- extractRunDigestFromPhaseOutputs,
26
25
  } = await import("./auto-release");
27
26
 
28
27
  function publishRecord(digest: string): DriverStepRecord {
@@ -64,21 +63,6 @@ describe("extractRunDigest", () => {
64
63
  });
65
64
  });
66
65
 
67
- describe("extractRunDigestFromPhaseOutputs", () => {
68
- test("finds the digest across phase outputs (Temporal workflow result shape)", () => {
69
- expect(extractRunDigestFromPhaseOutputs({ Publish: { digest: "sha256:abc", uri: "repo@sha256:abc" }, Apply: { ok: true } })).toBe("sha256:abc");
70
- });
71
-
72
- test("returns undefined for undefined/empty phaseOutputs", () => {
73
- expect(extractRunDigestFromPhaseOutputs(undefined)).toBeUndefined();
74
- expect(extractRunDigestFromPhaseOutputs({})).toBeUndefined();
75
- });
76
-
77
- test("ignores a phase output carrying only a content digest (SBOM, #665)", () => {
78
- expect(extractRunDigestFromPhaseOutputs({ Sbom: { digest: "sha256:sbombytes" } })).toBeUndefined();
79
- });
80
- });
81
-
82
66
  describe("maybeRecordAutoRelease", () => {
83
67
  beforeEach(() => {
84
68
  getHeadCommitMock.mockReset().mockResolvedValue("abc123headsha");
@@ -111,19 +95,19 @@ describe("maybeRecordAutoRelease", () => {
111
95
  expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
112
96
  });
113
97
 
114
- test("a pre-resolved digest (Temporal path) takes precedence and is used directly", async () => {
98
+ test("a pre-resolved digest takes precedence and is used directly", async () => {
115
99
  appendReleaseRecordMock.mockResolvedValue({
116
100
  commit: "b".repeat(40),
117
- record: { version: 1, component: "svc", env: "prod", digest: "sha256:temporal", gitSha: "x", runId: "r", timestamp: "t", actor: "a" },
101
+ record: { version: 1, component: "svc", env: "prod", digest: "sha256:preresolved", gitSha: "x", runId: "r", timestamp: "t", actor: "a" },
118
102
  });
119
103
 
120
104
  await maybeRecordAutoRelease(
121
- { component: "svc", env: "prod", success: true, digest: "sha256:temporal", records: [publishRecord("sha256:ignored")], runId: "run-1" },
105
+ { component: "svc", env: "prod", success: true, digest: "sha256:preresolved", records: [publishRecord("sha256:ignored")], runId: "run-1" },
122
106
  { actor: "alice" },
123
107
  );
124
108
 
125
109
  const [input] = appendReleaseRecordMock.mock.calls[0];
126
- expect(input.digest).toBe("sha256:temporal");
110
+ expect(input.digest).toBe("sha256:preresolved");
127
111
  });
128
112
 
129
113
  test("failure (run.success = false) -> writes nothing", async () => {
@@ -4,23 +4,19 @@
4
4
  * release ledger (../lifecycle/release-ledger.ts) was only populated by the
5
5
  * standalone `chant components release <env>` command — a deploy that never
6
6
  * called it left the ledger silently empty. This module makes recording
7
- * happen *by construction*: the CLI post-run step for both the local
8
- * executor (`runOpComponents`) and the durable Temporal path
9
- * (`runComponentTemporal`) calls `maybeRecordAutoRelease` after the run
10
- * reports success.
7
+ * happen *by construction*: the CLI's post-run step (`runOpComponents`)
8
+ * calls `maybeRecordAutoRelease` after the run reports success.
11
9
  *
12
10
  * Deliberately CLI-side, not driver-side or workflow-side:
13
11
  * - `../components/driver.ts` stays capability-agnostic — it already
14
12
  * resists per-component/per-capability branching, and "write to git"
15
13
  * is exactly the kind of side effect that doesn't belong in a step
16
14
  * dispatcher tests exercise against a bare `CapabilityRegistry`.
17
- * - The Temporal workflow (lexicons/temporal/src/component-op/) must stay
18
- * deterministic and replay-safe. A ledger write is a non-idempotent git
19
- * push with real-world side effects (network, `Date.now()`, file writes
20
- * outside workflow state) — precisely what Temporal workflow code must
21
- * never do directly. It happens in the CLI, after `handle.describe()`
22
- * reports a terminal COMPLETED status, the same place `runOpTemporal`
23
- * already writes its deployment report post-run.
15
+ * - A ledger write is a non-idempotent git push with real-world side
16
+ * effects (network, `Date.now()`, file writes) — the kind of thing that
17
+ * belongs at the edge of a run rather than inside a step a retry may run
18
+ * a second time. It happens in the CLI, once the run has reported a
19
+ * terminal outcome.
24
20
  *
25
21
  * Reuses ../lifecycle/release-ledger.ts's `appendReleaseRecord` verbatim —
26
22
  * this module only decides *whether* to call it and *what digest* to record,
@@ -72,27 +68,6 @@ export function extractRunDigest(records: DriverStepRecord[]): string | undefine
72
68
  return found;
73
69
  }
74
70
 
75
- /**
76
- * Same digest extraction as `extractRunDigest`, but over a component
77
- * Temporal workflow's returned `phaseOutputs` (`{ [phase]: output }`) instead
78
- * of a `DriverStepRecord[]` — the shape `handle.result()` resolves to for a
79
- * COMPLETED component workflow (see lexicons/temporal/src/component-op/
80
- * serializer.ts's generated `return { phaseOutputs, componentOutputs }`).
81
- * Used by the `--temporal` CLI path, which never sees individual step
82
- * records (those exist only inside the workflow/activities).
83
- */
84
- export function extractRunDigestFromPhaseOutputs(
85
- phaseOutputs: Record<string, Record<string, unknown>> | undefined,
86
- ): string | undefined {
87
- let found: string | undefined;
88
- for (const output of Object.values(phaseOutputs ?? {})) {
89
- if (isPromotedArtifact(output) && typeof output.digest === "string") {
90
- found = output.digest;
91
- }
92
- }
93
- return found;
94
- }
95
-
96
71
  /** Explicit reasons `maybeRecordAutoRelease` declined to write a record — never a thrown error, since "nothing to record" (or "opted out") is an expected, common outcome. */
97
72
  export type AutoReleaseSkipReason =
98
73
  | "opted-out"
@@ -105,19 +80,19 @@ export type AutoReleaseResult =
105
80
  | { recorded: false; reason: AutoReleaseSkipReason; detail?: string }
106
81
  | { recorded: false; reason: "error"; error: string };
107
82
 
108
- /** Input describing one component's completed run, common to both the local-executor and Temporal-durable CLI paths. */
83
+ /** Input describing one component's completed run. */
109
84
  export interface AutoReleaseRunInfo {
110
85
  component: string;
111
86
  env: string;
112
- /** Whether the run reported overall success — `DriverRunResult.ok` (local) or a terminal `COMPLETED` Temporal status. A caller must not call this for a non-terminal/in-progress run. */
87
+ /** Whether the run reported overall success (`DriverRunResult.ok`). A caller must not call this for a non-terminal/in-progress run. */
113
88
  success: boolean;
114
89
  /** The component's step records (local executor), used to locate the published digest via `extractRunDigest`. Mutually exclusive with `digest` — pass whichever the caller already has. */
115
90
  records?: DriverStepRecord[];
116
- /** A digest already resolved by the caller (e.g. the `--temporal` path, via `extractRunDigestFromPhaseOutputs` over the workflow's `handle.result()`). Takes precedence over `records` when both are given. */
91
+ /** A digest the caller already resolved by its own means. Takes precedence over `records` when both are given. */
117
92
  digest?: string;
118
- /** Orchestrator run identifier — a Temporal `runId`, or a locally generated id for the local executor (mirrors `runComponentsReleaseRecord`'s `--run-id` default). */
93
+ /** Orchestrator run identifier — a hosting runtime's own run id, or a locally generated one (mirrors `runComponentsReleaseRecord`'s `--run-id` default). */
119
94
  runId: string;
120
- /** The id space `runId` lives in (#2045) — `{ forge: "op" }` for a Temporal run, `{ forge: "local" }` for a local-executor mint. Recorded verbatim as the release record's `runOrigin`. */
95
+ /** The id space `runId` lives in (#2045) — `{ forge: "op" }` for a hosted run, `{ forge: "local" }` for a local-executor mint. Recorded verbatim as the release record's `runOrigin`. */
121
96
  runOrigin?: RunOrigin;
122
97
  /** The bypassed capability-profile divergences, when the caller deliberately overrode a deploy-time profile assertion (chant #1244) — recorded verbatim as the release record's `profileOverride`. */
123
98
  profileOverride?: string;
@@ -142,11 +117,11 @@ function resolveActor(override?: string): string | undefined {
142
117
  }
143
118
 
144
119
  /**
145
- * After a successful `chant run --components <name> --env <env>` (local or
146
- * `--temporal`), append exactly one immutable release record to the ledger
147
- * and push it — or explain, without throwing, why it didn't. Never called
148
- * for a failed run (`run.success` must be true before the caller invokes
149
- * this at all; see `runOpComponents`/`runComponentTemporal`) — a failed
120
+ * After a successful `chant run --components <name> --env <env>`, append
121
+ * exactly one immutable release record to the ledger and push it — or
122
+ * explain, without throwing, why it didn't. Never called for a failed run
123
+ * (`run.success` must be true before the caller invokes this at all; see
124
+ * `runOpComponents`) — a failed
150
125
  * deploy writes nothing, by construction, since this function is simply
151
126
  * never reached on that path.
152
127
  *
@@ -50,10 +50,10 @@ export interface Capability<In = unknown, Out = unknown> {
50
50
  * returned (#1944, epic #1564 phase 4) — a serializable identity channel a
51
51
  * capability can use to recover state `rollback` needs when it cannot rely
52
52
  * on in-process object identity between its `run`/`rollback` calls. The
53
- * local interpret driver (../driver.ts) always threads it through; the
54
- * durable Temporal path (lexicons/temporal/src/component-op/*.ts) threads
55
- * it across the Activity boundary as plain JSON, which is exactly the case
56
- * this exists for — see ./verbs/run-agent.ts's "Rollback identity" doc
53
+ * local interpret driver (../driver.ts) always threads it through; a
54
+ * hosting runtime that splits a run across process boundaries threads it
55
+ * across as plain JSON, which is exactly the case this exists for — see
56
+ * ./verbs/run-agent.ts's "Rollback identity" doc
57
57
  * comment for the motivating gap (a fresh sprite's checkpoint id, recorded
58
58
  * only in an in-process `WeakMap` keyed by `run()`'s `input` object, never
59
59
  * survives to a `rollback()` call that runs as a separate Activity with its
@@ -25,6 +25,7 @@ import {
25
25
  generateComponentsPipeline,
26
26
  } from "./cli-support";
27
27
  import { CapabilityRegistry, type DeployContext } from "./capability";
28
+ import { memoryGateLedgerPort } from "../op/gate";
28
29
  import type { DriverComponent, RunProgressEvent } from "./driver";
29
30
 
30
31
  // A minimal stand-in for the real gitlab lexicon plugin, satisfying
@@ -427,9 +428,9 @@ describe("findComponentGate", () => {
427
428
  const component: DriverComponent = {
428
429
  name: "svc",
429
430
  dependsOn: [],
430
- deploy: [{ phase: "Approve", steps: [{ kind: "gate", signalName: "release-approval" }] }],
431
+ deploy: [{ phase: "Approve", steps: [{ kind: "gate", gate: "release-approval" }] }],
431
432
  };
432
- expect(findComponentGate(component)).toEqual({ kind: "gate", signalName: "release-approval" });
433
+ expect(findComponentGate(component)).toEqual({ gate: "release-approval" });
433
434
  });
434
435
 
435
436
  test("finds a gate nested inside a fan-out phase", () => {
@@ -442,13 +443,13 @@ describe("findComponentGate", () => {
442
443
  steps: [
443
444
  {
444
445
  phase: "instance-2",
445
- steps: [{ kind: "gate", signalName: "instance-2-approval" }],
446
+ steps: [{ kind: "gate", gate: "instance-2-approval" }],
446
447
  },
447
448
  ],
448
449
  },
449
450
  ],
450
451
  };
451
- expect(findComponentGate(component)?.signalName).toBe("instance-2-approval");
452
+ expect(findComponentGate(component)?.gate).toBe("instance-2-approval");
452
453
  });
453
454
 
454
455
  test("finds a gate in a component's rollback phases", () => {
@@ -456,9 +457,20 @@ describe("findComponentGate", () => {
456
457
  name: "svc",
457
458
  dependsOn: [],
458
459
  deploy: [{ phase: "Apply", steps: [{ kind: "deploy-thing" }] }],
459
- rollback: [{ phase: "Rollback", steps: [{ kind: "gate", signalName: "rollback-approval" }] }],
460
+ rollback: [{ phase: "Rollback", steps: [{ kind: "gate", gate: "rollback-approval" }] }],
461
+ };
462
+ expect(findComponentGate(component)?.gate).toBe("rollback-approval");
463
+ });
464
+
465
+ // #2202: the name comes back on `gate` whichever key the component spelled
466
+ // it with, so no caller has to know about the deprecated one.
467
+ test("normalizes a gate step's deprecated `signalName` key onto `gate`", () => {
468
+ const component = {
469
+ name: "svc",
470
+ dependsOn: [],
471
+ deploy: [{ phase: "Approve", steps: [{ kind: "gate", signalName: "release-approval" }] }],
460
472
  };
461
- expect(findComponentGate(component)?.signalName).toBe("rollback-approval");
473
+ expect(findComponentGate(component)).toEqual({ gate: "release-approval" });
462
474
  });
463
475
  });
464
476
 
@@ -587,11 +599,11 @@ describe("runComponents", () => {
587
599
  expect(result.error).toContain("svc");
588
600
  });
589
601
 
590
- test("a gate in the selected component is rejected before any step runs", async () => {
602
+ test("a gate in the selected component ends the run pending approval (#2119)", async () => {
591
603
  await writeFile(
592
604
  join(testDir, "svc.component.ts"),
593
605
  `export const svc = { name: "svc", dependsOn: [], deploy: [
594
- { phase: "Approve", steps: [{ kind: "gate", signalName: "release-approval" }] },
606
+ { phase: "Approve", steps: [{ kind: "gate", gate: "release-approval" }] },
595
607
  { phase: "Apply", steps: [{ kind: "deploy-thing" }] },
596
608
  ] };`,
597
609
  );
@@ -600,11 +612,15 @@ describe("runComponents", () => {
600
612
  const registry = new CapabilityRegistry();
601
613
  registry.register(capability);
602
614
 
603
- const result = await runComponents(testDir, "svc", { registry });
615
+ const gates = memoryGateLedgerPort();
616
+ const result = await runComponents(testDir, "svc", { registry, gates });
604
617
 
605
618
  expect(result.success).toBe(false);
606
- expect(result.gateUnsupported).toEqual({ component: "svc", signalName: "release-approval" });
607
- // Pre-flighted: the deploy-thing step after the gate never ran.
619
+ expect(result.gated?.component).toBe("svc");
620
+ expect(result.gated?.gate.gate).toBe("release-approval");
621
+ expect(result.run?.status).toBe("gated");
622
+ expect(gates.appended).toHaveLength(1);
623
+ // Nothing after the gate ran.
608
624
  expect(capability.calls).toHaveLength(0);
609
625
  });
610
626
 
@@ -844,7 +860,7 @@ describe("resolveComponentTargets — buildParams (chant #1108)", () => {
844
860
  await rm(testDir, { recursive: true, force: true });
845
861
  });
846
862
 
847
- test("forwards buildParams into discovery — the durable (--temporal) path's entrypoint", async () => {
863
+ test("forwards buildParams into discovery — the selector-resolution entrypoint", async () => {
848
864
  await writeFile(
849
865
  join(testDir, "svc.component.ts"),
850
866
  `
@@ -31,12 +31,15 @@ import {
31
31
  runComponentDeploy,
32
32
  UnknownDependencyError,
33
33
  DependencyCycleError,
34
- DriverGateUnsupportedError,
35
34
  DriverRunFailure,
36
35
  type DriverComponent,
36
+ type DriverGate,
37
37
  type DriverPhase,
38
38
  type DriverRunResult,
39
39
  } from "./driver";
40
+ import type { PendingGateRecord } from "../lifecycle/gate-ledger";
41
+ import type { GateLedgerPort } from "../op/gate";
42
+ import { gateName } from "../op/gate-name";
40
43
  import { isLexiconPlugin, type LexiconPlugin, type ComponentPipelineOptions } from "../lexicon";
41
44
  import type { RunProgressEvent } from "./run-progress";
42
45
  import { relative } from "node:path";
@@ -313,18 +316,21 @@ function toDriverComponent(component: { name: string; dependsOn: string[]; deplo
313
316
 
314
317
  /**
315
318
  * Find the first `gate` step anywhere in a component's `deploy`/`rollback`
316
- * composition (including nested fan-out phases), mirroring
317
- * `../op/local-executor.ts`'s `findGate`. Used as a pre-flight check so
318
- * `chant run --components` fails before any step runs — matching
319
- * `runOpLocal`'s behavior for Ops — rather than only failing mid-run when the
320
- * driver itself reaches the gated phase (`DriverGateUnsupportedError`).
319
+ * composition (including nested fan-out phases).
320
+ *
321
+ * A declaration-time question, not a pre-flight refusal: since #2119 the
322
+ * driver decides a gate against the ledger when it reaches one, so nothing
323
+ * needs to know up front that a component has one.
324
+ *
325
+ * The name comes back on `gate` whichever key the component spelled it with,
326
+ * so a caller never has to know about the deprecated `signalName` (#2202).
321
327
  */
322
- export function findComponentGate(component: DriverComponent): { signalName: string } | undefined {
323
- const search = (phases: DriverPhase[] | undefined): { signalName: string } | undefined => {
328
+ export function findComponentGate(component: DriverComponent): { gate: string } | undefined {
329
+ const search = (phases: DriverPhase[] | undefined): { gate: string } | undefined => {
324
330
  for (const phaseDef of phases ?? []) {
325
331
  for (const entry of phaseDef.steps) {
326
332
  if ((entry as { kind?: unknown }).kind === "gate") {
327
- return entry as unknown as { signalName: string };
333
+ return { gate: gateName(entry as DriverGate) };
328
334
  }
329
335
  if (typeof (entry as DriverPhase).phase === "string" && Array.isArray((entry as DriverPhase).steps)) {
330
336
  const nested = search([entry as DriverPhase]);
@@ -406,6 +412,8 @@ export interface RunComponentsOptions {
406
412
  * every test in `cli-support.test.ts`) that doesn't supply this.
407
413
  */
408
414
  buildParams?: BuildParamProvenance[];
415
+ /** Where a `gate` step's facts are read and written (#2119). Defaults to the `chant/lifecycle` orphan branch; a test passes `memoryGateLedgerPort()` from `../op/gate.ts`. */
416
+ gates?: GateLedgerPort;
409
417
  }
410
418
 
411
419
  /** Result of `chant run --components <name|all>`. */
@@ -416,8 +424,8 @@ export interface RunComponentsResult {
416
424
  /** Component names actually dispatched to the driver, in run order. */
417
425
  selected: string[];
418
426
  error?: string;
419
- /** Set when a selected component (or one of its `deploy`/`rollback` phases) contains a `gate` the local executor cannot run. */
420
- gateUnsupported?: { component: string; signalName: string };
427
+ /** Set when the run stopped at a `gate` nobody has approved (#2119): the component it stopped at and the pending fact recorded for it. */
428
+ gated?: { component: string; gate: PendingGateRecord };
421
429
  /** This run's resolved build-time parameters (chant #1108) — the component-driver counterpart of `../cli/commands/build.ts`'s `BuildResult.buildParams`. Present only once the run actually reached dispatch (mirrors `BuildResult.buildParams`, which is likewise absent on an early-error return). */
422
430
  buildParams?: BuildParamProvenance[];
423
431
  }
@@ -428,8 +436,7 @@ export interface RunComponentsResult {
428
436
  * local in-process executor — the CLI entrypoint the driver never had (#585,
429
437
  * follow-up to #556). Discovers the full component set first, then either:
430
438
  * - `selector === "all"`: resolves the whole set's dependency order/waves
431
- * and dispatches every component through `runInterpretDriver`, matching
432
- * what the generated orchestrator Op will eventually do — the same
439
+ * and dispatches every component through `runInterpretDriver`, in the same
433
440
  * order `chant graph --components` reports.
434
441
  * - a single name: dispatches just that component via `runComponentDeploy`,
435
442
  * without requiring the rest of its `dependsOn` graph to be present in
@@ -441,14 +448,12 @@ export interface RunComponentsResult {
441
448
  * infra outside the discovered set (e.g. a shared stack, per the
442
449
  * `search-service` pilot), which is exactly the common case.
443
450
  *
444
- * Pre-flights every selected component for a `gate` step and fails before any
445
- * step runs (`gateUnsupported`), matching `runOpLocal`'s pre-flight
446
- * `findGate` check for Ops — gated components need a durable (Temporal)
447
- * backend, which is out of scope here (issue #585 scopes Temporal-backed
448
- * component execution to what already exists for Ops; the epic tracks
449
- * graduating a gated component to `--temporal` separately).
451
+ * A `gate` no longer refuses the run up front (#2119). The driver decides each
452
+ * one against the gate ledger as it reaches it; a gate nobody has approved
453
+ * stops the run there with `gated` set, which the CLI turns into exit code 3
454
+ * and the `chant approve` line.
450
455
  */
451
- /** Result of resolving a `<name|all>` selector against discovered components — shared by the local (`runComponents`) and durable (Temporal codegen, #589) entrypoints. */
456
+ /** Result of resolving a `<name|all>` selector against discovered components. */
452
457
  export interface ResolvedComponentTargets {
453
458
  success: boolean;
454
459
  targets: DriverComponent[];
@@ -459,10 +464,8 @@ export interface ResolvedComponentTargets {
459
464
  * Discover every component under `path` and resolve `selector` (`"all"` or a
460
465
  * single component name) to the `DriverComponent`(s) to run, with no gate
461
466
  * check and no dispatch — just discovery + selection, factored out of
462
- * `runComponents` so the durable Temporal entrypoint (`chant run --components
463
- * <name> --temporal`, #589) can reuse the exact same selection semantics
464
- * without also inheriting the local executor's pre-flight gate rejection
465
- * (gates are exactly what the durable path exists to support).
467
+ * `runComponents` so another entrypoint can reuse the exact same selection
468
+ * semantics without inheriting the run itself.
466
469
  */
467
470
  export async function resolveComponentTargets(
468
471
  path: string,
@@ -526,17 +529,6 @@ export async function runComponents(
526
529
  }
527
530
  const targets = resolved.targets;
528
531
 
529
- for (const component of targets) {
530
- const gate = findComponentGate(component);
531
- if (gate) {
532
- return {
533
- success: false,
534
- selected: targets.map((c) => c.name),
535
- gateUnsupported: { component: component.name, signalName: gate.signalName },
536
- };
537
- }
538
- }
539
-
540
532
  // (#629) Resolve `chant.config.ts`'s `sbom`/`signing`/`vulnPolicy` sections
541
533
  // and fill their defaults into every recognized step (`generate-sbom`,
542
534
  // `sign`/`attest-provenance`, `verify`, `vuln-gate`) that didn't already
@@ -563,10 +555,25 @@ export async function runComponents(
563
555
  const seedOutputs = options.componentOutputs ?? {};
564
556
  const { onProgress } = options;
565
557
 
558
+ const gates = options.gates;
559
+
566
560
  try {
567
561
  if (selector === "all") {
568
- const run = await runInterpretDriver(resolvedTargets, registry, { env, componentOutputs: seedOutputs, onProgress });
569
- return { success: true, run, selected, buildParams: options.buildParams };
562
+ const run = await runInterpretDriver(resolvedTargets, registry, {
563
+ env,
564
+ componentOutputs: seedOutputs,
565
+ onProgress,
566
+ ...(gates ? { gates } : {}),
567
+ });
568
+ return {
569
+ success: run.status === "ok",
570
+ run,
571
+ selected,
572
+ buildParams: options.buildParams,
573
+ ...(run.status === "gated" && run.gate
574
+ ? { gated: { component: run.gatedComponent ?? selected[0], gate: run.gate } }
575
+ : {}),
576
+ };
570
577
  }
571
578
 
572
579
  // Single-component invocation: run just this component, bypassing
@@ -592,8 +599,9 @@ export async function runComponents(
592
599
  registry,
593
600
  componentOutputs,
594
601
  onProgress,
602
+ gates ? { port: gates } : undefined,
595
603
  );
596
- const status: "ok" | "failed" = componentResult.ok ? "ok" : "failed";
604
+ const status = componentResult.status === "fail" ? "failed" : componentResult.status;
597
605
  onProgress?.({ type: "component-done", wave: 1, component: componentName, status });
598
606
  onProgress?.({ type: "wave-done", wave: 1, status });
599
607
  onProgress?.({ type: "run-done", status });
@@ -602,21 +610,26 @@ export async function runComponents(
602
610
  waves: [selected],
603
611
  results: [componentResult],
604
612
  ok: componentResult.ok,
605
- failedComponent: componentResult.ok ? undefined : componentResult.component,
613
+ status: componentResult.status,
614
+ failedComponent: componentResult.status === "fail" ? componentResult.component : undefined,
615
+ ...(componentResult.status === "gated"
616
+ ? { gatedComponent: componentResult.component, gate: componentResult.gate }
617
+ : {}),
606
618
  componentOutputs,
607
619
  };
608
- return { success: componentResult.ok, run, selected, buildParams: options.buildParams };
620
+ return {
621
+ success: componentResult.ok,
622
+ run,
623
+ selected,
624
+ buildParams: options.buildParams,
625
+ ...(componentResult.status === "gated" && componentResult.gate
626
+ ? { gated: { component: componentResult.component, gate: componentResult.gate } }
627
+ : {}),
628
+ };
609
629
  } catch (err) {
610
630
  if (err instanceof DriverRunFailure) {
611
631
  return { success: false, run: err.result, selected, error: err.message };
612
632
  }
613
- if (err instanceof DriverGateUnsupportedError) {
614
- return {
615
- success: false,
616
- selected,
617
- gateUnsupported: { component: err.component, signalName: err.signalName },
618
- };
619
- }
620
633
  if (err instanceof UnknownDependencyError || err instanceof DependencyCycleError) {
621
634
  return { success: false, selected, error: err.message };
622
635
  }
@@ -192,14 +192,14 @@ describe("Component JSON Schema", () => {
192
192
  deploy: [
193
193
  {
194
194
  phase: "Approve",
195
- steps: [{ kind: "gate", signalName: "approve-gated", description: "confirm", timeout: "24h" }],
195
+ steps: [{ kind: "gate", gate: "approve-gated", description: "confirm", timeout: "24h" }],
196
196
  },
197
197
  ],
198
198
  };
199
199
  expect(validate(withGate)).toBe(true);
200
200
  });
201
201
 
202
- it("rejects a gate step missing signalName", () => {
202
+ it("rejects a gate step naming neither `gate` nor `signalName`", () => {
203
203
  const invalid = {
204
204
  name: "gated",
205
205
  dependsOn: [],
@@ -208,6 +208,22 @@ describe("Component JSON Schema", () => {
208
208
  expect(validate(invalid)).toBe(false);
209
209
  });
210
210
 
211
+ // The gate step's name key was renamed from `signalName` to `gate` in #2202.
212
+ // The schema takes either one and exactly one, through 0.59.0.
213
+ const gated = (step: Record<string, unknown>): Record<string, unknown> => ({
214
+ name: "gated",
215
+ dependsOn: [],
216
+ deploy: [{ phase: "Approve", steps: [step] }],
217
+ });
218
+
219
+ it("still accepts the deprecated `signalName` key on a gate step", () => {
220
+ expect(validate(gated({ kind: "gate", signalName: "approve-gated" }))).toBe(true);
221
+ });
222
+
223
+ it("rejects a gate step carrying both `gate` and `signalName`", () => {
224
+ expect(validate(gated({ kind: "gate", gate: "approve-gated", signalName: "approve-gated" }))).toBe(false);
225
+ });
226
+
211
227
  it("accepts a stackOutput cross-stack reference", () => {
212
228
  const withStackOutput = {
213
229
  name: "svc",
@@ -160,17 +160,30 @@
160
160
  }
161
161
  },
162
162
 
163
+ "GateName": {
164
+ "type": "string",
165
+ "minLength": 1,
166
+ "description": "A gate's name, on either of the two keys that may carry it."
167
+ },
168
+
163
169
  "Gate": {
164
170
  "type": "object",
165
- "description": "Pauses the composition for an external signal (typically human approval) before continuing. A gate in a component's composition requires the durable (Temporal) execution backend; it cannot run on the local in-process executor.",
166
- "required": ["kind", "signalName"],
171
+ "description": "Ends the run pending human approval. The driver decides a gate against the gate ledger when it reaches one; a gate nobody has approved stops the run there, and `chant approve <component> <gate>` records the resolution the next run reads.",
172
+ "required": ["kind"],
173
+ "oneOf": [
174
+ { "required": ["gate"], "properties": { "gate": { "$ref": "#/$defs/GateName" } } },
175
+ { "required": ["signalName"], "properties": { "signalName": { "$ref": "#/$defs/GateName" } } }
176
+ ],
167
177
  "additionalProperties": false,
168
178
  "properties": {
169
179
  "kind": { "type": "string", "const": "gate" },
180
+ "gate": {
181
+ "$ref": "#/$defs/GateName",
182
+ "description": "The gate's name — what `chant approve <component> <gate>` resolves."
183
+ },
170
184
  "signalName": {
171
- "type": "string",
172
- "minLength": 1,
173
- "description": "Signal name the generated workflow waits for before continuing."
185
+ "$ref": "#/$defs/GateName",
186
+ "description": "Deprecated spelling of `gate` (chant #2202), accepted through 0.59.0 and removed in 0.60.0. Exactly one of `gate` and `signalName` may be present."
174
187
  },
175
188
  "timeout": {
176
189
  "type": "string",
@@ -37,13 +37,13 @@ describe("phase()", () => {
37
37
 
38
38
  describe("gate()", () => {
39
39
  it("builds a minimal Gate", () => {
40
- expect(gate("approve-x")).toEqual({ kind: "gate", signalName: "approve-x" });
40
+ expect(gate("approve-x")).toEqual({ kind: "gate", gate: "approve-x" });
41
41
  });
42
42
 
43
43
  it("carries optional timeout/description", () => {
44
44
  expect(gate("approve-x", { timeout: "24h", description: "confirm" })).toEqual({
45
45
  kind: "gate",
46
- signalName: "approve-x",
46
+ gate: "approve-x",
47
47
  timeout: "24h",
48
48
  description: "confirm",
49
49
  });
@@ -77,16 +77,36 @@ export interface Step {
77
77
  [param: string]: unknown;
78
78
  }
79
79
 
80
- /** Mirrors `$defs.Gate` — pauses the composition for an external signal (typically human approval). */
81
- export interface Gate {
80
+ /** Everything on a component gate step except the key that names it. */
81
+ export interface GateBase {
82
82
  kind: "gate";
83
- signalName: string;
84
- /** Duration string bounding the wait, e.g. "48h". Default: "48h". */
83
+ /** How long a recorded pending gate stays valid, as a duration string. Default: "48h". */
85
84
  timeout?: string;
86
85
  /** Human-readable description of the action required to unblock this gate. */
87
86
  description?: string;
88
87
  }
89
88
 
89
+ /**
90
+ * Mirrors `$defs.Gate` — a human approval decided against the gate ledger; the
91
+ * run stops here with status `gated` until `chant approve` has answered it.
92
+ * The name lives on `gate`; `signalName` is the key it carried through 0.58.0
93
+ * and is still accepted (#2202). Read both through `gateName()`.
94
+ */
95
+ export type Gate = GateBase &
96
+ (
97
+ | {
98
+ /** The gate's name — what `chant approve <component> <gate>` resolves. */
99
+ gate: string;
100
+ /** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
101
+ signalName?: string;
102
+ }
103
+ | {
104
+ gate?: undefined;
105
+ /** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
106
+ signalName: string;
107
+ }
108
+ );
109
+
90
110
  /**
91
111
  * Mirrors `$defs.Phase` — one named phase of a deploy composition. A step may
92
112
  * itself be a nested `Phase`, which is how a fan-out unit becomes a mini-
@@ -170,9 +190,9 @@ export function phase(name: string, steps: Array<Step | Gate | Phase>, opts?: {
170
190
  return { phase: name, steps, ...(opts?.parallel ? { parallel: true } : {}) };
171
191
  }
172
192
 
173
- /** Author a gate step — pauses the composition for an external signal (typically human approval). */
174
- export function gate(signalName: string, opts?: { timeout?: string; description?: string }): Gate {
175
- return { kind: "gate", signalName, ...opts };
193
+ /** Author a gate step — a human approval the driver decides against the gate ledger, stopping the run `gated` when nothing has answered it. */
194
+ export function gate(name: string, opts?: { timeout?: string; description?: string }): Gate {
195
+ return { kind: "gate", gate: name, ...opts };
176
196
  }
177
197
 
178
198
  /**
@@ -257,11 +257,11 @@ describe("applyConfigDefaults", () => {
257
257
  test("leaves gate steps untouched", () => {
258
258
  const config: ChantConfig = { sbom: { format: "cyclonedx" } };
259
259
  const comp = component([
260
- { phase: "Approve", steps: [{ kind: "gate", signalName: "release-approval" }] },
260
+ { phase: "Approve", steps: [{ kind: "gate", gate: "release-approval" }] },
261
261
  ]);
262
262
 
263
263
  const result = applyConfigDefaults(comp, config);
264
- expect(result.deploy[0]!.steps[0]).toEqual({ kind: "gate", signalName: "release-approval" });
264
+ expect(result.deploy[0]!.steps[0]).toEqual({ kind: "gate", gate: "release-approval" });
265
265
  });
266
266
 
267
267
  test("applies defaults to rollback phases too", () => {