@intentius/chant 0.56.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +20 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +14 -8
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  34. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  35. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  36. package/dist/cli/commands/import.d.ts.map +1 -1
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  38. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  40. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  41. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/lint.d.ts.map +1 -1
  44. package/dist/cli/commands/onboard.d.ts +2 -0
  45. package/dist/cli/commands/onboard.d.ts.map +1 -1
  46. package/dist/cli/handlers/build.d.ts.map +1 -1
  47. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  48. package/dist/cli/handlers/operator.d.ts +82 -16
  49. package/dist/cli/handlers/operator.d.ts.map +1 -1
  50. package/dist/cli/handlers/run.d.ts +49 -42
  51. package/dist/cli/handlers/run.d.ts.map +1 -1
  52. package/dist/cli/main.d.ts +28 -1
  53. package/dist/cli/main.d.ts.map +1 -1
  54. package/dist/cli/mcp/op-tools.d.ts +16 -1
  55. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  56. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  57. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  58. package/dist/cli/registry.d.ts +26 -9
  59. package/dist/cli/registry.d.ts.map +1 -1
  60. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  61. package/dist/components/auto-release.d.ts +10 -20
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability.d.ts +4 -4
  64. package/dist/components/cli-support.d.ts +20 -21
  65. package/dist/components/cli-support.d.ts.map +1 -1
  66. package/dist/components/component.d.ts +3 -3
  67. package/dist/components/component.d.ts.map +1 -1
  68. package/dist/components/driver-output.d.ts.map +1 -1
  69. package/dist/components/driver.d.ts +66 -36
  70. package/dist/components/driver.d.ts.map +1 -1
  71. package/dist/components/index.d.ts +1 -2
  72. package/dist/components/index.d.ts.map +1 -1
  73. package/dist/components/manifest-persistence.d.ts +1 -9
  74. package/dist/components/manifest-persistence.d.ts.map +1 -1
  75. package/dist/components/run-progress.d.ts +6 -6
  76. package/dist/components/run-progress.d.ts.map +1 -1
  77. package/dist/components/verbs/run-agent.d.ts +9 -15
  78. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  79. package/dist/components/verbs/verify.d.ts +2 -2
  80. package/dist/deep-observation.d.ts +17 -0
  81. package/dist/deep-observation.d.ts.map +1 -1
  82. package/dist/discovery/files.d.ts +4 -4
  83. package/dist/discovery/fold-import.d.ts.map +1 -1
  84. package/dist/discovery/param-deps.d.ts +33 -0
  85. package/dist/discovery/param-deps.d.ts.map +1 -1
  86. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  87. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  88. package/dist/fold/foldable-helpers.d.ts +5 -1
  89. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  90. package/dist/fold-provenance.d.ts +236 -0
  91. package/dist/fold-provenance.d.ts.map +1 -0
  92. package/dist/graph-ops.d.ts +1 -1
  93. package/dist/held-elsewhere.d.ts +85 -0
  94. package/dist/held-elsewhere.d.ts.map +1 -0
  95. package/dist/import/ir-utils.d.ts +1 -1
  96. package/dist/import/ir-utils.d.ts.map +1 -1
  97. package/dist/import/parser.d.ts +33 -0
  98. package/dist/import/parser.d.ts.map +1 -1
  99. package/dist/index.d.ts +3 -0
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/kubectl-context.d.ts +3 -3
  102. package/dist/lexicon-config.d.ts +4 -4
  103. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  104. package/dist/lexicon.d.ts +104 -14
  105. package/dist/lexicon.d.ts.map +1 -1
  106. package/dist/lifecycle/change-set.d.ts +13 -0
  107. package/dist/lifecycle/change-set.d.ts.map +1 -1
  108. package/dist/lifecycle/deep-diff.d.ts +133 -6
  109. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  110. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  111. package/dist/lifecycle/gate-ledger.d.ts +71 -3
  112. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  113. package/dist/lifecycle/index.d.ts +1 -0
  114. package/dist/lifecycle/index.d.ts.map +1 -1
  115. package/dist/lifecycle/release-ledger.d.ts +2 -2
  116. package/dist/lifecycle/run-ledger.d.ts +53 -0
  117. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  118. package/dist/lifecycle/symptoms.d.ts +3 -3
  119. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  120. package/dist/lint/config.d.ts +81 -2
  121. package/dist/lint/config.d.ts.map +1 -1
  122. package/dist/lint/post-synth.d.ts +55 -2
  123. package/dist/lint/post-synth.d.ts.map +1 -1
  124. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  125. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  126. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  127. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  128. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  129. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  130. package/dist/lint/rules/comp/index.d.ts +1 -1
  131. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  132. package/dist/lint/rules/op/index.d.ts +16 -0
  133. package/dist/lint/rules/op/index.d.ts.map +1 -0
  134. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  135. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  136. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  137. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  138. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  139. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  140. package/dist/lint/rules/op/support.d.ts +12 -0
  141. package/dist/lint/rules/op/support.d.ts.map +1 -0
  142. package/dist/lint/suppressions.d.ts +108 -0
  143. package/dist/lint/suppressions.d.ts.map +1 -0
  144. package/dist/live-endpoint.d.ts +1 -1
  145. package/dist/op/activities/activity-contracts.d.ts +54 -0
  146. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  147. package/dist/op/activities/apply.d.ts +262 -0
  148. package/dist/op/activities/apply.d.ts.map +1 -0
  149. package/dist/op/activities/build.d.ts +13 -0
  150. package/dist/op/activities/build.d.ts.map +1 -0
  151. package/dist/op/activities/converge.d.ts +110 -0
  152. package/dist/op/activities/converge.d.ts.map +1 -0
  153. package/dist/op/activities/env-teardown.d.ts +76 -0
  154. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  155. package/dist/op/activities/guard-validate.d.ts +64 -0
  156. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  157. package/dist/op/activities/http-check.d.ts +34 -0
  158. package/dist/op/activities/http-check.d.ts.map +1 -0
  159. package/dist/op/activities/index.d.ts +31 -0
  160. package/dist/op/activities/index.d.ts.map +1 -0
  161. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  162. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  163. package/dist/op/activities/lifecycle.d.ts +42 -0
  164. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  165. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  166. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  167. package/dist/op/activities/policy.d.ts +17 -0
  168. package/dist/op/activities/policy.d.ts.map +1 -0
  169. package/dist/op/activities/reconcile.d.ts +89 -0
  170. package/dist/op/activities/reconcile.d.ts.map +1 -0
  171. package/dist/op/activities/shell.d.ts +13 -0
  172. package/dist/op/activities/shell.d.ts.map +1 -0
  173. package/dist/op/activities/teardown.d.ts +10 -0
  174. package/dist/op/activities/teardown.d.ts.map +1 -0
  175. package/dist/op/activities/util.d.ts +7 -0
  176. package/dist/op/activities/util.d.ts.map +1 -0
  177. package/dist/op/activities/wait.d.ts +28 -0
  178. package/dist/op/activities/wait.d.ts.map +1 -0
  179. package/dist/op/activities/workflow-audit.d.ts +92 -0
  180. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  181. package/dist/op/activity-contract-registry.d.ts +76 -0
  182. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  183. package/dist/op/activity-contract.d.ts +25 -18
  184. package/dist/op/activity-contract.d.ts.map +1 -1
  185. package/dist/op/activity-failure.d.ts +28 -0
  186. package/dist/op/activity-failure.d.ts.map +1 -0
  187. package/dist/op/activity-profiles.d.ts +118 -0
  188. package/dist/op/activity-profiles.d.ts.map +1 -0
  189. package/dist/op/activity-registry.d.ts +22 -38
  190. package/dist/op/activity-registry.d.ts.map +1 -1
  191. package/dist/op/activity-runtime.d.ts +3 -14
  192. package/dist/op/activity-runtime.d.ts.map +1 -1
  193. package/dist/op/builders.d.ts +84 -29
  194. package/dist/op/builders.d.ts.map +1 -1
  195. package/dist/op/composites/apply-op.d.ts +113 -0
  196. package/dist/op/composites/apply-op.d.ts.map +1 -0
  197. package/dist/op/composites/converge-op.d.ts +120 -0
  198. package/dist/op/composites/converge-op.d.ts.map +1 -0
  199. package/dist/op/composites/index.d.ts +26 -0
  200. package/dist/op/composites/index.d.ts.map +1 -0
  201. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  202. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  203. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  204. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  205. package/dist/op/composites/reconcile-op.d.ts +57 -0
  206. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  207. package/dist/op/composites/watch-op.d.ts +60 -0
  208. package/dist/op/composites/watch-op.d.ts.map +1 -0
  209. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  210. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  211. package/dist/op/converge-rule.d.ts +12 -10
  212. package/dist/op/converge-rule.d.ts.map +1 -1
  213. package/dist/op/cron.d.ts +51 -0
  214. package/dist/op/cron.d.ts.map +1 -0
  215. package/dist/op/discover.d.ts +9 -0
  216. package/dist/op/discover.d.ts.map +1 -1
  217. package/dist/op/duration.d.ts +11 -0
  218. package/dist/op/duration.d.ts.map +1 -0
  219. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  220. package/dist/op/gate.d.ts +90 -0
  221. package/dist/op/gate.d.ts.map +1 -0
  222. package/dist/op/generate-pipeline.d.ts +9 -0
  223. package/dist/op/generate-pipeline.d.ts.map +1 -1
  224. package/dist/op/index.d.ts +23 -7
  225. package/dist/op/index.d.ts.map +1 -1
  226. package/dist/op/local-executor.d.ts +114 -28
  227. package/dist/op/local-executor.d.ts.map +1 -1
  228. package/dist/op/local-output.d.ts +11 -1
  229. package/dist/op/local-output.d.ts.map +1 -1
  230. package/dist/op/op-ir.d.ts +184 -0
  231. package/dist/op/op-ir.d.ts.map +1 -0
  232. package/dist/op/op-verb-class.d.ts +10 -2
  233. package/dist/op/op-verb-class.d.ts.map +1 -1
  234. package/dist/op/operator.d.ts +30 -5
  235. package/dist/op/operator.d.ts.map +1 -1
  236. package/dist/op/receipt-store.d.ts +1 -1
  237. package/dist/op/receipt-store.d.ts.map +1 -1
  238. package/dist/op/resource.d.ts +15 -1
  239. package/dist/op/resource.d.ts.map +1 -1
  240. package/dist/op/runtime.d.ts +200 -0
  241. package/dist/op/runtime.d.ts.map +1 -0
  242. package/dist/op/runtimes/local.d.ts +29 -0
  243. package/dist/op/runtimes/local.d.ts.map +1 -0
  244. package/dist/op/step-output-ref.d.ts +15 -13
  245. package/dist/op/step-output-ref.d.ts.map +1 -1
  246. package/dist/op/types.d.ts +79 -27
  247. package/dist/op/types.d.ts.map +1 -1
  248. package/dist/ownership.d.ts +1 -1
  249. package/dist/provenance.d.ts +21 -0
  250. package/dist/provenance.d.ts.map +1 -1
  251. package/dist/serializer-walker.d.ts.map +1 -1
  252. package/dist/stack-output.d.ts +5 -0
  253. package/dist/stack-output.d.ts.map +1 -1
  254. package/package.json +6 -1
  255. package/src/audit/catalog.test.ts +79 -3
  256. package/src/audit/catalog.ts +111 -13
  257. package/src/audit/core.test.ts +26 -0
  258. package/src/audit/core.ts +61 -17
  259. package/src/audit/discover.test.ts +39 -0
  260. package/src/audit/discover.ts +91 -15
  261. package/src/audit/lineage.ts +100 -0
  262. package/src/audit/prior-art.ts +153 -0
  263. package/src/audit/proof.test.ts +67 -0
  264. package/src/audit/proof.ts +70 -0
  265. package/src/audit/report-html.ts +9 -4
  266. package/src/audit/report-model.ts +16 -2
  267. package/src/audit/report.test.ts +33 -0
  268. package/src/audit/report.ts +5 -3
  269. package/src/audit/rules-doc.test.ts +34 -2
  270. package/src/audit/rules-doc.ts +82 -9
  271. package/src/audit/secrets.ts +15 -3
  272. package/src/audit/terraform-state.test.ts +144 -0
  273. package/src/audit/terraform-state.ts +131 -0
  274. package/src/build.ts +31 -1
  275. package/src/claimed-fields.test.ts +145 -0
  276. package/src/claimed-fields.ts +208 -0
  277. package/src/cli/build-params-cli.ts +2 -2
  278. package/src/cli/command-group.ts +14 -0
  279. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  280. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  281. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  282. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  283. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  284. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  285. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  286. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  287. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  288. package/src/cli/commands/audit.test.ts +189 -11
  289. package/src/cli/commands/audit.ts +73 -27
  290. package/src/cli/commands/build.test.ts +292 -9
  291. package/src/cli/commands/build.ts +156 -24
  292. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  293. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  294. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  295. package/src/cli/commands/import.ts +6 -0
  296. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  297. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  298. package/src/cli/commands/init-lexicon.test.ts +97 -2
  299. package/src/cli/commands/init-lexicon.ts +4 -2
  300. package/src/cli/commands/init.test.ts +35 -1
  301. package/src/cli/commands/init.ts +14 -3
  302. package/src/cli/commands/lint.test.ts +48 -0
  303. package/src/cli/commands/lint.ts +123 -0
  304. package/src/cli/commands/onboard.test.ts +75 -0
  305. package/src/cli/commands/onboard.ts +54 -23
  306. package/src/cli/handlers/build.test.ts +81 -1
  307. package/src/cli/handlers/build.ts +15 -1
  308. package/src/cli/handlers/graph.test.ts +3 -3
  309. package/src/cli/handlers/lifecycle.test.ts +195 -12
  310. package/src/cli/handlers/lifecycle.ts +123 -6
  311. package/src/cli/handlers/misc.ts +1 -1
  312. package/src/cli/handlers/operator.test.ts +183 -11
  313. package/src/cli/handlers/operator.ts +260 -55
  314. package/src/cli/handlers/run.test.ts +431 -1287
  315. package/src/cli/handlers/run.ts +365 -915
  316. package/src/cli/main.test.ts +23 -15
  317. package/src/cli/main.ts +88 -33
  318. package/src/cli/mcp/op-tools.ts +147 -88
  319. package/src/cli/mcp/resource-handlers.ts +10 -37
  320. package/src/cli/mcp/resources/context.ts +11 -12
  321. package/src/cli/mcp/server.test.ts +25 -27
  322. package/src/cli/mcp/server.ts +2 -2
  323. package/src/cli/registry.ts +26 -9
  324. package/src/codegen/docs.ts +1 -1
  325. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  326. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  327. package/src/components/README.md +3 -2
  328. package/src/components/auto-release.test.ts +4 -20
  329. package/src/components/auto-release.ts +17 -42
  330. package/src/components/capability.ts +4 -4
  331. package/src/components/cli-support.test.ts +10 -5
  332. package/src/components/cli-support.ts +52 -44
  333. package/src/components/component.schema.json +2 -2
  334. package/src/components/component.ts +3 -3
  335. package/src/components/driver-output.ts +14 -2
  336. package/src/components/driver.test.ts +92 -22
  337. package/src/components/driver.ts +193 -83
  338. package/src/components/index.ts +1 -6
  339. package/src/components/manifest-persistence.test.ts +2 -20
  340. package/src/components/manifest-persistence.ts +4 -24
  341. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  342. package/src/components/run-progress.ts +6 -6
  343. package/src/components/verbs/run-agent.ts +11 -17
  344. package/src/components/verbs/verify.ts +2 -2
  345. package/src/deep-observation.test.ts +75 -0
  346. package/src/deep-observation.ts +48 -0
  347. package/src/discovery/collect.test.ts +3 -3
  348. package/src/discovery/files.ts +4 -4
  349. package/src/discovery/fold-import.ts +105 -2
  350. package/src/discovery/param-deps.test.ts +112 -1
  351. package/src/discovery/param-deps.ts +193 -0
  352. package/src/discovery/sandbox/bundle.ts +15 -1
  353. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  354. package/src/discovery/sandbox/config-wire.ts +2 -2
  355. package/src/fold/fold.test.ts +56 -0
  356. package/src/fold/foldable-helpers.ts +81 -1
  357. package/src/fold-provenance-exclusion.test.ts +186 -0
  358. package/src/fold-provenance.test.ts +495 -0
  359. package/src/fold-provenance.ts +441 -0
  360. package/src/graph-ops.test.ts +2 -2
  361. package/src/graph-ops.ts +1 -1
  362. package/src/held-elsewhere.test.ts +102 -0
  363. package/src/held-elsewhere.ts +114 -0
  364. package/src/import/ir-utils.ts +11 -1
  365. package/src/import/parser.ts +35 -0
  366. package/src/index.ts +3 -0
  367. package/src/kubectl-context.ts +3 -3
  368. package/src/lexicon-config.test.ts +5 -5
  369. package/src/lexicon-config.ts +4 -4
  370. package/src/lexicon-plugin-helpers.ts +1 -1
  371. package/src/lexicon.ts +120 -14
  372. package/src/lifecycle/change-set.test.ts +49 -0
  373. package/src/lifecycle/change-set.ts +67 -0
  374. package/src/lifecycle/converge-ledger.ts +1 -1
  375. package/src/lifecycle/deep-diff.test.ts +267 -14
  376. package/src/lifecycle/deep-diff.ts +217 -14
  377. package/src/lifecycle/deep-observe.test.ts +3 -1
  378. package/src/lifecycle/deep-observe.ts +16 -6
  379. package/src/lifecycle/gate-ledger.test.ts +74 -2
  380. package/src/lifecycle/gate-ledger.ts +143 -36
  381. package/src/lifecycle/index.ts +1 -0
  382. package/src/lifecycle/release-ledger.ts +2 -2
  383. package/src/lifecycle/run-ledger.test.ts +268 -0
  384. package/src/lifecycle/run-ledger.ts +201 -0
  385. package/src/lifecycle/symptoms.ts +3 -3
  386. package/src/lint/config.test.ts +82 -1
  387. package/src/lint/config.ts +112 -3
  388. package/src/lint/policy.test.ts +1 -1
  389. package/src/lint/post-synth.test.ts +31 -0
  390. package/src/lint/post-synth.ts +54 -1
  391. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  392. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  393. package/src/lint/rules/comp/comp.test.ts +1 -1
  394. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
  395. package/src/lint/rules/comp/index.ts +3 -3
  396. package/src/lint/rules/op/index.ts +23 -0
  397. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  398. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  399. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  400. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  401. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  402. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  403. package/src/lint/rules/op/support.ts +11 -0
  404. package/src/lint/suppressions.test.ts +163 -0
  405. package/src/lint/suppressions.ts +204 -0
  406. package/src/live-endpoint.ts +1 -1
  407. package/src/op/activities/activity-contracts.ts +66 -0
  408. package/src/op/activities/apply.test.ts +567 -0
  409. package/src/op/activities/apply.ts +662 -0
  410. package/src/op/activities/build.ts +26 -0
  411. package/src/op/activities/converge.test.ts +330 -0
  412. package/src/op/activities/converge.ts +449 -0
  413. package/src/op/activities/env-teardown.test.ts +187 -0
  414. package/src/op/activities/env-teardown.ts +171 -0
  415. package/src/op/activities/guard-validate.test.ts +139 -0
  416. package/src/op/activities/guard-validate.ts +223 -0
  417. package/src/op/activities/http-check.test.ts +48 -0
  418. package/src/op/activities/http-check.ts +55 -0
  419. package/src/op/activities/index.ts +119 -0
  420. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  421. package/src/op/activities/lexicon-upgrade.ts +673 -0
  422. package/src/op/activities/lifecycle.ts +85 -0
  423. package/src/op/activities/pipeline-audit.test.ts +67 -0
  424. package/src/op/activities/pipeline-audit.ts +201 -0
  425. package/src/op/activities/policy.test.ts +19 -0
  426. package/src/op/activities/policy.ts +37 -0
  427. package/src/op/activities/reconcile.test.ts +81 -0
  428. package/src/op/activities/reconcile.ts +187 -0
  429. package/src/op/activities/shell.ts +26 -0
  430. package/src/op/activities/teardown.ts +22 -0
  431. package/src/op/activities/util.ts +6 -0
  432. package/src/op/activities/wait.ts +69 -0
  433. package/src/op/activities/workflow-audit.test.ts +90 -0
  434. package/src/op/activities/workflow-audit.ts +203 -0
  435. package/src/op/activity-contract-registry.test.ts +98 -0
  436. package/src/op/activity-contract-registry.ts +114 -0
  437. package/src/op/activity-contract.test.ts +1 -1
  438. package/src/op/activity-contract.ts +37 -33
  439. package/src/op/activity-failure.ts +34 -0
  440. package/src/op/activity-profiles.test.ts +56 -0
  441. package/src/op/activity-profiles.ts +116 -0
  442. package/src/op/activity-registry.test.ts +37 -28
  443. package/src/op/activity-registry.ts +27 -56
  444. package/src/op/activity-runtime.ts +3 -47
  445. package/src/op/builders-exports.test.ts +0 -49
  446. package/src/op/builders-typed.test.ts +164 -0
  447. package/src/op/builders.ts +123 -39
  448. package/src/op/composites/apply-op.ts +208 -0
  449. package/src/op/composites/composites.test.ts +366 -0
  450. package/src/op/composites/converge-op.test.ts +168 -0
  451. package/src/op/composites/converge-op.ts +214 -0
  452. package/src/op/composites/index.ts +26 -0
  453. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  454. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  455. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  456. package/src/op/composites/pipeline-audit-op.ts +78 -0
  457. package/src/op/composites/reconcile-op.test.ts +51 -0
  458. package/src/op/composites/reconcile-op.ts +107 -0
  459. package/src/op/composites/watch-op.ts +108 -0
  460. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  461. package/src/op/composites/workflow-audit-op.ts +88 -0
  462. package/src/op/converge-rule.ts +12 -10
  463. package/src/op/cron.test.ts +128 -0
  464. package/src/op/cron.ts +149 -0
  465. package/src/op/discover-root.test.ts +105 -1
  466. package/src/op/discover.test.ts +6 -2
  467. package/src/op/discover.ts +84 -16
  468. package/src/op/duration.ts +21 -0
  469. package/src/op/effect-step.test.ts +26 -11
  470. package/src/op/emulator-lifecycle.ts +1 -2
  471. package/src/op/gate.ts +155 -0
  472. package/src/op/generate-pipeline.test.ts +65 -3
  473. package/src/op/generate-pipeline.ts +19 -2
  474. package/src/op/index.ts +39 -6
  475. package/src/op/local-executor.test.ts +163 -34
  476. package/src/op/local-executor.ts +370 -102
  477. package/src/op/local-output.test.ts +95 -11
  478. package/src/op/local-output.ts +33 -4
  479. package/src/op/op-ir.test.ts +281 -0
  480. package/src/op/op-ir.ts +417 -0
  481. package/src/op/op-verb-class.ts +19 -5
  482. package/src/op/op.test.ts +26 -5
  483. package/src/op/operator.test.ts +175 -6
  484. package/src/op/operator.ts +63 -16
  485. package/src/op/receipt-store.ts +1 -1
  486. package/src/op/resource.ts +20 -2
  487. package/src/op/runtime.ts +203 -0
  488. package/src/op/runtimes/local.test.ts +181 -0
  489. package/src/op/runtimes/local.ts +212 -0
  490. package/src/op/step-output-ref.ts +15 -13
  491. package/src/op/types.ts +84 -24
  492. package/src/ownership.ts +1 -1
  493. package/src/provenance.test.ts +6 -0
  494. package/src/provenance.ts +21 -1
  495. package/src/serializer-walker.test.ts +42 -0
  496. package/src/serializer-walker.ts +21 -2
  497. package/src/stack-output.ts +6 -1
  498. package/dist/cli/handlers/op-progress.d.ts +0 -90
  499. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  500. package/dist/cli/handlers/run-client.d.ts +0 -127
  501. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  502. package/dist/cli/handlers/run-report.d.ts +0 -5
  503. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  504. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  505. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  506. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  507. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  508. package/src/cli/handlers/op-progress.test.ts +0 -268
  509. package/src/cli/handlers/op-progress.ts +0 -248
  510. package/src/cli/handlers/run-client.test.ts +0 -82
  511. package/src/cli/handlers/run-client.ts +0 -219
  512. package/src/cli/handlers/run-report.test.ts +0 -62
  513. package/src/cli/handlers/run-report.ts +0 -122
  514. package/src/components/temporal-codegen-loader.ts +0 -41
  515. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -0,0 +1,181 @@
1
+ import { describe, test, expect, vi, beforeEach } from "vitest";
2
+ import type { OpConfig } from "../types";
3
+ import type { OpRunRecord, OpRunRecordInput } from "../runtime";
4
+
5
+ const loadActivitiesMock = vi.fn();
6
+ const loadProfilesMock = vi.fn();
7
+ const loadChantConfigMock = vi.fn();
8
+
9
+ vi.mock("../activity-registry", async () => {
10
+ const actual = await vi.importActual<typeof import("../activity-registry")>("../activity-registry");
11
+ return {
12
+ ...actual,
13
+ loadActivities: (...args: unknown[]) => loadActivitiesMock(...args),
14
+ loadProfiles: (...args: unknown[]) => loadProfilesMock(...args),
15
+ };
16
+ });
17
+ vi.mock("../../config", async () => {
18
+ const actual = await vi.importActual<typeof import("../../config")>("../../config");
19
+ return { ...actual, loadChantConfig: (...args: unknown[]) => loadChantConfigMock(...args) };
20
+ });
21
+
22
+ // The gate ledger a local run consults (#2119) is the `chant/lifecycle` orphan
23
+ // branch by default. Point it at memory here so a unit test never writes a
24
+ // fact to the real repo.
25
+ vi.mock("../gate", async () => {
26
+ const actual = await vi.importActual<typeof import("../gate")>("../gate");
27
+ return { ...actual, gitGateLedgerPort: () => actual.memoryGateLedgerPort() };
28
+ });
29
+
30
+ /** The run ledger, in memory — see the mock below. Cleared before each test. */
31
+ const runLedger: OpRunRecord[] = [];
32
+
33
+ // The run ledger this runtime appends to and answers from (#2118) is that same
34
+ // orphan branch. In memory here for the same reason the gate ledger is: a unit
35
+ // test must never leave a fact in the real repo. Everything else about the
36
+ // ledger path stays real, so these tests exercise the actual read-back.
37
+ vi.mock("../../lifecycle/run-ledger", async () => {
38
+ const actual = await vi.importActual<typeof import("../../lifecycle/run-ledger")>("../../lifecycle/run-ledger");
39
+ return {
40
+ ...actual,
41
+ appendRunRecord: async (input: OpRunRecordInput) => {
42
+ const record: OpRunRecord = { version: 1, ...input, id: input.id ?? `run-${runLedger.length}` };
43
+ runLedger.push(record);
44
+ return { commit: "0".repeat(40), record };
45
+ },
46
+ readRunLedger: async (_env: string, op: string) => ({
47
+ records: runLedger.filter((r) => r.op === op),
48
+ malformed: 0,
49
+ }),
50
+ };
51
+ });
52
+
53
+ const { createLocalOpRuntime } = await import("./local");
54
+
55
+ function op(name: string, steps: unknown[]): OpConfig {
56
+ return {
57
+ name,
58
+ overview: `${name} overview`,
59
+ phases: [{ name: "main", steps }],
60
+ } as unknown as OpConfig;
61
+ }
62
+
63
+ describe("the local op runtime", () => {
64
+ beforeEach(() => {
65
+ loadActivitiesMock.mockReset();
66
+ loadProfilesMock.mockReset().mockResolvedValue({ fastIdempotent: { timeout: "1m" } });
67
+ loadChantConfigMock.mockReset().mockResolvedValue({ config: { lexicons: ["aws"] } });
68
+ runLedger.length = 0;
69
+ });
70
+
71
+ test("start runs the Op and reports it completed, with the executor's own result", async () => {
72
+ loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({ done: true }))]]));
73
+ const runtime = createLocalOpRuntime();
74
+
75
+ const handle = await runtime.start(op("hello", [{ kind: "activity", fn: "ok", args: {} }]), {});
76
+ const status = await handle.result();
77
+
78
+ expect(runtime.name).toBe("local");
79
+ expect(status.state).toBe("completed");
80
+ expect(status.result?.status).toBe("ok");
81
+ expect(status.records?.map((r) => r.fn)).toEqual(["ok"]);
82
+ });
83
+
84
+ test("the project's configured lexicons decide which appliers load", async () => {
85
+ loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
86
+ const runtime = createLocalOpRuntime();
87
+ await (await runtime.start(op("hello", [{ kind: "activity", fn: "ok", args: {} }]), {})).result();
88
+ expect(loadActivitiesMock).toHaveBeenCalledWith(["aws"]);
89
+ });
90
+
91
+ test("a failing step settles as failed rather than throwing out of result()", async () => {
92
+ loadActivitiesMock.mockResolvedValue(new Map([["boom", vi.fn(async () => { throw new Error("nope"); })]]));
93
+ const runtime = createLocalOpRuntime();
94
+
95
+ const handle = await runtime.start(op("bad", [{ kind: "activity", fn: "boom", args: {} }]), {});
96
+ const status = await handle.result();
97
+
98
+ expect(status.state).toBe("failed");
99
+ expect(status.result?.status).toBe("fail");
100
+ });
101
+
102
+ test("progress is called once per settled step", async () => {
103
+ loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
104
+ const runtime = createLocalOpRuntime();
105
+ const seen: string[] = [];
106
+
107
+ const handle = await runtime.start(
108
+ op("hello", [
109
+ { kind: "activity", fn: "ok", args: {} },
110
+ { kind: "activity", fn: "ok", args: {} },
111
+ ]),
112
+ { progress: (record) => seen.push(record.fn) },
113
+ );
114
+ await handle.result();
115
+
116
+ expect(seen).toEqual(["ok", "ok"]);
117
+ });
118
+
119
+ test("a gated Op settles as gated, naming the gate, and runs nothing after it (#2119)", async () => {
120
+ const after = vi.fn(async () => ({}));
121
+ loadActivitiesMock.mockResolvedValue(new Map([["after", after]]));
122
+ const runtime = createLocalOpRuntime();
123
+
124
+ const handle = await runtime.start(
125
+ op("gated", [
126
+ { kind: "gate", signalName: "approve-prod" },
127
+ { kind: "activity", fn: "after", args: {} },
128
+ ]),
129
+ {},
130
+ );
131
+ const status = await handle.result();
132
+
133
+ expect(status.state).toBe("gated");
134
+ expect(status.gate?.name).toBe("approve-prod");
135
+ expect(status.result?.status).toBe("gated");
136
+ expect(after).not.toHaveBeenCalled();
137
+ });
138
+
139
+ test("status, log and list answer from the run ledger (#2118)", async () => {
140
+ loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
141
+ const runtime = createLocalOpRuntime();
142
+ const config = op("hello", [{ kind: "activity", fn: "ok", args: {} }]);
143
+
144
+ expect(await runtime.status("hello")).toBeUndefined();
145
+ expect(await runtime.log("hello")).toEqual([]);
146
+
147
+ await (await runtime.start(config, {})).result();
148
+ await (await runtime.start(config, {})).result();
149
+
150
+ // Two records on the ledger, not two entries in a process-local map.
151
+ expect(runLedger.map((r) => r.op)).toEqual(["hello", "hello"]);
152
+ expect((await runtime.status("hello"))?.state).toBe("completed");
153
+ expect(await runtime.log("hello")).toHaveLength(2);
154
+ expect(await runtime.log("hello", { limit: 1 })).toHaveLength(1);
155
+ expect((await runtime.list([config])).get("hello")?.state).toBe("completed");
156
+
157
+ // Newest first, and the ledger's own id is the run id a reader sees.
158
+ const [newest] = await runtime.log("hello");
159
+ expect(newest.id).toBe(runLedger[1].id);
160
+ expect((await runtime.status("hello"))?.runId).toBe(runLedger[1].id);
161
+ });
162
+
163
+ test("a run the ledger could not record still answers from this process", async () => {
164
+ loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
165
+ const runtime = createLocalOpRuntime();
166
+ const config = op("hello", [{ kind: "activity", fn: "ok", args: {} }]);
167
+
168
+ await (await runtime.start(config, {})).result();
169
+ // Whatever the ledger holds is lost (an unwritable branch, a project that
170
+ // is not a checkout); the in-memory history is the fallback.
171
+ runLedger.length = 0;
172
+
173
+ expect((await runtime.status("hello"))?.state).toBe("completed");
174
+ expect((await runtime.list([config])).get("hello")?.state).toBe("completed");
175
+ });
176
+
177
+ test("cancel says why a foreground run has nothing to cancel", async () => {
178
+ const runtime = createLocalOpRuntime();
179
+ await expect(runtime.cancel("hello", { force: true })).rejects.toThrow(/foreground/);
180
+ });
181
+ });
@@ -0,0 +1,212 @@
1
+ /**
2
+ * The built-in `local` op runtime (#2121, epic #2114).
3
+ *
4
+ * Wraps `runOpLocally` (../local-executor.ts) in the {@link OpRuntimeProvider}
5
+ * contract so `chant run <op>` has one dispatch path whether the run is hosted
6
+ * here or by a lexicon's `opRuntime`. Behaviour is the executor's, unchanged:
7
+ * activities and profiles come from the project's configured lexicons, a gate
8
+ * is decided against the gate ledger and ends the run `gated` (#2119), and
9
+ * Ctrl-C aborts through the caller's `AbortSignal`.
10
+ *
11
+ * Status, log and list read the run ledger (#2118): every run this provider
12
+ * starts appends one `OpRunRecord` to `<env>/runs__<op>.jsonl` on the
13
+ * lifecycle branch, so an answer here outlives the process that produced it
14
+ * and a run started by cron, CI or another machine is visible too. The
15
+ * in-memory history stays as the fallback for the case the ledger cannot cover
16
+ * — a project that is not a checkout, or a run whose append failed — so a
17
+ * `chant run` followed by `chant run status` in the same process still
18
+ * answers.
19
+ */
20
+
21
+ import { loadChantConfig } from "../../config";
22
+ import { loadActivities, loadProfiles } from "../activity-registry";
23
+ import { runOpLocally, OpRunFailure, type OpRunResult } from "../local-executor";
24
+ import { runComponents } from "../../components/cli-support";
25
+ import { discoverOps } from "../discover";
26
+ import { readRunLedger, runEnvOf, DEFAULT_RUN_ENV } from "../../lifecycle/run-ledger";
27
+ import type { OpConfig } from "../types";
28
+ import {
29
+ runStateOf,
30
+ type OpRunHandle,
31
+ type OpRunRecord,
32
+ type OpRunStartOptions,
33
+ type OpRunStatus,
34
+ type OpRuntimeProvider,
35
+ } from "../runtime";
36
+
37
+ /** Every run this process has started, newest last, keyed by op name. */
38
+ type RunLog = Map<string, OpRunStatus[]>;
39
+
40
+ function statusFrom(
41
+ op: string,
42
+ runId: string,
43
+ startedAt: string,
44
+ result: OpRunResult,
45
+ ): OpRunStatus {
46
+ return {
47
+ op,
48
+ runId,
49
+ state: runStateOf(result.status),
50
+ startedAt,
51
+ endedAt: new Date().toISOString(),
52
+ records: result.records,
53
+ result,
54
+ ...(result.gate ? { gate: { name: result.gate.gate, since: result.gate.timestamp } } : {}),
55
+ };
56
+ }
57
+
58
+ /**
59
+ * A ledger record read back as a runtime status. `records` and `result` are
60
+ * absent on purpose: the ledger keeps each step's verdict, not the activity
61
+ * return values a live `OpRunResult` carries, and inventing them would make a
62
+ * replayed answer look like a live one.
63
+ */
64
+ function statusFromRecord(record: OpRunRecord): OpRunStatus {
65
+ return {
66
+ op: record.op,
67
+ runId: record.id,
68
+ state: runStateOf(record.status),
69
+ startedAt: record.started,
70
+ endedAt: record.ended,
71
+ ...(record.gate ? { gate: record.gate } : {}),
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Build the local provider. `projectPath` is where `chant.config.ts` is read
77
+ * from to decide which cloud appliers to load — the same best-effort read the
78
+ * CLI did inline before the seam existed.
79
+ */
80
+ export function createLocalOpRuntime(opts: { projectPath?: string } = {}): OpRuntimeProvider {
81
+ const runs: RunLog = new Map();
82
+ const projectPath = opts.projectPath ?? process.cwd();
83
+
84
+ const record = (status: OpRunStatus): void => {
85
+ const existing = runs.get(status.op);
86
+ if (existing) existing.push(status);
87
+ else runs.set(status.op, [status]);
88
+ };
89
+
90
+ // A run ledger is keyed `<env>/runs__<op>.jsonl`, and `status`/`log` are
91
+ // handed a name rather than a config. `start` and `list` know the config and
92
+ // seed this; otherwise the same `*.op.ts` scan that found the Op in the
93
+ // first place resolves its `labels.Env`.
94
+ const envs = new Map<string, string>();
95
+ const noteEnv = (op: OpConfig): string => {
96
+ const env = runEnvOf(op);
97
+ envs.set(op.name, env);
98
+ return env;
99
+ };
100
+
101
+ const envFor = async (op: string): Promise<string> => {
102
+ const known = envs.get(op);
103
+ if (known) return known;
104
+ try {
105
+ const { ops } = await discoverOps({ cwd: projectPath });
106
+ for (const discovered of ops.values()) noteEnv(discovered.config);
107
+ } catch {
108
+ // Not a checkout — nothing to scan; fall through to the default env.
109
+ }
110
+ return envs.get(op) ?? DEFAULT_RUN_ENV;
111
+ };
112
+
113
+ /** This op's ledger history, oldest first. Empty when there is no ledger to read. */
114
+ const ledgerFor = async (op: string, env?: string): Promise<OpRunRecord[]> => {
115
+ try {
116
+ const { records } = await readRunLedger(env ?? (await envFor(op)), op, { cwd: projectPath });
117
+ return records;
118
+ } catch {
119
+ return [];
120
+ }
121
+ };
122
+
123
+ return {
124
+ name: "local",
125
+
126
+ async start(op: OpConfig, startOpts: OpRunStartOptions): Promise<OpRunHandle> {
127
+ // The project's configured lexicons decide which cloud appliers to load
128
+ // (aws -> floci, gcp -> gcpApply, azure -> az group). Best-effort: an
129
+ // unreadable config just yields the base activities.
130
+ let lexicons: string[] = [];
131
+ try {
132
+ lexicons = (await loadChantConfig(projectPath)).config.lexicons ?? [];
133
+ } catch {
134
+ // No/invalid chant.config — base activities only.
135
+ }
136
+
137
+ const [activities, profiles] = await Promise.all([loadActivities(lexicons), loadProfiles()]);
138
+
139
+ const runId = `local-${Date.now()}`;
140
+ const startedAt = new Date().toISOString();
141
+ noteEnv(op);
142
+
143
+ const settled = (async (): Promise<OpRunStatus> => {
144
+ try {
145
+ const result = await runOpLocally(
146
+ op,
147
+ activities,
148
+ profiles,
149
+ startOpts.signal,
150
+ {
151
+ runId,
152
+ // The run's outcome is a durable fact (#2118): the executor
153
+ // appends it here, at the one seam every local run passes
154
+ // through, rather than in the CLI handler above it.
155
+ ledger: { cwd: projectPath },
156
+ ...(startOpts.progress ? { onRecord: startOpts.progress } : {}),
157
+ },
158
+ );
159
+ const status = statusFrom(op.name, runId, startedAt, result);
160
+ record(status);
161
+ return status;
162
+ } catch (err) {
163
+ if (err instanceof OpRunFailure) {
164
+ const status = statusFrom(op.name, runId, startedAt, err.result);
165
+ record(status);
166
+ return status;
167
+ }
168
+ throw err;
169
+ }
170
+ })();
171
+
172
+ return { op: op.name, runId, result: () => settled };
173
+ },
174
+
175
+ async status(op: string): Promise<OpRunStatus | undefined> {
176
+ const newest = (await ledgerFor(op)).at(-1);
177
+ if (newest) return statusFromRecord(newest);
178
+ const history = runs.get(op);
179
+ return history?.[history.length - 1];
180
+ },
181
+
182
+ async log(op: string, logOpts?: { limit?: number }): Promise<OpRunRecord[]> {
183
+ const history = (await ledgerFor(op)).reverse();
184
+ return logOpts?.limit === undefined ? history : history.slice(0, logOpts.limit);
185
+ },
186
+
187
+ async list(ops: OpConfig[]): Promise<Map<string, OpRunStatus | undefined>> {
188
+ const out = new Map<string, OpRunStatus | undefined>();
189
+ for (const op of ops) {
190
+ const newest = (await ledgerFor(op.name, noteEnv(op))).at(-1);
191
+ if (newest) {
192
+ out.set(op.name, statusFromRecord(newest));
193
+ continue;
194
+ }
195
+ const history = runs.get(op.name);
196
+ out.set(op.name, history?.[history.length - 1]);
197
+ }
198
+ return out;
199
+ },
200
+
201
+ async cancel(op: string): Promise<void> {
202
+ throw new Error(
203
+ `the local runtime runs "${op}" in the foreground — there is no detached run to cancel. ` +
204
+ `Press Ctrl-C in the terminal running it, or pass --on <lexicon> for a hosted run.`,
205
+ );
206
+ },
207
+
208
+ runComponents(path, selector, options) {
209
+ return runComponents(path, selector, options);
210
+ },
211
+ };
212
+ }
@@ -5,14 +5,16 @@
5
5
  * An Op's steps run in a fixed sequence chant already knows: phases in
6
6
  * order, and (within a non-parallel phase) steps in order. Today the only
7
7
  * way a value escapes a step is `outcomeAttribute`, which stringifies it
8
- * into a Temporal search attribute — a UI filter, not something a later
9
- * step can consume. `StepOutputRef` is the mechanism that lets a later
8
+ * into a named run outcome — something to read a run back by, not something a
9
+ * later step can consume. `StepOutputRef` is the mechanism that lets a later
10
10
  * step's `args` hold a *reference* to an earlier step's declared return
11
11
  * value instead.
12
12
  *
13
13
  * Deliberately a reference, not an expression: `diff.out.driftedStacks` is
14
- * a value placeholder the build resolves and the serializer compiles into a
15
- * real local variable in the generated workflow — never `diff.out.count >
14
+ * a value placeholder that stays inert in the Op's data until the executor
15
+ * substitutes the producing step's recorded result for it, just before the
16
+ * consuming activity is called (`../op/local-executor.ts`'s
17
+ * `resolveStepOutputRefs` over `resultsById`) — never `diff.out.count >
16
18
  * 0` or a `.map()` over a reference. That property (an Op is data you can
17
19
  * read and know what it does, not a program) is exactly what makes it safe
18
20
  * to add this without Ops becoming programs; see the issue's "line not to
@@ -42,10 +44,10 @@
42
44
  * Cross-contract type compatibility (chant #1950 pre-merge review, finding
43
45
  * 3): `validateStepOutputRefs` checks the producer side (a registered
44
46
  * contract with a `returns` schema, and — when `path` is set — that the path
45
- * resolves on it) and, separately, `validateActivitySteps`/TMP012 checks a
47
+ * resolves on it) and, separately, `validateActivitySteps`/OPS012 checks a
46
48
  * step's `args` against its own contract's `args` schema — but a
47
49
  * {@link StepOutputRef} sitting in `args` is a placeholder object at build
48
- * time, not the value it resolves to, so TMP012 skips it (see
50
+ * time, not the value it resolves to, so OPS012 skips it (see
49
51
  * `activity-contract.ts`'s `isStepOutputRefValue` guard) rather than
50
52
  * false-positive on it. Nothing before this compared the *consumer's*
51
53
  * declared type at that position against the *producer's* declared type at
@@ -93,8 +95,8 @@ const STEP_OUTPUT_REF_BRAND = Symbol.for("chant.op.stepOutputRef");
93
95
  * A typed reference to a prior step's declared return value. Inert by
94
96
  * construction — it carries a producer step id and an optional dot-path
95
97
  * into that producer's return schema, resolved by `chant build`
96
- * (`validateStepOutputRefs`) and compiled by the temporal serializer into a
97
- * local variable holding the awaited activity result.
98
+ * (`validateStepOutputRefs`) and compiled by a hosting lexicon's serializer
99
+ * into a local variable holding the awaited activity result.
98
100
  */
99
101
  export interface StepOutputRef {
100
102
  readonly [STEP_OUTPUT_REF_BRAND]: true;
@@ -268,11 +270,11 @@ function indexById(locations: StepLocation[]): { byId: Map<string, StepLocation>
268
270
  * validateStepOutputRefs}'s checks that don't depend on a contract map, kept
269
271
  * as its own export so a caller with no contracts on hand (or that wants to
270
272
  * defend against exactly this class of bug regardless of what contracts are
271
- * registered) can still refuse a scope-invalid reference. The temporal
272
- * lexicon's serializer (`serializeOps`) is exactly this caller: TMP013 (which
273
- * calls the fuller {@link validateStepOutputRefs}) protects `chant build`,
274
- * but `serializeOps` is a public export a caller can invoke directly,
275
- * bypassing that lint pass — this is its own defense-in-depth.
273
+ * registered) can still refuse a scope-invalid reference. A hosting lexicon's
274
+ * own Op serializer is exactly this caller: OPS013 (which calls the fuller
275
+ * {@link validateStepOutputRefs}) protects `chant build`, but a serializer is
276
+ * a public export a caller can invoke directly, bypassing that lint pass —
277
+ * this is its own defense-in-depth.
276
278
  *
277
279
  * Flags:
278
280
  * - a reference authored inside `onFailure`, or inside an `EffectStep`'s
package/src/op/types.ts CHANGED
@@ -1,33 +1,66 @@
1
1
  /**
2
- * Op type definitions — the data model for a named, phased Temporal workflow.
2
+ * Op type definitions — the data model for a named, phased Op.
3
3
  *
4
- * These types are intentionally free of Temporal SDK imports so they can live
5
- * in core without pulling in @temporalio/* as a dependency.
4
+ * These types are intentionally free of any runtime SDK's imports, so they can
5
+ * live in core without core depending on a runtime.
6
6
  */
7
7
 
8
8
  import type { EffectReceiptRef } from "./receipt-store";
9
+ import type { ActivityProfileName } from "./activity-profiles";
9
10
 
10
11
  export interface OpConfig {
11
- /** Kebab-case identifier. Used as the workflow function name (camelCase) and output directory name. */
12
+ /** Kebab-case identifier. Names the Op's output directory (`dist/ops/<name>/`), and is the name `chant run <name>` and another Op's `depends` refer to. */
12
13
  name: string;
13
14
  /** Human-readable description shown in `chant run list` and deployment reports. */
14
15
  overview: string;
15
- /** Temporal task queue. Defaults to `name`. */
16
- taskQueue?: string;
17
- /** Temporal namespace. Defaults to chant.config.ts defaultProfile's namespace. */
18
- namespace?: string;
19
16
  /** Ordered list of execution phases. */
20
17
  phases: PhaseDefinition[];
21
18
  /** Other Op names that must be complete before this Op can run. */
22
19
  depends?: string[];
23
20
  /** Compensation phases executed on terminal failure (run in reverse order). */
24
21
  onFailure?: PhaseDefinition[];
25
- /** Search attributes to upsert at workflow start. */
26
- searchAttributes?: Record<string, string>;
22
+ /**
23
+ * Discovery keys for this Op — free-form `name: value` pairs a reader
24
+ * filters on. `ConvergeOp` sets `Converge: "true"` and `Env`, `WatchOp`
25
+ * sets `Watch`, and `discoverConvergeOps` (`./operator.ts`) reads both;
26
+ * `chant run list` prints whatever is here.
27
+ *
28
+ * These are the discovery half of what `searchAttributes` used to carry
29
+ * (#2118). The other half — a run's own outcome (`Phase`, `Drift`,
30
+ * `Approver`, `RollbackFailed`) — is not a property of the declaration at
31
+ * all and now lands on the run ledger as a fact
32
+ * (`../lifecycle/run-ledger.ts`), written per run rather than declared once.
33
+ */
34
+ labels?: Record<string, string>;
35
+ /**
36
+ * The cadence this Op runs on, when it has one (#2120). Runtime-neutral
37
+ * data, not a scheduler: the github/gitlab/forgejo lexicons render it as a
38
+ * CI cron ({@link ScheduledOpSpec}), `chant operator` reads it as this Op's
39
+ * tick cadence, a hosting lexicon hands it to its own scheduler, and the
40
+ * local one-shot executor ignores it.
41
+ */
42
+ schedule?: OpSchedule;
43
+ }
44
+
45
+ /**
46
+ * An Op's cadence (#2120). The cron is validated at `Op()` construction by
47
+ * the permissive 5-/6-field parser in `./cron.ts`, the same one a lexicon's
48
+ * own post-synth cron check imports.
49
+ */
50
+ export interface OpSchedule {
51
+ /** 5- or 6-field cron expression, read in the running host's local time. */
52
+ cron: string;
53
+ /**
54
+ * What a fire does while the previous run is still going. `"skip"` is the
55
+ * only value — and the default — because that is what a level-triggered
56
+ * tick wants: the next fire re-observes everything anyway, so queueing a
57
+ * backlog buys nothing a single later tick does not.
58
+ */
59
+ overlap?: "skip";
27
60
  }
28
61
 
29
62
  export interface PhaseDefinition {
30
- /** Display name shown in progress output and Temporal UI. */
63
+ /** Display name shown in progress output. */
31
64
  name: string;
32
65
  /** Ordered steps within the phase. */
33
66
  steps: StepDefinition[];
@@ -61,23 +94,50 @@ export interface ActivityStep {
61
94
  */
62
95
  args?: Record<string, unknown>;
63
96
  /**
64
- * Key from TEMPORAL_ACTIVITY_PROFILES controlling timeout + retry.
97
+ * Key from {@link ACTIVITY_PROFILES} controlling timeout + retry.
65
98
  * Default: "fastIdempotent"
66
99
  */
67
- profile?: "fastIdempotent" | "longInfra" | "k8sWait" | "humanGate" | "argoSync" | "policyCheck";
100
+ profile?: ActivityProfileName;
68
101
  /**
69
- * Surface this activity's return value as a workflow search attribute.
102
+ * Surface this activity's return value as a named run outcome.
103
+ *
104
+ * The local executor captures it into the step's record and folds it into
105
+ * the run ledger's `outcomes` (`../lifecycle/run-ledger.ts`); a hosting
106
+ * lexicon's serializer may additionally publish it to whatever index that
107
+ * runtime queries by. Useful for reading back a run by outcome (e.g. `Drift:
108
+ * "true"/"false"` from a lifecycleDiff activity).
70
109
  *
71
- * The serializer captures the awaited result into a temporary, then emits
72
- * `upsertSearchAttributes({ <name>: [String(<from-path>)] })` immediately
73
- * after. Useful for filtering runs by outcome (e.g. `Drift: "true"/"false"`
74
- * from a lifecycleDiff activity).
110
+ * An array publishes several attributes off the same result in one upsert
111
+ * (#2105): one activity can answer more than one question about a run, and
112
+ * `choudoufuLivePlan`'s drift boolean plus its unowned and adoptable counts
113
+ * are three attributes over a single live read that nothing would be gained
114
+ * by splitting into three steps. A single object is the same thing with one
115
+ * entry, and stays the authored form everywhere one attribute is enough.
75
116
  *
76
117
  * `from` is a dot-path into the return value (e.g. `"drifted"` for
77
118
  * `{ drifted: boolean }`); when omitted, the whole return value is
78
- * stringified.
119
+ * recorded.
79
120
  */
80
- outcomeAttribute?: { name: string; from?: string };
121
+ outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[];
122
+ }
123
+
124
+ /** One named run outcome published off a step's return value. */
125
+ export interface OutcomeAttribute {
126
+ /** The outcome's name, as it appears in the run ledger's `outcomes`. */
127
+ name: string;
128
+ /** Dot-path into the activity's return value; the whole value when omitted. */
129
+ from?: string;
130
+ }
131
+
132
+ /**
133
+ * {@link ActivityStep.outcomeAttribute} as a list, whichever form it was
134
+ * authored in. `[]` when the step publishes none, so every consumer can
135
+ * iterate without first asking which of the two shapes it is holding.
136
+ */
137
+ export function outcomeAttributesOf(step: { outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[] }): OutcomeAttribute[] {
138
+ const declared = step.outcomeAttribute;
139
+ if (!declared) return [];
140
+ return Array.isArray(declared) ? declared : [declared];
81
141
  }
82
142
 
83
143
  /**
@@ -102,19 +162,19 @@ export interface EffectStep {
102
162
  expectation?: string;
103
163
  /**
104
164
  * Steps run when the live receipt does not match, in authored order. A gate
105
- * authored here pauses only when the effect will fire. Effect steps do not
165
+ * authored here is reached only when the effect will fire. Effect steps do not
106
166
  * nest.
107
167
  */
108
168
  steps: Array<ActivityStep | GateStep>;
109
- /** Annotation carried into the generated workflow as a comment. */
169
+ /** Annotation carried into the Op's build output as a comment. */
110
170
  description?: string;
111
171
  }
112
172
 
113
173
  export interface GateStep {
114
174
  kind: "gate";
115
- /** Signal name. The generated workflow waits for this signal before continuing. */
175
+ /** The gate's name — what `chant approve <op> <gate>` resolves. */
116
176
  signalName: string;
117
- /** Temporal duration string. Default: "48h". */
177
+ /** How long a recorded pending gate stays valid, as a duration string. Default: "48h". */
118
178
  timeout?: string;
119
179
  /** Human-readable description of the action required to unblock this gate. */
120
180
  description?: string;
package/src/ownership.ts CHANGED
@@ -44,7 +44,7 @@ export interface ChannelKeys {
44
44
  /**
45
45
  * The label-based ownership convention (`app.kubernetes.io/managed-by` +
46
46
  * `chant.intentius.io/{stack,env}`) — the default, shared by every label-based
47
- * lexicon (k8s, gcp, helm, and the Temporal apply activity's `kubectl --prune`
47
+ * lexicon (k8s, gcp, helm, and the `k8sApply` activity's `kubectl --prune`
48
48
  * selector). AWS and Azure tag keys are defined in their own lexicons.
49
49
  */
50
50
  export const LABEL_OWNERSHIP_KEYS: ChannelKeys = {
@@ -155,6 +155,12 @@ describe("describePathOrigin", () => {
155
155
  "composite WebService (web)",
156
156
  );
157
157
  expect(describePathOrigin({ kind: "build-param", params: ["region", "tier"] })).toBe("param region, tier");
158
+ expect(
159
+ describePathOrigin({ kind: "composite-parameter", composite: "WebService", parameters: ["name", "tier"] }),
160
+ ).toBe("composite WebService parameter name, tier");
161
+ expect(describePathOrigin({ kind: "composite-literal", composite: "WebService" })).toBe(
162
+ "composite WebService literal",
163
+ );
158
164
  });
159
165
  });
160
166