@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
@@ -11,11 +11,18 @@
11
11
  * component.schema.json (`@Phase.field` prior-step references,
12
12
  * `@<component>.publish.<field>` cross-component artifact references, and
13
13
  * passes through `$env.*`/`stackOutput` values as opaque env config), runs
14
- * `parallel` phases concurrently, rejects a `gate` locally (matching
15
- * ../op/local-executor.ts's `LocalGateUnsupportedError`), and on terminal
16
- * failure unwinds every executed step in reverse via that step's capability
17
- * `rollback`, then runs `onFailure` phases in reverse order (best-effort),
18
- * mirroring the Op local executor's saga semantics.
14
+ * `parallel` phases concurrently, decides a `gate` against the gate ledger
15
+ * (#2119 — the same `../op/gate.ts` the Op executor uses, so `chant run
16
+ * --components` and `chant run <op>` can never disagree about what a gate
17
+ * means), and on terminal failure unwinds every executed step in reverse via
18
+ * that step's capability `rollback`, then runs `onFailure` phases in reverse
19
+ * order (best-effort), mirroring the Op local executor's saga semantics.
20
+ *
21
+ * A gate nobody has approved is not a failure: the component stops there with
22
+ * status `gated`, the pending fact is on the ledger, and no rollback and no
23
+ * `onFailure` phase runs — nothing failed and the steps that did run are the
24
+ * steps the author meant to run before the approval. The next run re-reads the
25
+ * ledger and continues past the gate if `chant approve` has answered it.
19
26
  *
20
27
  * A step whose capability declares no `rollback` is never silently passed
21
28
  * over during unwind: it gets a `"rollback-opted-out"` record (see
@@ -25,15 +32,13 @@
25
32
  * already requires at author time — the driver reports the same fact the
26
33
  * lint rule already made a component author state.
27
34
  *
28
- * This unwind runs entirely in-process: if the process crashes mid-rollback
29
- * on the local executor, nothing resumes it — there is no persisted run state
30
- * to resume from. That is the documented Temporal boundary (see
31
- * docs/components/orchestration.mdx#rollback-comes-free and
32
- * docs/guide/local-vs-temporal.mdx): the *mechanism* (reverse-order unwind
33
- * calling each capability's `rollback`) is capability-agnostic and works
34
- * identically on both executors, but *durable resume of a rollback already in
35
- * progress* is Temporal-only, the same boundary that already applies to
36
- * forward `onFailure` compensation on an Op.
35
+ * This unwind runs entirely in-process: if the process crashes mid-rollback,
36
+ * nothing resumes it — there is no persisted run state to resume from (see
37
+ * docs/components/orchestration.mdx#rollback-comes-free). The *mechanism*
38
+ * (reverse-order unwind calling each capability's `rollback`) is
39
+ * capability-agnostic; *durable resume of a rollback already in progress*
40
+ * would be a hosting runtime's to offer, the same boundary that already
41
+ * applies to forward `onFailure` compensation on an Op.
37
42
  *
38
43
  * Contains zero per-component logic: nothing in this module branches on a
39
44
  * component or capability `kind`/name. All behavior is either generic
@@ -42,8 +47,11 @@
42
47
  */
43
48
 
44
49
  import { topoSort } from "../codegen/topo-sort";
50
+ import { evaluateGate, gitGateLedgerPort, type GateLedgerPort } from "../op/gate";
51
+ import { gateName } from "../op/gate-name";
52
+ import type { PendingGateRecord } from "../lifecycle/gate-ledger";
45
53
  import type { CapabilityRegistry, DeployContext } from "./capability";
46
- import type { RunProgressEvent } from "./run-progress";
54
+ import type { RunProgressEvent, RunProgressStatus } from "./run-progress";
47
55
 
48
56
  export type { RunProgressEvent } from "./run-progress";
49
57
 
@@ -61,10 +69,16 @@ export interface DriverStep {
61
69
  [param: string]: unknown;
62
70
  }
63
71
 
64
- /** A gate step — pauses for an external signal; unsupported on the local executor (schema `Gate`). */
72
+ /**
73
+ * A gate step — a human approval, decided against the gate ledger when the run
74
+ * reaches it (schema `Gate`). The name is on `gate`; `signalName` is the
75
+ * deprecated spelling (#2202), so read the name through `gateName()`.
76
+ */
65
77
  export interface DriverGate {
66
78
  kind: "gate";
67
- signalName: string;
79
+ gate?: string;
80
+ /** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
81
+ signalName?: string;
68
82
  timeout?: string;
69
83
  description?: string;
70
84
  }
@@ -96,20 +110,6 @@ function isPhaseStep(step: DriverStep | DriverGate | DriverPhase): step is Drive
96
110
 
97
111
  // ── Errors ────────────────────────────────────────────────────────────────
98
112
 
99
- /** Thrown when a component's composition contains a `gate` — gates need a durable runtime, matching chant's Op local executor. */
100
- export class DriverGateUnsupportedError extends Error {
101
- constructor(
102
- public readonly component: string,
103
- public readonly signalName: string,
104
- ) {
105
- super(
106
- `component "${component}": gate "${signalName}" is not supported on the local executor — ` +
107
- `gates need a durable runtime. Re-run with a durable (Temporal) backend.`,
108
- );
109
- this.name = "DriverGateUnsupportedError";
110
- }
111
- }
112
-
113
113
  /** Thrown when a dependency cycle is found among `dependsOn` edges. */
114
114
  export class DependencyCycleError extends Error {
115
115
  constructor(public readonly cycle: string[]) {
@@ -147,12 +147,18 @@ export interface DriverStepRecord {
147
147
  durationMs: number;
148
148
  output?: unknown;
149
149
  error?: string;
150
+ /** Set on a `gate` step that passed (#2119): who resolved it, when, and at what address. */
151
+ approval?: { gate: string; resolvedBy: string; timestamp: string; url?: string };
150
152
  }
151
153
 
152
154
  export interface DriverComponentResult {
153
155
  component: string;
154
156
  ok: boolean;
157
+ /** Three-state outcome (#2119) — `gated` is `ok: false` without being a failure: the component stopped at a gate awaiting `chant approve`, and nothing was rolled back. */
158
+ status: "ok" | "fail" | "gated";
155
159
  records: DriverStepRecord[];
160
+ /** Present when `status === "gated"`: the pending fact this component stopped on. */
161
+ gate?: PendingGateRecord;
156
162
  }
157
163
 
158
164
  export interface DriverRunResult {
@@ -162,8 +168,14 @@ export interface DriverRunResult {
162
168
  waves: string[][];
163
169
  results: DriverComponentResult[];
164
170
  ok: boolean;
171
+ /** Three-state outcome (#2119), matching `OpRunResult.status`. */
172
+ status: "ok" | "fail" | "gated";
165
173
  /** Name of the component that terminated the run, if any. */
166
174
  failedComponent?: string;
175
+ /** Name of the component the run stopped at for approval, when `status === "gated"`. */
176
+ gatedComponent?: string;
177
+ /** The pending fact the run stopped on, when `status === "gated"`. */
178
+ gate?: PendingGateRecord;
167
179
  /**
168
180
  * The accumulated cross-component/cross-stack outputs after the run — each
169
181
  * component's `publish` output and, for an applied stack, its `cfn-deploy`
@@ -285,12 +297,11 @@ export function resolveWiring(
285
297
  * Deep-walk an object, resolving every string/stackOutput wiring value found.
286
298
  * Arrays and nested objects are walked too.
287
299
  *
288
- * Exported (not just used internally) so the durable Temporal path
289
- * (`@intentius/chant-lexicon-temporal`'s component workflow codegen, see
290
- * epic #551 #589) can resolve a step's wiring the same way inside a Temporal
291
- * *activity* — the workflow itself only accumulates `phaseOutputs`/
292
- * `componentOutputs` and passes them through; resolution logic stays in one
293
- * place so local and durable execution can never silently diverge.
300
+ * Exported (not just used internally) so a hosting runtime that runs steps
301
+ * out of process can resolve a step's wiring the same way — the orchestrator
302
+ * only accumulates `phaseOutputs`/`componentOutputs` and passes them through;
303
+ * resolution logic stays in one place so local and hosted execution can never
304
+ * silently diverge.
294
305
  */
295
306
  export function resolveStepInput(
296
307
  input: Record<string, unknown>,
@@ -338,6 +349,29 @@ class StepFailure extends Error {
338
349
  }
339
350
  }
340
351
 
352
+ /** Internal: a phase stopped at an unapproved gate (#2119). Carries what ran before it, so the records survive; not a failure, so no unwind follows. */
353
+ class GateStop extends Error {
354
+ constructor(
355
+ public readonly records: DriverStepRecord[],
356
+ public readonly executed: ExecutedStep[],
357
+ public readonly pending: PendingGateRecord,
358
+ ) {
359
+ super(`gate "${pending.gate}" is pending approval`);
360
+ this.name = "GateStop";
361
+ }
362
+ }
363
+
364
+ /** A result status as the progress stream spells it — the only difference is `fail` vs `failed`, which the two vocabularies have always disagreed on. */
365
+ function progressStatus(status: DriverComponentResult["status"]): RunProgressStatus {
366
+ return status === "fail" ? "failed" : status;
367
+ }
368
+
369
+ /** How a component's run reaches the gate ledger — see `../op/gate.ts`. */
370
+ export interface GateContext {
371
+ port: GateLedgerPort;
372
+ now?: string;
373
+ }
374
+
341
375
  /** Run a single capability step. Never throws for a capability-run failure; returns a fail record instead. */
342
376
  async function runCapabilityStep(
343
377
  step: DriverStep,
@@ -381,11 +415,16 @@ async function runCapabilityStep(
381
415
  }
382
416
 
383
417
  /**
384
- * Run a phase's steps. A step may be a `Gate` (rejected — local executor has
385
- * no durable wait) or a nested `Phase` (a fan-out unit; recursed into,
386
- * inheriting `parallel` from its own definition, not its parent's). Steps run
387
- * sequentially unless `phase.parallel` is set, in which case they run via
388
- * `Promise.all`, matching ../op/local-executor.ts's phase semantics.
418
+ * Run a phase's steps. A step may be a `Gate` (decided against the gate
419
+ * ledger, in authored order — a resolution newer than the gate's newest
420
+ * pending fact lets it pass carrying the approver, anything else records the
421
+ * fact and stops the component) or a nested `Phase` (a fan-out unit; recursed
422
+ * into, inheriting `parallel` from its own definition, not its parent's).
423
+ * Steps run sequentially unless `phase.parallel` is set, in which case they run
424
+ * via `Promise.all`, matching ../op/local-executor.ts's phase semantics — and
425
+ * as there, a gate in a parallel phase is decided before the fan-out, since a
426
+ * gate is a read of the ledger rather than work, and starting activities a
427
+ * pending gate is about to strand defeats the point of stopping at it.
389
428
  *
390
429
  * `onProgress`, when supplied, is called with a `phase-start` event before any
391
430
  * step runs, a `step` event around each capability invocation (`"running"`
@@ -402,22 +441,60 @@ async function runPhase(
402
441
  registry: CapabilityRegistry,
403
442
  phaseOutputs: Record<string, Record<string, unknown>>,
404
443
  componentOutputs: Record<string, Record<string, unknown>>,
444
+ gates: GateContext,
405
445
  onProgress?: (event: RunProgressEvent) => void,
406
446
  ): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[] }> {
407
- const gate = phaseDef.steps.find(isGateStep);
408
- if (gate) throw new DriverGateUnsupportedError(ctx.component, gate.signalName);
447
+ /** Decide this phase's gates against the ledger, in authored order, before any of its work starts. Throws `GateStop` at the first one nobody has approved. */
448
+ const decideGates = async (): Promise<DriverStepRecord[]> => {
449
+ const gateRecords: DriverStepRecord[] = [];
450
+ for (const gate of phaseDef.steps.filter(isGateStep)) {
451
+ const start = Date.now();
452
+ const check = await evaluateGate(gates.port, {
453
+ op: ctx.component,
454
+ gate: gateName(gate),
455
+ ...(gate.description ? { description: gate.description } : {}),
456
+ ...(gate.timeout ? { timeout: gate.timeout } : {}),
457
+ ...(gates.now ? { now: gates.now } : {}),
458
+ });
459
+ const base = { component: ctx.component, phase: phaseDef.phase, kind: `gate:${gateName(gate)}` };
460
+ if (!check.satisfied) {
461
+ gateRecords.push({ ...base, status: "skipped" as const, durationMs: Date.now() - start });
462
+ for (const skipped of phaseDef.steps.filter((s): s is DriverStep | DriverPhase => !isGateStep(s))) {
463
+ gateRecords.push(skippedRecord(skipped));
464
+ }
465
+ throw new GateStop(gateRecords, [], check.pending);
466
+ }
467
+ gateRecords.push({
468
+ ...base,
469
+ status: "ok" as const,
470
+ durationMs: Date.now() - start,
471
+ approval: {
472
+ gate: gateName(gate),
473
+ resolvedBy: check.resolution.resolvedBy,
474
+ timestamp: check.resolution.timestamp,
475
+ ...(check.resolution.url ? { url: check.resolution.url } : {}),
476
+ },
477
+ });
478
+ }
479
+ return gateRecords;
480
+ };
409
481
 
410
482
  const entries = phaseDef.steps.filter((s): s is DriverStep | DriverPhase => !isGateStep(s));
411
483
 
412
484
  const runEntry = async (
413
485
  entry: DriverStep | DriverPhase,
414
- ): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[]; failed: boolean }> => {
486
+ ): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[]; failed: boolean; pending?: PendingGateRecord }> => {
415
487
  if (isPhaseStep(entry)) {
416
488
  try {
417
- const nested = await runPhase(entry, ctx, registry, phaseOutputs, componentOutputs, onProgress);
489
+ const nested = await runPhase(entry, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
418
490
  return { ...nested, failed: false };
419
491
  } catch (err) {
420
492
  if (err instanceof StepFailure) return { records: err.records, executed: err.executed, failed: true };
493
+ // A nested fan-out phase's gate stops the whole component, but the
494
+ // records it produced before the gate still belong in the run.
495
+ if (err instanceof GateStop) {
496
+ return { records: err.records, executed: err.executed, failed: false, pending: err.pending };
497
+ }
421
498
  throw err;
422
499
  }
423
500
  }
@@ -448,32 +525,38 @@ async function runPhase(
448
525
  };
449
526
  };
450
527
 
528
+ const skippedRecord = (entry: DriverStep | DriverPhase): DriverStepRecord => ({
529
+ component: ctx.component,
530
+ phase: phaseDef.phase,
531
+ kind: isPhaseStep(entry) ? entry.phase : (entry as DriverStep).kind,
532
+ status: "skipped",
533
+ durationMs: 0,
534
+ });
535
+
451
536
  const runEntries = async (): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[] }> => {
537
+ const gateRecords = await decideGates();
452
538
  if (phaseDef.parallel) {
453
539
  const results = await Promise.all(entries.map(runEntry));
454
- const records = results.flatMap((r) => r.records);
540
+ const records = gateRecords.concat(results.flatMap((r) => r.records));
455
541
  const executed = results.flatMap((r) => r.executed);
542
+ const pending = results.find((r) => r.pending)?.pending;
543
+ if (pending) throw new GateStop(records, executed, pending);
456
544
  if (results.some((r) => r.failed)) throw new StepFailure(records, executed);
457
545
  return { records, executed };
458
546
  }
459
547
 
460
- const records: DriverStepRecord[] = [];
548
+ const records: DriverStepRecord[] = [...gateRecords];
461
549
  const executed: ExecutedStep[] = [];
462
550
  for (let i = 0; i < entries.length; i++) {
463
551
  const result = await runEntry(entries[i]);
464
552
  records.push(...result.records);
465
553
  executed.push(...result.executed);
554
+ if (result.pending) {
555
+ for (const skipped of entries.slice(i + 1)) records.push(skippedRecord(skipped));
556
+ throw new GateStop(records, executed, result.pending);
557
+ }
466
558
  if (result.failed) {
467
- for (const skipped of entries.slice(i + 1)) {
468
- const skippedKind = isPhaseStep(skipped) ? skipped.phase : (skipped as DriverStep).kind;
469
- records.push({
470
- component: ctx.component,
471
- phase: phaseDef.phase,
472
- kind: skippedKind,
473
- status: "skipped",
474
- durationMs: 0,
475
- });
476
- }
559
+ for (const skipped of entries.slice(i + 1)) records.push(skippedRecord(skipped));
477
560
  throw new StepFailure(records, executed);
478
561
  }
479
562
  }
@@ -486,7 +569,9 @@ async function runPhase(
486
569
  onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "ok" });
487
570
  return result;
488
571
  } catch (err) {
489
- if (err instanceof StepFailure) {
572
+ if (err instanceof GateStop) {
573
+ onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "gated" });
574
+ } else if (err instanceof StepFailure) {
490
575
  onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "failed" });
491
576
  }
492
577
  throw err;
@@ -577,6 +662,7 @@ export async function runComponentDeploy(
577
662
  registry: CapabilityRegistry,
578
663
  componentOutputs: Record<string, Record<string, unknown>>,
579
664
  onProgress?: (event: RunProgressEvent) => void,
665
+ gates: GateContext = { port: gitGateLedgerPort() },
580
666
  ): Promise<DriverComponentResult> {
581
667
  const phaseOutputs: Record<string, Record<string, unknown>> = {};
582
668
  const records: DriverStepRecord[] = [];
@@ -584,11 +670,20 @@ export async function runComponentDeploy(
584
670
 
585
671
  try {
586
672
  for (const phaseDef of component.deploy) {
587
- const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, onProgress);
673
+ const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
588
674
  records.push(...result.records);
589
675
  allExecuted.push(...result.executed);
590
676
  }
591
677
  } catch (err) {
678
+ // A pending gate stops the component where it stands (#2119): no saga
679
+ // unwind and no `rollback` phase. The steps before the gate ran on
680
+ // purpose and are meant to survive the wait for an approval — undoing
681
+ // them would make every gated run a no-op with a rollback attached.
682
+ if (err instanceof GateStop) {
683
+ records.push(...err.records);
684
+ return { component: component.name, ok: false, status: "gated", records, gate: err.pending };
685
+ }
686
+
592
687
  if (err instanceof StepFailure) {
593
688
  records.push(...err.records);
594
689
  allExecuted.push(...err.executed);
@@ -600,24 +695,24 @@ export async function runComponentDeploy(
600
695
 
601
696
  for (const phaseDef of [...(component.rollback ?? [])].reverse()) {
602
697
  try {
603
- const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, onProgress);
698
+ const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
604
699
  records.push(...result.records);
605
700
  } catch (compErr) {
606
- if (compErr instanceof StepFailure) records.push(...compErr.records);
701
+ if (compErr instanceof StepFailure || compErr instanceof GateStop) records.push(...compErr.records);
607
702
  else throw compErr;
608
703
  }
609
704
  }
610
705
 
611
- return { component: component.name, ok: false, records };
706
+ return { component: component.name, ok: false, status: "fail", records };
612
707
  }
613
708
 
614
709
  // Publish-family and stack outputs become this component's entry in
615
- // `componentOutputs` — through the same exported accumulator the durable
616
- // path's `accumulateComponentOutputs` activity calls (#700), so local and
617
- // Temporal runs can never diverge on what downstream references see.
710
+ // `componentOutputs` — through the same exported accumulator a hosted
711
+ // runtime calls (#700), so local and hosted runs can never diverge on what
712
+ // downstream references see.
618
713
  accumulateComponentOutputs(componentOutputs, component.name, phaseOutputs);
619
714
 
620
- return { component: component.name, ok: true, records };
715
+ return { component: component.name, ok: true, status: "ok", records };
621
716
  }
622
717
 
623
718
  /**
@@ -641,9 +736,8 @@ export async function runComponentDeploy(
641
736
  * the driver free of per-capability branching. Returns `undefined` when the
642
737
  * component exposed nothing.
643
738
  *
644
- * Exported, like `resolveStepInput`, so the durable Temporal path
645
- * (lexicons/temporal/src/component-op/activities.ts) accumulates outputs via
646
- * this exact function rather than re-deriving it (#700). The resolver and the
739
+ * Exported, like `resolveStepInput`, so a hosting runtime accumulates outputs
740
+ * via this exact function rather than re-deriving it (#700). The resolver and the
647
741
  * accumulator are the two halves of one contract; sharing only the resolver
648
742
  * is how the cross-stack gap #699 closed locally could reopen durably.
649
743
  */
@@ -659,11 +753,11 @@ export function collectComponentOutputs(
659
753
  /**
660
754
  * Record a finished component's outputs (`collectComponentOutputs`) into the
661
755
  * shared `componentOutputs` map under the component's own name, merging over
662
- * any seeded entry (`--seed-outputs`, or a durable parent workflow's
663
- * thread-through). Mutates and returns `componentOutputs`, so a Temporal
664
- * activity can hand the updated map back to its workflow over the JSON
665
- * boundary — every value in it is plain activity-result data, so the map is
666
- * serializable by construction. A no-op when the component exposed nothing.
756
+ * any seeded entry (`--seed-outputs`, or a parent orchestrator's
757
+ * thread-through). Mutates and returns `componentOutputs`, so an out-of-process
758
+ * step can hand the updated map back over a JSON boundary — every value in it
759
+ * is plain result data, so the map is serializable by construction. A no-op
760
+ * when the component exposed nothing.
667
761
  */
668
762
  export function accumulateComponentOutputs(
669
763
  componentOutputs: Record<string, Record<string, unknown>>,
@@ -736,6 +830,10 @@ export interface InterpretRunOptions {
736
830
  * byte-for-byte the same as before this option existed.
737
831
  */
738
832
  onProgress?: (event: RunProgressEvent) => void;
833
+ /** 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`. */
834
+ gates?: GateLedgerPort;
835
+ /** ISO-8601 "now" for gate decisions, so a test is deterministic. */
836
+ now?: string;
739
837
  }
740
838
 
741
839
  /**
@@ -748,6 +846,11 @@ export interface InterpretRunOptions {
748
846
  * a result with `ok: false`; throws `DriverRunFailure` carrying that result
749
847
  * so callers can choose to inspect or propagate it.
750
848
  *
849
+ * A component that stops at an unapproved gate (#2119) ends the run the same
850
+ * way, with `status: "gated"` and the pending fact on `gate` — but it is
851
+ * *returned*, never thrown, because nothing failed. Downstream waves do not
852
+ * run: a gate is the author saying a human decides before the rest happens.
853
+ *
751
854
  * Zero per-component logic: this function and everything it calls dispatches
752
855
  * purely on the generic `Component`/`Phase`/`Step` shapes and the registry —
753
856
  * no branch anywhere names a specific component or capability.
@@ -761,11 +864,16 @@ export async function runInterpretDriver(
761
864
  const byName = new Map(components.map((c) => [c.name, c]));
762
865
  const componentOutputs: Record<string, Record<string, unknown>> = { ...(options.componentOutputs ?? {}) };
763
866
  const { onProgress } = options;
867
+ const gates: GateContext = {
868
+ port: options.gates ?? gitGateLedgerPort(),
869
+ ...(options.now ? { now: options.now } : {}),
870
+ };
764
871
 
765
872
  onProgress?.({ type: "run-start", waves });
766
873
 
767
874
  const results: DriverComponentResult[] = [];
768
875
  let failedComponent: string | undefined;
876
+ let gated: DriverComponentResult | undefined;
769
877
 
770
878
  waveLoop: for (const [waveIndex, wave] of waves.entries()) {
771
879
  const waveNum = waveIndex + 1;
@@ -780,23 +888,32 @@ export async function runInterpretDriver(
780
888
  registry,
781
889
  componentOutputs,
782
890
  onProgress,
891
+ gates,
783
892
  );
784
- onProgress?.({ type: "component-done", wave: waveNum, component: component.name, status: result.ok ? "ok" : "failed" });
893
+ onProgress?.({ type: "component-done", wave: waveNum, component: component.name, status: progressStatus(result.status) });
785
894
  return result;
786
895
  }),
787
896
  );
788
897
  results.push(...waveResults);
789
- const failed = waveResults.find((r) => !r.ok);
790
- onProgress?.({ type: "wave-done", wave: waveNum, status: failed ? "failed" : "ok" });
791
- if (failed) {
792
- failedComponent = failed.component;
898
+ const stopped = waveResults.find((r) => r.status !== "ok");
899
+ onProgress?.({ type: "wave-done", wave: waveNum, status: progressStatus(stopped?.status ?? "ok") });
900
+ if (stopped) {
901
+ // A failure in the same wave outranks a gate: something is actually
902
+ // broken, and reporting the run as "waiting on a human" would hide it.
903
+ const failure = waveResults.find((r) => r.status === "fail");
904
+ if (failure) failedComponent = failure.component;
905
+ else gated = stopped;
793
906
  break waveLoop;
794
907
  }
795
908
  }
796
909
 
797
- const ok = failedComponent === undefined;
798
- onProgress?.({ type: "run-done", status: ok ? "ok" : "failed" });
799
- const result: DriverRunResult = { order, waves, results, ok, failedComponent, componentOutputs };
800
- if (!ok) throw new DriverRunFailure(result);
910
+ const status: DriverRunResult["status"] = failedComponent ? "fail" : gated ? "gated" : "ok";
911
+ const ok = status === "ok";
912
+ onProgress?.({ type: "run-done", status: progressStatus(status) });
913
+ const result: DriverRunResult = {
914
+ order, waves, results, ok, status, failedComponent, componentOutputs,
915
+ ...(gated ? { gatedComponent: gated.component, gate: gated.gate } : {}),
916
+ };
917
+ if (status === "fail") throw new DriverRunFailure(result);
801
918
  return result;
802
919
  }
@@ -95,7 +95,7 @@ export {
95
95
  accumulateComponentOutputs,
96
96
  runComponentDeploy,
97
97
  runInterpretDriver,
98
- DriverGateUnsupportedError,
98
+ type GateContext,
99
99
  DependencyCycleError,
100
100
  UnknownDependencyError,
101
101
  DriverRunFailure,
@@ -108,8 +108,3 @@ export {
108
108
  SingleHostComposeComponent,
109
109
  type SingleHostComposeComponentConfig,
110
110
  } from "./presets/index";
111
- export {
112
- type ComponentTemporalCodegen,
113
- type ComponentTemporalCodegenOptions,
114
- loadComponentTemporalCodegen,
115
- } from "./temporal-codegen-loader";
@@ -16,7 +16,6 @@ vi.mock("../lifecycle/git", () => ({
16
16
  const {
17
17
  maybePersistBuildManifest,
18
18
  extractRunManifest,
19
- extractRunManifestFromPhaseOutputs,
20
19
  } = await import("./manifest-persistence");
21
20
 
22
21
  function makeManifest(component: string, digest: string): BuildArchiveManifest {
@@ -67,23 +66,6 @@ describe("extractRunManifest", () => {
67
66
  });
68
67
  });
69
68
 
70
- describe("extractRunManifestFromPhaseOutputs", () => {
71
- test("finds the manifest across phase outputs (Temporal workflow result shape)", () => {
72
- const manifest = makeManifest("svc", "sha256:abc");
73
- expect(
74
- extractRunManifestFromPhaseOutputs({
75
- Build: { archivePath: "image.tar", digest: "sha256:abc", manifest },
76
- Apply: { ok: true },
77
- }),
78
- ).toEqual(manifest);
79
- });
80
-
81
- test("returns undefined for undefined/empty phaseOutputs", () => {
82
- expect(extractRunManifestFromPhaseOutputs(undefined)).toBeUndefined();
83
- expect(extractRunManifestFromPhaseOutputs({})).toBeUndefined();
84
- });
85
- });
86
-
87
69
  describe("maybePersistBuildManifest", () => {
88
70
  beforeEach(() => {
89
71
  persistBuildManifestMock.mockReset();
@@ -102,8 +84,8 @@ describe("maybePersistBuildManifest", () => {
102
84
  expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
103
85
  });
104
86
 
105
- test("a pre-resolved manifest (Temporal path) takes precedence over records", async () => {
106
- const preResolved = makeManifest("svc", "sha256:temporal");
87
+ test("a pre-resolved manifest takes precedence over records", async () => {
88
+ const preResolved = makeManifest("svc", "sha256:preresolved");
107
89
  persistBuildManifestMock.mockResolvedValue({ commit: "b".repeat(40) });
108
90
 
109
91
  const outcome = await maybePersistBuildManifest({
@@ -13,10 +13,9 @@
13
13
  * doc: a manifest write is a git commit + push, a non-idempotent side effect
14
14
  * with real-world I/O — exactly what `driver.ts` resists taking on (it is
15
15
  * exercised in tests against a bare `CapabilityRegistry` with no lifecycle
16
- * dependency at all) and what Temporal workflow code must never do directly
17
- * (replay-safety). The CLI calls this after `runComponents`/`handle.result()`
18
- * reports success, the same place `maybeRecordAutoRelease` is already
19
- * called from (../cli/handlers/run.ts).
16
+ * dependency at all). The CLI calls this after `runComponents` reports
17
+ * success, the same place `maybeRecordAutoRelease` is already called from
18
+ * (../cli/handlers/run.ts).
20
19
  *
21
20
  * **Extraction is duck-typed, not capability-specific.** `docker-build`,
22
21
  * `generate-sbom`, `extract-config-bom`, and `addArchiveTemplate` (the
@@ -68,25 +67,6 @@ export function extractRunManifest(records: DriverStepRecord[]): BuildArchiveMan
68
67
  return found;
69
68
  }
70
69
 
71
- /**
72
- * Same manifest extraction as `extractRunManifest`, but over a component
73
- * Temporal workflow's returned `phaseOutputs` (`{ [phase]: output }`) —
74
- * mirroring ./auto-release.ts's `extractRunDigestFromPhaseOutputs`, the
75
- * `--temporal` CLI path's counterpart, since that path never sees individual
76
- * step records either.
77
- */
78
- export function extractRunManifestFromPhaseOutputs(
79
- phaseOutputs: Record<string, Record<string, unknown>> | undefined,
80
- ): BuildArchiveManifest | undefined {
81
- let found: BuildArchiveManifest | undefined;
82
- for (const output of Object.values(phaseOutputs ?? {})) {
83
- if (isManifestShaped(output)) {
84
- found = output.manifest;
85
- }
86
- }
87
- return found;
88
- }
89
-
90
70
  /** Explicit reasons `maybePersistBuildManifest` declined to write — never a thrown error, mirroring ./auto-release.ts's `AutoReleaseSkipReason`. */
91
71
  export type ManifestPersistSkipReason = "opted-out" | "run-not-successful" | "no-manifest";
92
72
 
@@ -101,7 +81,7 @@ export interface ManifestPersistRunInfo {
101
81
  success: boolean;
102
82
  /** The component's step records (local executor), used to locate the accumulated manifest via `extractRunManifest`. Mutually exclusive with `manifest`. */
103
83
  records?: DriverStepRecord[];
104
- /** A manifest already resolved by the caller (e.g. a future durable/Temporal path that has its own phaseOutputs-shaped extraction). Takes precedence over `records` when both are given. */
84
+ /** A manifest the caller already resolved by its own means. Takes precedence over `records` when both are given. */
105
85
  manifest?: BuildArchiveManifest;
106
86
  }
107
87
 
@@ -31,7 +31,7 @@ interface Neo4jInstanceConfig {
31
31
  */
32
32
  health: { size: number } | { quorum: true };
33
33
  /** Optional human gate placed before this instance's steps (rolling instances only, never the seed). */
34
- approval?: { signalName: string; description: string; timeout: string };
34
+ approval?: { gate: string; description: string; timeout: string };
35
35
  }
36
36
 
37
37
  const SEED: Neo4jInstanceConfig = {
@@ -55,7 +55,7 @@ const FOLLOWERS: Neo4jInstanceConfig[] = [
55
55
  template: "archive:neo4j-1.template.json",
56
56
  health: { quorum: true },
57
57
  approval: {
58
- signalName: "approve-neo4j-node-1",
58
+ gate: "approve-neo4j-node-1",
59
59
  description: "Confirm the seed node is healthy before rolling to node 1",
60
60
  timeout: "24h",
61
61
  },
@@ -71,7 +71,7 @@ const FOLLOWERS: Neo4jInstanceConfig[] = [
71
71
  /** Build one instance's mini-composition phase — the unit that repeats N times for an N-node cluster. */
72
72
  function instancePhase(instance: Neo4jInstanceConfig): Phase {
73
73
  const steps = [
74
- ...(instance.approval ? [gate(instance.approval.signalName, instance.approval)] : []),
74
+ ...(instance.approval ? [gate(instance.approval.gate, instance.approval)] : []),
75
75
  { kind: "cfn-deploy", template: instance.template },
76
76
  { kind: "code-deploy", instance: instance.index, revision: "@Seed.templateUri" },
77
77
  { kind: "wait-cluster-healthy", ...instance.health },