@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
@@ -2,7 +2,17 @@ import { OpResource } from "./resource";
2
2
  import type { OpConfig, PhaseDefinition, StepDefinition, ActivityStep, GateStep, EffectStep } from "./types";
3
3
  import { isEffectReceipt, type EffectReceiptDeclaration } from "../effect-receipt";
4
4
  import { receiptCheckInput } from "./receipt-store";
5
- import { makeOutProxy, type StepOutputRef } from "./step-output-ref";
5
+ import { makeOutProxy, type StepOutputRef, type WithStepRefs } from "./step-output-ref";
6
+ import type { ChantBuildArgs } from "./activities/build";
7
+ import type { ShellCmdArgs } from "./activities/shell";
8
+ import type { WaitForStackArgs } from "./activities/wait";
9
+ import type { LifecycleSnapshotArgs } from "./activities/lifecycle";
10
+ import type { ChantTeardownArgs } from "./activities/teardown";
11
+ import type { EnvTeardownArgs } from "./activities/env-teardown";
12
+ import type { HttpCheckArgs } from "./activities/http-check";
13
+ import type { PolicyGateArgs } from "./activities/policy";
14
+ import type { GuardValidateArgs } from "./activities/guard-validate";
15
+ import { isValidCronExpression, cronSyntaxMessage } from "./cron";
6
16
 
7
17
  /** An `activity()` result — the plain `ActivityStep` shape plus the `.out` reference sugar (#1290). */
8
18
  export interface NamedActivityStep extends ActivityStep {
@@ -18,7 +28,7 @@ export interface NamedActivityStep extends ActivityStep {
18
28
  // ── Core builders ─────────────────────────────────────────────────────────────
19
29
 
20
30
  /**
21
- * Declare a named, phased Temporal workflow.
31
+ * Declare a named, phased Op.
22
32
  *
23
33
  * @example
24
34
  * ```ts
@@ -31,8 +41,15 @@ export interface NamedActivityStep extends ActivityStep {
31
41
  * ],
32
42
  * });
33
43
  * ```
44
+ *
45
+ * A `schedule` may be supplied for an Op that runs on a cadence (#2120); its
46
+ * cron is validated here, at construction, so a typo fails on `chant build`
47
+ * rather than becoming a schedule that silently never fires.
34
48
  */
35
49
  export function Op(config: OpConfig): InstanceType<typeof OpResource> {
50
+ if (config.schedule && !isValidCronExpression(config.schedule.cron)) {
51
+ throw new Error(`Op "${config.name}": ${cronSyntaxMessage(config.schedule.cron)}`);
52
+ }
36
53
  return new OpResource(config as unknown as Record<string, unknown>);
37
54
  }
38
55
 
@@ -85,14 +102,19 @@ export function activity(
85
102
  return step;
86
103
  }
87
104
 
88
- /** Insert a human gate — the workflow pauses until the named signal is received. */
105
+ /**
106
+ * Insert a human gate. A gate is a fact on the gate ledger, not a wait: a run
107
+ * that reaches this step with no resolution newer than its pending fact
108
+ * records the pending fact and ends `gated`. `chant approve <op> <gate>`
109
+ * writes the resolution, and the next run walks through carrying the approver.
110
+ */
89
111
  export function gate(
90
- signalName: string,
112
+ name: string,
91
113
  opts?: { timeout?: string; description?: string },
92
114
  ): GateStep {
93
115
  return {
94
116
  kind: "gate",
95
- signalName,
117
+ gate: name,
96
118
  ...(opts?.timeout ? { timeout: opts.timeout } : {}),
97
119
  ...(opts?.description ? { description: opts.description } : {}),
98
120
  };
@@ -113,9 +135,10 @@ export function gate(
113
135
  * would sever the step from the declaration that lint, plan, and the lexicon
114
136
  * row all key on.
115
137
  *
116
- * A gate authored inside `steps` pauses only when the effect will fire (the
117
- * matched path never reaches it). The receipt-store activities (`receiptRead`,
118
- * `receiptWrite`) are provided by the receipt row's lexicon (#1835, aws).
138
+ * A gate authored inside `steps` is reached only when the effect will fire
139
+ * (the matched path never reaches it). The receipt-store activities
140
+ * (`receiptRead`, `receiptWrite`) are provided by the receipt row's lexicon
141
+ * (#1835, aws).
119
142
  *
120
143
  * @example
121
144
  * ```ts
@@ -190,10 +213,25 @@ export function takeProfileAndId(
190
213
  return { args, profile, id };
191
214
  }
192
215
 
193
- /** Run an npm build script in the given project directory. `opts.script` selects the script (default `build`, e.g. `build:aws`); `opts.env` adds env vars. */
194
- export const build = (path: string, opts?: Record<string, unknown>): ActivityStep => {
195
- const { args, profile } = takeProfile(opts);
196
- return activity("chantBuild", { path, ...args }, profile);
216
+ /**
217
+ * Extra opts every typed base-activity wrapper below accepts alongside its
218
+ * activity's own fields: the step's `profile` override and its `id` (which
219
+ * routes to the step, never into args, so `.out` works — chant #1290).
220
+ */
221
+ type StepOpts = { profile?: ActivityStep["profile"]; id?: string };
222
+
223
+ /**
224
+ * Run an npm build script in the given project directory. `opts` is
225
+ * {@link ChantBuildArgs} itself, minus the positional `path` — `script`
226
+ * selects the npm script (default `build`, e.g. `build:aws`), `env` adds
227
+ * env vars.
228
+ */
229
+ export const build = (
230
+ path: string,
231
+ opts?: WithStepRefs<Omit<ChantBuildArgs, "path">> & StepOpts,
232
+ ): NamedActivityStep => {
233
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
234
+ return activity("chantBuild", { path, ...args }, { ...(profile ? { profile } : {}), ...(id ? { id } : {}) });
197
235
  };
198
236
 
199
237
  /** Run `kubectl apply -f <manifest>`. Defaults to the `longInfra` profile (override via `opts.profile`). */
@@ -228,10 +266,17 @@ export const helmInstallPinned = (
228
266
  return activity("helmInstall", { name, contentDigest, ...args }, profile ?? "longInfra");
229
267
  };
230
268
 
231
- /** Poll for stack readiness (kubectl rollout, CloudFormation complete, etc). Defaults to the `k8sWait` profile (override via `opts.profile`). */
232
- export const waitForStack = (name: string, opts?: Record<string, unknown>): ActivityStep => {
233
- const { args, profile } = takeProfile(opts);
234
- return activity("waitForStack", { name, ...args }, profile ?? "k8sWait");
269
+ /**
270
+ * Poll until a Kubernetes Deployment/StatefulSet is fully rolled out. `opts` is
271
+ * {@link WaitForStackArgs} itself, minus the positional `name`. Defaults to the
272
+ * `k8sWait` profile (override via `opts.profile`).
273
+ */
274
+ export const waitForStack = (
275
+ name: string,
276
+ opts?: WithStepRefs<Omit<WaitForStackArgs, "name">> & StepOpts,
277
+ ): NamedActivityStep => {
278
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
279
+ return activity("waitForStack", { name, ...args }, { profile: profile ?? "k8sWait", ...(id ? { id } : {}) });
235
280
  };
236
281
 
237
282
  /** Poll any operator-backed Kubernetes resource until it reports ready, driven by a data-only readiness spec (CRD-aware; #365). Defaults to the `k8sWait` profile (override via `opts.profile`). */
@@ -246,20 +291,26 @@ export const gitlabPipeline = (name: string, opts?: Record<string, unknown>): Ac
246
291
  return activity("gitlabPipeline", { name, ...args }, profile ?? "longInfra");
247
292
  };
248
293
 
249
- /** Take a chant lifecycle snapshot for the given environment. */
250
- export const lifecycleSnapshot = (env: string): ActivityStep =>
251
- activity("lifecycleSnapshot", { env });
294
+ /**
295
+ * Take a chant lifecycle snapshot for the given environment.
296
+ * {@link LifecycleSnapshotArgs} has only `env`, which is positional here, so
297
+ * `opts` carries nothing but the step's `id` (for `.out`).
298
+ */
299
+ export const lifecycleSnapshot = (env: string, opts?: { id?: string }): NamedActivityStep =>
300
+ activity("lifecycleSnapshot", { env } satisfies LifecycleSnapshotArgs, opts?.id ? { id: opts.id } : undefined);
252
301
 
253
302
  /**
254
303
  * Run an arbitrary shell command. Tag long-running commands with a `profile`
255
304
  * (e.g. `longInfra` for a multi-GB image push) so they get the right
256
- * start-to-close timeout under both the local executor and Temporal.
305
+ * start-to-close timeout on whichever runtime hosts the run.
257
306
  */
258
307
  export const shell = (
259
308
  cmd: string,
260
- opts?: { env?: Record<string, string>; profile?: ActivityStep["profile"] },
261
- ): ActivityStep =>
262
- activity("shellCmd", { cmd, ...(opts?.env ? { env: opts.env } : {}) }, opts?.profile);
309
+ opts?: WithStepRefs<Omit<ShellCmdArgs, "cmd">> & StepOpts,
310
+ ): NamedActivityStep => {
311
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
312
+ return activity("shellCmd", { cmd, ...args }, { ...(profile ? { profile } : {}), ...(id ? { id } : {}) });
313
+ };
263
314
 
264
315
  /**
265
316
  * Ensure a `generated-once` secret exists in the target store (#1829, epic
@@ -283,9 +334,17 @@ export const ensureSecret = (
283
334
  return activity("ensureSecret", { name, keys, ...args }, profile);
284
335
  };
285
336
 
286
- /** Run `chant teardown` in the given project directory. Uses `longInfra` profile. */
287
- export const teardown = (path: string): ActivityStep =>
288
- activity("chantTeardown", { path }, "longInfra");
337
+ /**
338
+ * Run `chant teardown` in the given project directory. Fixed `longInfra`
339
+ * profile (not overridable). {@link ChantTeardownArgs} has only `path`
340
+ * (positional), so `opts` is just the step's `id` (for `.out`).
341
+ */
342
+ export const teardown = (path: string, opts?: { id?: string }): NamedActivityStep =>
343
+ activity(
344
+ "chantTeardown",
345
+ { path } satisfies ChantTeardownArgs,
346
+ { profile: "longInfra", ...(opts?.id ? { id: opts.id } : {}) },
347
+ );
289
348
 
290
349
  /**
291
350
  * Tear down one environment's marker-owned resources — the durable form of
@@ -309,13 +368,16 @@ export const teardown = (path: string): ActivityStep =>
309
368
  * ]),
310
369
  * ```
311
370
  *
312
- * `opts` also accepts `path` (the chant project directory, default the
313
- * worker's cwd). Defaults to the `longInfra` profile (override via
371
+ * `opts` also accepts `path` (the chant project directory, default the chant
372
+ * process's cwd). Defaults to the `longInfra` profile (override via
314
373
  * `opts.profile`).
315
374
  */
316
- export const envTeardown = (env: string, opts?: Record<string, unknown>): ActivityStep => {
317
- const { args, profile } = takeProfile(opts);
318
- return activity("envTeardown", { env, ...args }, profile ?? "longInfra");
375
+ export const envTeardown = (
376
+ env: string,
377
+ opts?: WithStepRefs<Omit<EnvTeardownArgs, "env">> & StepOpts,
378
+ ): NamedActivityStep => {
379
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
380
+ return activity("envTeardown", { env, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
319
381
  };
320
382
 
321
383
  /**
@@ -455,9 +517,12 @@ export const flociGcpDown = (opts?: Record<string, unknown>): ActivityStep => {
455
517
  * Defaults to the `fastIdempotent` profile. `opts` accepts `method`, `status`
456
518
  * (default any 2xx), `contains` (body substring), `retries`, `intervalMs`.
457
519
  */
458
- export const httpCheck = (url: string, opts?: Record<string, unknown>): ActivityStep => {
459
- const { args, profile } = takeProfile(opts);
460
- return activity("httpCheck", { url, ...args }, profile ?? "fastIdempotent");
520
+ export const httpCheck = (
521
+ url: string,
522
+ opts?: WithStepRefs<Omit<HttpCheckArgs, "url">> & StepOpts,
523
+ ): NamedActivityStep => {
524
+ const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
525
+ return activity("httpCheck", { url, ...args }, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
461
526
  };
462
527
 
463
528
  /**
@@ -546,7 +611,7 @@ export const gcpDelete = (manifestPath: string, opts?: Record<string, unknown>):
546
611
  // The builder and the executor-side activity function share a name (e.g.
547
612
  // `spriteCreate`), and that is intentional: the builder here returns an
548
613
  // `activity("spriteCreate", ...)` step; `loadActivities` loads the function of
549
- // the same name from the temporal lexicon to run the HTTP. They live in
614
+ // the same name from the fly lexicon to run the HTTP. They live in
550
615
  // different modules and are both exported — exactly how `flapsUp`/`flapsDown`
551
616
  // already work. Op files import these builders; the executor resolves the
552
617
  // function by name. Endpoint override + bearer are read by the activity from
@@ -806,14 +871,33 @@ export const spritesDown = (args: {
806
871
 
807
872
  /**
808
873
  * Gate an apply on organizational policy: build the project and run its
809
- * `lint.policies` over the resolved resources, blocking the workflow on any
810
- * violation. Place it before the apply phase. `env` (or `ownership.env`) lets a
874
+ * `lint.policies` over the resolved resources, failing the step on any
875
+ * violation so no later phase runs. Place it before the apply phase. `env` (or `ownership.env`) lets a
811
876
  * policy branch on environment. Single-attempt (`policyCheck` profile) — a
812
877
  * deterministic violation is not retried.
813
878
  */
814
- export const policyGate = (opts?: { env?: string; path?: string }): ActivityStep =>
815
- activity(
879
+ export const policyGate = (opts?: WithStepRefs<PolicyGateArgs> & { id?: string }): NamedActivityStep => {
880
+ const path = (opts?.path as PolicyGateArgs["path"] | undefined) ?? ".";
881
+ const env = opts?.env;
882
+ return activity(
816
883
  "policyGate",
817
- { path: opts?.path ?? ".", ...(opts?.env ? { env: opts.env } : {}) },
818
- "policyCheck",
884
+ { path, ...(env !== undefined ? { env } : {}) },
885
+ { profile: "policyCheck", ...(opts?.id ? { id: opts.id } : {}) },
819
886
  );
887
+ };
888
+
889
+ /**
890
+ * Run an external CloudFormation Guard rules pack against the project's built
891
+ * CloudFormation template (chant #522). `opts` is {@link GuardValidateArgs}
892
+ * itself, minus the positional `rules`; `template` defaults (inside the
893
+ * activity) to `<path>/template.json`. Fixed `policyCheck` profile — same
894
+ * reasoning as {@link policyGate}: a deterministic policy check is
895
+ * single-attempt — and not overridable.
896
+ */
897
+ export const guardValidate = (
898
+ rules: string,
899
+ opts?: WithStepRefs<Omit<GuardValidateArgs, "rules">> & { id?: string },
900
+ ): NamedActivityStep => {
901
+ const { id, ...rest } = (opts ?? {}) as Omit<GuardValidateArgs, "rules"> & { id?: string };
902
+ return activity("guardValidate", { rules, ...rest }, { profile: "policyCheck", ...(id ? { id } : {}) });
903
+ };
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The wake gate (#1981): coalescing, the floor, and abort.
3
+ *
4
+ * Real timers with small floors rather than fake ones: the gate is nothing but
5
+ * two `setTimeout`s racing, and a fake-timer test of that asserts the mock
6
+ * rather than the behaviour.
7
+ */
8
+ import { describe, test, expect } from "vitest";
9
+ import { createChangeSignalGate, DEFAULT_SIGNAL_FLOOR_MS } from "./change-signal";
10
+
11
+ describe("createChangeSignalGate", () => {
12
+ test("no signal: the wait runs the full interval and reports the timer", async () => {
13
+ const gate = createChangeSignalGate({ floorMs: 10 });
14
+ gate.roundStarted();
15
+ const started = Date.now();
16
+ expect(await gate.wait(60)).toBe("timer");
17
+ expect(Date.now() - started).toBeGreaterThanOrEqual(45);
18
+ expect(gate.wakeCount).toBe(0);
19
+ });
20
+
21
+ test("a signal past the floor wakes the sleep early", async () => {
22
+ const gate = createChangeSignalGate({ floorMs: 0 });
23
+ gate.roundStarted();
24
+ const started = Date.now();
25
+ const waiting = gate.wait(5_000);
26
+ setTimeout(() => gate.signal(), 10);
27
+ expect(await waiting).toBe("signal");
28
+ expect(Date.now() - started).toBeLessThan(2_000);
29
+ expect(gate.wakeCount).toBe(1);
30
+ });
31
+
32
+ test("a signal inside the floor waits the floor out rather than waking at once", async () => {
33
+ const gate = createChangeSignalGate({ floorMs: 120 });
34
+ gate.roundStarted();
35
+ const started = Date.now();
36
+ const waiting = gate.wait(5_000);
37
+ gate.signal();
38
+ expect(await waiting).toBe("signal");
39
+ // Woken by the signal, but not before the floor had passed.
40
+ expect(Date.now() - started).toBeGreaterThanOrEqual(100);
41
+ });
42
+
43
+ test("a storm of signals inside one floor window costs exactly one wake", async () => {
44
+ const gate = createChangeSignalGate({ floorMs: 60 });
45
+ gate.roundStarted();
46
+ const waiting = gate.wait(5_000);
47
+ for (let i = 0; i < 500; i++) gate.signal();
48
+ expect(await waiting).toBe("signal");
49
+ expect(gate.signalCount).toBe(500);
50
+ expect(gate.wakeCount).toBe(1);
51
+ });
52
+
53
+ test("the floor is measured from the round, so a steady stream cannot starve the tick", async () => {
54
+ const gate = createChangeSignalGate({ floorMs: 80 });
55
+ gate.roundStarted();
56
+ const started = Date.now();
57
+ const waiting = gate.wait(5_000);
58
+ // A signal every 10ms. A debounce would push the deadline out forever.
59
+ const drip = setInterval(() => gate.signal(), 10);
60
+ const reason = await waiting;
61
+ clearInterval(drip);
62
+ expect(reason).toBe("signal");
63
+ expect(Date.now() - started).toBeLessThan(1_000);
64
+ });
65
+
66
+ test("a signal arriving between rounds is honoured by the next wait, not lost", async () => {
67
+ const gate = createChangeSignalGate({ floorMs: 0 });
68
+ gate.roundStarted();
69
+ gate.signal(); // nothing is sleeping yet
70
+ expect(await gate.wait(5_000)).toBe("signal");
71
+ });
72
+
73
+ test("roundStarted clears the pending flag, so one signal never wakes two rounds", async () => {
74
+ const gate = createChangeSignalGate({ floorMs: 0 });
75
+ gate.roundStarted();
76
+ gate.signal();
77
+ expect(await gate.wait(5_000)).toBe("signal");
78
+ gate.roundStarted();
79
+ expect(await gate.wait(40)).toBe("timer");
80
+ expect(gate.wakeCount).toBe(1);
81
+ });
82
+
83
+ test("abort resolves rather than throwing, before and during a wait", async () => {
84
+ const gate = createChangeSignalGate({ floorMs: 0 });
85
+ const already = new AbortController();
86
+ already.abort();
87
+ expect(await gate.wait(5_000, already.signal)).toBe("aborted");
88
+
89
+ const controller = new AbortController();
90
+ const waiting = gate.wait(5_000, controller.signal);
91
+ setTimeout(() => controller.abort(), 10);
92
+ expect(await waiting).toBe("aborted");
93
+ });
94
+
95
+ test("a signal after abort does nothing", async () => {
96
+ const gate = createChangeSignalGate({ floorMs: 0 });
97
+ const controller = new AbortController();
98
+ const waiting = gate.wait(5_000, controller.signal);
99
+ controller.abort();
100
+ expect(await waiting).toBe("aborted");
101
+ gate.signal();
102
+ expect(gate.wakeCount).toBe(0);
103
+ });
104
+
105
+ test("signal() carries no payload: the type has no argument and the call ignores one", () => {
106
+ const gate = createChangeSignalGate();
107
+ expect(gate.signal.length).toBe(0);
108
+ // A caller that fabricates an event has nowhere to put it: the extra
109
+ // argument is dropped, and the gate's only state is a boolean.
110
+ (gate.signal as (...args: unknown[]) => void)({ kind: "Deployment", name: "fabricated" });
111
+ expect(gate.signalCount).toBe(1);
112
+ });
113
+
114
+ test("the documented floor is a real, positive default", () => {
115
+ expect(DEFAULT_SIGNAL_FLOOR_MS).toBe(5_000);
116
+ });
117
+ });
@@ -0,0 +1,169 @@
1
+ /**
2
+ * The wake gate between a substrate's change signal and `chant operator`'s
3
+ * sleep (#1981, epic #1487).
4
+ *
5
+ * A lexicon that implements `subscribeChanges` (`../lexicon.ts`) can say
6
+ * "something moved". This module is everything the loop does with that: it
7
+ * shortens the current sleep, at most once per floor. It is deliberately the
8
+ * only place a signal touches, so the rule that a signal is a trigger and
9
+ * never a fact is a property of the code rather than a convention. Nothing
10
+ * here has a parameter, a return value or a field that could carry what
11
+ * changed.
12
+ *
13
+ * ## Backpressure: the floor
14
+ *
15
+ * A watch on a busy namespace is not a trickle. A rollout, a Job sweep or a
16
+ * controller resyncing its whole world produces hundreds of events in a
17
+ * second, and each one is a truthful "something moved". Waking a tick per
18
+ * event would turn a convergence loop into a load generator pointed at the
19
+ * cluster it is meant to be watching.
20
+ *
21
+ * So the gate coalesces. Signals are collapsed into a single pending flag, and
22
+ * a pending flag wakes the sleep no earlier than {@link
23
+ * ChangeSignalGateOptions.floorMs} after the last round *started*. A storm of
24
+ * a thousand signals inside one floor window costs exactly one early wake, and
25
+ * a substrate that never stops sending settles into ticking on the floor
26
+ * rather than on the interval, which is the fastest the loop is ever allowed
27
+ * to run.
28
+ *
29
+ * The floor is measured from the start of the last round, not from the last
30
+ * signal, so a steady stream can never push the wake further out (that would
31
+ * be a debounce, and a debounce starves: the busier the cluster, the later the
32
+ * tick). Measuring from the round start makes the guarantee a rate limit,
33
+ * never more than one signal-driven tick per floor, which is the property the
34
+ * loop actually needs.
35
+ */
36
+
37
+ /**
38
+ * The shortest gap between two rounds a change signal may produce. Signals
39
+ * arriving inside this window of the last round's start are coalesced into one
40
+ * wake at the end of it.
41
+ *
42
+ * Five seconds: long enough that a rollout's event storm costs one tick rather
43
+ * than dozens, short enough that "wakes within a second or so of a change"
44
+ * holds for the quiet case a signal exists for. The timer
45
+ * (`DEFAULT_OPERATOR_INTERVAL_MS`, 60s) is unchanged and remains the ceiling.
46
+ */
47
+ export const DEFAULT_SIGNAL_FLOOR_MS = 5_000;
48
+
49
+ /** Why {@link ChangeSignalGate.wait} returned. */
50
+ export type WakeReason =
51
+ /** The full interval elapsed. An ordinary timer-driven round. */
52
+ | "timer"
53
+ /** A substrate signalled and the floor had passed. An early round. */
54
+ | "signal"
55
+ /** The operator is stopping. */
56
+ | "aborted";
57
+
58
+ export interface ChangeSignalGateOptions {
59
+ /** @default DEFAULT_SIGNAL_FLOOR_MS */
60
+ floorMs?: number;
61
+ /** Injectable clock, for tests. @default Date.now */
62
+ now?: () => number;
63
+ }
64
+
65
+ /**
66
+ * One operator loop's wake gate. Not reusable across loops: it carries the
67
+ * time the current loop last started a round, which is what the floor is
68
+ * measured from.
69
+ */
70
+ export interface ChangeSignalGate {
71
+ /**
72
+ * A substrate said something moved. Takes nothing and returns nothing, and
73
+ * that is the enforcement of "a trigger, never a fact": there is no
74
+ * argument for a watch event to ride in on.
75
+ *
76
+ * Safe to call at any time, including while no `wait` is in flight (the flag
77
+ * is remembered and honoured by the next one) and after the loop has
78
+ * stopped (it does nothing).
79
+ */
80
+ signal(): void;
81
+ /** The loop is starting a round now. Resets the pending flag and the floor. */
82
+ roundStarted(): void;
83
+ /**
84
+ * Sleep up to `intervalMs`, resolving early when a signal has passed the
85
+ * floor. Resolves rather than throws on abort, like the timer-only sleep it
86
+ * replaces, so Ctrl-C never surfaces as a loop failure.
87
+ */
88
+ wait(intervalMs: number, abortSignal?: AbortSignal): Promise<WakeReason>;
89
+ /** How many signals have arrived, coalesced or not. Diagnostics and tests. */
90
+ readonly signalCount: number;
91
+ /** How many of those actually shortened a sleep. Diagnostics and tests. */
92
+ readonly wakeCount: number;
93
+ }
94
+
95
+ export function createChangeSignalGate(options: ChangeSignalGateOptions = {}): ChangeSignalGate {
96
+ const floorMs = options.floorMs ?? DEFAULT_SIGNAL_FLOOR_MS;
97
+ const now = options.now ?? (() => Date.now());
98
+
99
+ let pending = false;
100
+ let lastRoundAt = now();
101
+ let signalCount = 0;
102
+ let wakeCount = 0;
103
+ /** Set only while a `wait` is in flight. */
104
+ let arm: (() => void) | undefined;
105
+
106
+ return {
107
+ get signalCount() {
108
+ return signalCount;
109
+ },
110
+ get wakeCount() {
111
+ return wakeCount;
112
+ },
113
+
114
+ signal() {
115
+ signalCount++;
116
+ pending = true;
117
+ arm?.();
118
+ },
119
+
120
+ roundStarted() {
121
+ lastRoundAt = now();
122
+ pending = false;
123
+ },
124
+
125
+ wait(intervalMs: number, abortSignal?: AbortSignal): Promise<WakeReason> {
126
+ return new Promise<WakeReason>((resolve) => {
127
+ if (abortSignal?.aborted) return resolve("aborted");
128
+
129
+ let settled = false;
130
+ let floorTimer: ReturnType<typeof setTimeout> | undefined;
131
+
132
+ const finish = (reason: WakeReason) => {
133
+ if (settled) return;
134
+ settled = true;
135
+ clearTimeout(intervalTimer);
136
+ if (floorTimer) clearTimeout(floorTimer);
137
+ abortSignal?.removeEventListener("abort", onAbort);
138
+ arm = undefined;
139
+ if (reason === "signal") wakeCount++;
140
+ resolve(reason);
141
+ };
142
+
143
+ const intervalTimer = setTimeout(() => finish("timer"), intervalMs);
144
+ const onAbort = () => finish("aborted");
145
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
146
+
147
+ // A pending signal wakes the sleep the moment the floor has passed,
148
+ // and not one moment earlier. `remaining` is measured from the last
149
+ // round's start, so repeated signals inside the window collapse onto
150
+ // the same deadline instead of pushing it out.
151
+ const consider = () => {
152
+ if (settled || !pending) return;
153
+ const remaining = lastRoundAt + floorMs - now();
154
+ if (remaining <= 0) return finish("signal");
155
+ if (floorTimer) return; // already waiting out this window
156
+ floorTimer = setTimeout(() => {
157
+ floorTimer = undefined;
158
+ consider();
159
+ }, remaining);
160
+ };
161
+
162
+ arm = consider;
163
+ // A signal that arrived between rounds, while nothing was sleeping,
164
+ // is honoured here rather than lost.
165
+ consider();
166
+ });
167
+ },
168
+ };
169
+ }