@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
@@ -1,56 +1,94 @@
1
+ /**
2
+ * MCP tools over Ops — on the runtime seam (#2121), not on any one runtime's
3
+ * own client.
4
+ *
5
+ * Every tool here goes through an {@link OpRuntimeProvider} — the built-in
6
+ * `local` one by default, or the `runtime` argument's lexicon `opRuntime` when
7
+ * an agent names one. One provider is built per call, so a long-lived server
8
+ * picks up a project's config as it is now rather than as it was at boot; the
9
+ * local provider's in-process run history is the exception and is held for the
10
+ * life of the module, so `op-status` can answer for a run `op-run` started.
11
+ *
12
+ * #2118 owns the ledger-backed record shape; when it lands, `status`/`log`
13
+ * read the ledger and this file stops depending on the process outliving the
14
+ * run.
15
+ */
16
+
1
17
  import { resolve } from "node:path";
2
18
  import { discoverOps } from "../../op/discover";
3
- import { makeTemporalClient } from "../handlers/run";
4
- import { resolveWorkflowId, fetchNormalizedHistory } from "../handlers/run-client";
5
- import { generateReport } from "../handlers/run-report";
6
- import { extractStepRecords, countActivities, queryGateState } from "../handlers/op-progress";
19
+ import { createLocalOpRuntime } from "../../op/runtimes/local";
20
+ import type { OpRuntimeProvider } from "../../op/runtime";
21
+ import { loadChantConfig } from "../../config";
22
+ import { loadPlugins } from "../plugins";
23
+ import { recordGateApproval } from "../handlers/operator";
7
24
  import type { ToolRegistration } from "./lifecycle-tools";
8
25
 
9
- function workflowFnName(opName: string): string {
10
- return opName.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()) + "Workflow";
26
+ /** The `local` provider, shared so an `op-run` is visible to a later `op-status`. */
27
+ let localRuntime: OpRuntimeProvider | undefined;
28
+
29
+ /**
30
+ * Resolve the runtime a tool call addresses. `runtime` names a configured
31
+ * lexicon's `opRuntime`; omitted (or `local`) it is core's built-in provider.
32
+ * Throws with an actionable message — the MCP layer turns that into `isError`.
33
+ */
34
+ async function runtimeFor(name: unknown): Promise<OpRuntimeProvider> {
35
+ const wanted = typeof name === "string" && name.length > 0 ? name : "local";
36
+ if (wanted === "local") {
37
+ localRuntime ??= createLocalOpRuntime({ projectPath: resolve(".") });
38
+ return localRuntime;
39
+ }
40
+
41
+ const configured = await loadChantConfig(resolve("."))
42
+ .then(({ config }) => config.lexicons ?? [])
43
+ .catch(() => [] as string[]);
44
+ if (!configured.includes(wanted)) {
45
+ throw new Error(
46
+ `runtime "${wanted}" is not a configured lexicon` +
47
+ (configured.length > 0 ? ` (configured: ${configured.join(", ")})` : ""),
48
+ );
49
+ }
50
+ const plugin = (await loadPlugins([wanted]))[0];
51
+ if (!plugin?.opRuntime) throw new Error(`lexicon "${wanted}" does not host Op runs`);
52
+ return plugin.opRuntime;
11
53
  }
12
54
 
55
+ const RUNTIME_PARAM = {
56
+ type: "string",
57
+ description: 'Runtime to address: a lexicon name with an opRuntime, or "local" (the default)',
58
+ } as const;
59
+
13
60
  export function createOpListTool(): ToolRegistration {
14
61
  return {
15
62
  definition: {
16
63
  name: "op-list",
17
- description: "List all Op definitions discovered from *.op.ts files with their current run status",
64
+ description: "List all Op definitions discovered from *.op.ts files with their current run state",
18
65
  inputSchema: {
19
66
  type: "object",
20
67
  properties: {
21
- profile: { type: "string", description: "Temporal profile name from chant.config.ts (optional)" },
68
+ runtime: RUNTIME_PARAM,
22
69
  },
23
70
  },
24
71
  },
25
72
  handler: async (params) => {
26
73
  const { ops, errors } = await discoverOps();
27
- const profile = params.profile as string | undefined;
28
74
 
29
- let client: Awaited<ReturnType<typeof makeTemporalClient>>["client"] | undefined;
75
+ let states: Map<string, { state: string } | undefined> = new Map();
30
76
  try {
31
- ({ client } = await makeTemporalClient(profile, resolve(".")));
77
+ const runtime = await runtimeFor(params.runtime);
78
+ states = await runtime.list([...ops.values()].map((d) => d.config));
32
79
  } catch {
33
- // Temporal not available — degrade gracefully
80
+ // Runtime unavailable — the definitions are still worth listing.
34
81
  }
35
82
 
36
83
  const result = [];
37
84
  for (const [name, { config }] of ops) {
38
- let runStatus = "—";
39
- if (client) {
40
- try {
41
- const desc = await client.workflow.getHandle(resolveWorkflowId(name)).describe();
42
- runStatus = desc.status.name;
43
- } catch {
44
- // workflow not found or Temporal error
45
- }
46
- }
47
85
  result.push({
48
86
  name,
49
87
  overview: config.overview,
50
88
  phases: config.phases.length,
51
- taskQueue: config.taskQueue ?? config.name,
89
+ labels: config.labels ?? {},
52
90
  depends: config.depends ?? [],
53
- runStatus,
91
+ runState: states.get(name)?.state ?? "—",
54
92
  });
55
93
  }
56
94
 
@@ -64,19 +102,18 @@ export function createOpRunTool(): ToolRegistration {
64
102
  definition: {
65
103
  name: "op-run",
66
104
  description:
67
- "Submit an Op workflow to Temporal (Temporal mode). A Temporal worker must already be running — start it with `chant run <name> --temporal`.",
105
+ "Run an Op on a runtime and return its result. Defaults to the built-in local runtime, which executes the Op in this process.",
68
106
  inputSchema: {
69
107
  type: "object",
70
108
  properties: {
71
109
  name: { type: "string", description: "Op name (e.g. alb-deploy)" },
72
- profile: { type: "string", description: "Temporal profile name from chant.config.ts (optional)" },
110
+ runtime: RUNTIME_PARAM,
73
111
  },
74
112
  required: ["name"],
75
113
  },
76
114
  },
77
115
  handler: async (params) => {
78
116
  const name = params.name as string;
79
- const profile = params.profile as string | undefined;
80
117
 
81
118
  const { ops } = await discoverOps();
82
119
  if (!ops.has(name)) {
@@ -84,18 +121,19 @@ export function createOpRunTool(): ToolRegistration {
84
121
  return `Op "${name}" not found. Available: ${available.join(", ") || "none"}`;
85
122
  }
86
123
 
87
- const { config } = ops.get(name)!;
88
- const { client, profile: resolvedProfile } = await makeTemporalClient(profile, resolve("."));
89
- const workflowId = resolveWorkflowId(name);
90
- const taskQueue = resolvedProfile.taskQueue ?? config.taskQueue ?? name;
91
-
92
- await client.workflow.start(workflowFnName(name), {
93
- taskQueue,
94
- workflowId,
95
- workflowIdConflictPolicy: "FAIL",
96
- });
124
+ const runtime = await runtimeFor(params.runtime);
125
+ const handle = await runtime.start(ops.get(name)!.config, {});
126
+ const status = await handle.result();
97
127
 
98
- return { workflowId, message: `Workflow "${workflowId}" submitted to task queue "${taskQueue}"` };
128
+ return {
129
+ op: status.op,
130
+ runId: status.runId,
131
+ state: status.state,
132
+ startedAt: status.startedAt,
133
+ endedAt: status.endedAt ?? null,
134
+ ...(status.records ? { records: status.records } : {}),
135
+ ...(status.gate ? { gate: status.gate } : {}),
136
+ };
99
137
  },
100
138
  };
101
139
  }
@@ -104,78 +142,81 @@ export function createOpStatusTool(): ToolRegistration {
104
142
  return {
105
143
  definition: {
106
144
  name: "op-status",
107
- description: "Return the current run state of an Op workflow",
145
+ description: "Return the current run state of an Op on a runtime",
108
146
  inputSchema: {
109
147
  type: "object",
110
148
  properties: {
111
149
  name: { type: "string", description: "Op name (e.g. alb-deploy)" },
112
- profile: { type: "string", description: "Temporal profile name from chant.config.ts (optional)" },
150
+ runtime: RUNTIME_PARAM,
113
151
  },
114
152
  required: ["name"],
115
153
  },
116
154
  },
117
155
  handler: async (params) => {
118
156
  const name = params.name as string;
119
- const profile = params.profile as string | undefined;
120
157
 
121
158
  const { ops } = await discoverOps();
122
- const config = ops.get(name)?.config;
123
-
124
- const { client } = await makeTemporalClient(profile, resolve("."));
125
- const handle = client.workflow.getHandle(resolveWorkflowId(name));
126
- const desc = await handle.describe();
127
- const history = await fetchNormalizedHistory(handle);
128
-
129
- const { completed: activitiesCompleted, scheduled: activitiesScheduled } = countActivities(history);
130
- // Per-phase progress (#1676) — the same StepRecord shape `chant run
131
- // <name> --json` uses locally, so a consumer renders one way
132
- // regardless of executor. Only buildable when the Op's config was
133
- // discoverable (a *.op.ts file on disk); absent otherwise rather than
134
- // guessed at.
135
- const progress = config ? extractStepRecords(config, history, { final: Boolean(desc.closeTime) }) : undefined;
136
- const gate = await queryGateState(handle);
159
+ if (!ops.has(name)) throw new Error(`Op "${name}" not found`);
160
+
161
+ const runtime = await runtimeFor(params.runtime);
162
+ const status = await runtime.status(name);
163
+ if (!status) return { op: name, runtime: runtime.name, state: null, message: "no run recorded" };
137
164
 
138
165
  return {
139
- workflowId: desc.workflowId,
140
- runId: desc.runId,
141
- status: desc.status.name,
142
- startTime: desc.startTime,
143
- closeTime: desc.closeTime ?? null,
144
- taskQueue: desc.taskQueue,
145
- activitiesCompleted,
146
- activitiesScheduled,
147
- ...(progress ? { progress } : {}),
148
- gate: gate ?? null,
166
+ op: status.op,
167
+ runtime: runtime.name,
168
+ runId: status.runId,
169
+ state: status.state,
170
+ startedAt: status.startedAt,
171
+ endedAt: status.endedAt ?? null,
172
+ ...(status.records ? { records: status.records } : {}),
173
+ gate: status.gate ?? null,
149
174
  };
150
175
  },
151
176
  };
152
177
  }
153
178
 
154
- export function createOpSignalTool(): ToolRegistration {
179
+ export function createOpApproveTool(): ToolRegistration {
155
180
  return {
156
181
  definition: {
157
- name: "op-signal",
158
- description: "Send a named signal to an Op workflow (e.g. to unblock a gate step)",
182
+ name: "op-approve",
183
+ description:
184
+ "Record a gate's resolution on the gate ledger and wake the runtime hosting the gated run. The rename of op-signal: a gate is resolved by recording the fact, not by sending a message.",
159
185
  inputSchema: {
160
186
  type: "object",
161
187
  properties: {
162
188
  name: { type: "string", description: "Op name (e.g. alb-deploy)" },
163
- signal: { type: "string", description: "Signal name (e.g. gate-dns-delegation)" },
164
- profile: { type: "string", description: "Temporal profile name from chant.config.ts (optional)" },
189
+ gate: { type: "string", description: "Gate name (e.g. gate-dns-delegation)" },
190
+ approver: { type: "string", description: "Who approved; defaults to the CI or shell identity" },
191
+ note: { type: "string", description: "Free-text context recorded on the resolution" },
192
+ url: { type: "string", description: "Absolute http/https URL this resolution happened at" },
193
+ runtime: RUNTIME_PARAM,
165
194
  },
166
- required: ["name", "signal"],
195
+ required: ["name", "gate"],
167
196
  },
168
197
  },
169
198
  handler: async (params) => {
170
199
  const name = params.name as string;
171
- const signal = params.signal as string;
172
- const profile = params.profile as string | undefined;
200
+ const gate = params.gate as string;
201
+ if (!name || !gate) throw new Error("op-approve needs both an Op name and a gate name");
173
202
 
174
- const { client } = await makeTemporalClient(profile, resolve("."));
175
- const handle = client.workflow.getHandle(resolveWorkflowId(name));
176
- await handle.signal(signal);
203
+ const runtime = await runtimeFor(params.runtime);
204
+ const outcome = await recordGateApproval(name, gate, {
205
+ actor: params.approver as string | undefined,
206
+ note: params.note as string | undefined,
207
+ url: params.url as string | undefined,
208
+ });
209
+ if (!outcome.ok) throw new Error(`Gate "${gate}" on "${name}" was not recorded`);
210
+
211
+ if (runtime.resolveGate) await runtime.resolveGate(name, gate, outcome.record);
177
212
 
178
- return `Signal "${signal}" sent to Op "${name}"`;
213
+ return {
214
+ op: name,
215
+ gate,
216
+ resolvedBy: outcome.record.resolvedBy,
217
+ timestamp: outcome.record.timestamp,
218
+ runtimeNotified: Boolean(runtime.resolveGate),
219
+ };
179
220
  },
180
221
  };
181
222
  }
@@ -184,32 +225,50 @@ export function createOpReportTool(): ToolRegistration {
184
225
  return {
185
226
  definition: {
186
227
  name: "op-report",
187
- description: "Return a markdown deployment report for the latest run of an Op",
228
+ description: "Return a markdown report for the latest run of an Op on a runtime",
188
229
  inputSchema: {
189
230
  type: "object",
190
231
  properties: {
191
232
  name: { type: "string", description: "Op name (e.g. alb-deploy)" },
192
- profile: { type: "string", description: "Temporal profile name from chant.config.ts (optional)" },
233
+ runtime: RUNTIME_PARAM,
193
234
  },
194
235
  required: ["name"],
195
236
  },
196
237
  },
197
238
  handler: async (params) => {
198
239
  const name = params.name as string;
199
- const profile = params.profile as string | undefined;
200
240
 
201
241
  const { ops } = await discoverOps();
202
- if (!ops.has(name)) {
203
- return `Op "${name}" not found`;
204
- }
242
+ if (!ops.has(name)) return `Op "${name}" not found`;
205
243
  const { config } = ops.get(name)!;
206
244
 
207
- const { client } = await makeTemporalClient(profile, resolve("."));
208
- const handle = client.workflow.getHandle(resolveWorkflowId(name));
209
- const desc = await handle.describe();
210
- const history = await fetchNormalizedHistory(handle);
245
+ const runtime = await runtimeFor(params.runtime);
246
+ const status = await runtime.status(name);
247
+ if (!status) return `# ${name}\n\n${config.overview}\n\nNo run is recorded on the "${runtime.name}" runtime.\n`;
248
+
249
+ const lines = [
250
+ `# ${name}`,
251
+ "",
252
+ config.overview,
253
+ "",
254
+ `- Runtime: ${runtime.name}`,
255
+ `- Run: ${status.runId}`,
256
+ `- State: ${status.state}`,
257
+ `- Started: ${status.startedAt}`,
258
+ ...(status.endedAt ? [`- Ended: ${status.endedAt}`] : []),
259
+ ...(status.gate ? [`- Gate: ${status.gate.name} (pending since ${status.gate.since})`] : []),
260
+ "",
261
+ ];
262
+
263
+ if (status.records?.length) {
264
+ lines.push("| Phase | Step | Status | Duration |", "|---|---|---|---|");
265
+ for (const record of status.records) {
266
+ lines.push(`| ${record.phase} | ${record.fn} | ${record.status} | ${record.durationMs}ms |`);
267
+ }
268
+ lines.push("");
269
+ }
211
270
 
212
- return generateReport(name, config, desc, history);
271
+ return lines.join("\n");
213
272
  },
214
273
  };
215
274
  }
@@ -4,9 +4,7 @@ import type { ResourceDefinition } from "./types";
4
4
  import { getContext } from "./resources/context";
5
5
  import { readSnapshot, readEnvironmentSnapshots } from "../../lifecycle/git";
6
6
  import { discoverOps } from "../../op/discover";
7
- import { makeTemporalClient } from "../handlers/run";
8
- import { resolveWorkflowId, fetchNormalizedHistory } from "../handlers/run-client";
9
- import { extractStepRecords, countActivities, queryGateState } from "../handlers/op-progress";
7
+ import { createLocalOpRuntime } from "../../op/runtimes/local";
10
8
  import { loadOkfBundle } from "../../okf-read";
11
9
  import { loadChantConfigUpward, resolveKnowledgeDir } from "../../config";
12
10
 
@@ -37,7 +35,7 @@ export const coreResourceDefinitions: ResourceDefinition[] = [
37
35
  {
38
36
  uri: "chant://ops/{name}/runs",
39
37
  name: "Op run history",
40
- description: "Workflow run history for a named Op",
38
+ description: "Run history for a named Op, newest first",
41
39
  mimeType: "application/json",
42
40
  },
43
41
  {
@@ -95,10 +93,6 @@ export function collectExamples(
95
93
  return examples;
96
94
  }
97
95
 
98
- function opWorkflowFnName(opName: string): string {
99
- return opName.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()) + "Workflow";
100
- }
101
-
102
96
  /**
103
97
  * Handle resources/read request — checks plugin resources after core
104
98
  */
@@ -167,7 +161,7 @@ export async function handleResourcesRead(
167
161
  name: config.name,
168
162
  overview: config.overview,
169
163
  phases: config.phases.length,
170
- taskQueue: config.taskQueue ?? config.name,
164
+ labels: config.labels ?? {},
171
165
  depends: config.depends ?? [],
172
166
  }));
173
167
  return {
@@ -175,33 +169,16 @@ export async function handleResourcesRead(
175
169
  };
176
170
  }
177
171
 
172
+ // Both run resources read the built-in local runtime (#2121, #2116) — the
173
+ // one an MCP client can address without naming a lexicon. `status` and `log`
174
+ // answer from the run ledger (#2118), so a run that ended in an earlier
175
+ // process still reads back here.
178
176
  if (uri.startsWith("chant://ops/") && uri.endsWith("/runs/latest")) {
179
177
  const name = uri.replace("chant://ops/", "").replace("/runs/latest", "");
180
178
  try {
181
- const { ops } = await discoverOps();
182
- const config = ops.get(name)?.config;
183
-
184
- const { client } = await makeTemporalClient(undefined, resolve("."));
185
- const handle = client.workflow.getHandle(resolveWorkflowId(name));
186
- const desc = await handle.describe();
187
- const history = await fetchNormalizedHistory(handle);
188
- const { completed: activitiesCompleted, scheduled: activitiesScheduled } = countActivities(history);
189
- const progress = config ? extractStepRecords(config, history, { final: Boolean(desc.closeTime) }) : undefined;
190
- const gate = await queryGateState(handle);
191
- const result = {
192
- workflowId: desc.workflowId,
193
- runId: desc.runId,
194
- status: desc.status.name,
195
- startTime: desc.startTime,
196
- closeTime: desc.closeTime ?? null,
197
- taskQueue: desc.taskQueue,
198
- activitiesCompleted,
199
- activitiesScheduled,
200
- ...(progress ? { progress } : {}),
201
- gate: gate ?? null,
202
- };
179
+ const status = await createLocalOpRuntime({ projectPath: resolve(".") }).status(name);
203
180
  return {
204
- contents: [{ uri, mimeType: "application/json", text: JSON.stringify(result, null, 2) }],
181
+ contents: [{ uri, mimeType: "application/json", text: JSON.stringify(status ?? null, null, 2) }],
205
182
  };
206
183
  } catch (err) {
207
184
  return {
@@ -213,11 +190,7 @@ export async function handleResourcesRead(
213
190
  if (uri.startsWith("chant://ops/") && uri.endsWith("/runs")) {
214
191
  const name = uri.replace("chant://ops/", "").replace("/runs", "");
215
192
  try {
216
- const { client } = await makeTemporalClient(undefined, resolve("."));
217
- const runs: unknown[] = [];
218
- for await (const run of client.workflow.list({ query: `WorkflowType = "${opWorkflowFnName(name)}"` })) {
219
- runs.push({ runId: run.runId, status: run.status.name, startTime: run.startTime, closeTime: run.closeTime ?? null });
220
- }
193
+ const runs = await createLocalOpRuntime({ projectPath: resolve(".") }).log(name);
221
194
  return {
222
195
  contents: [{ uri, mimeType: "application/json", text: JSON.stringify(runs, null, 2) }],
223
196
  };
@@ -49,32 +49,31 @@ chant import template.json # Convert external template
49
49
  chant import template.json -o ./src/ # Custom output dir
50
50
  \`\`\`
51
51
 
52
- ## Ops (Temporal Workflows)
52
+ ## Ops
53
53
 
54
- Ops are durable workflow definitions backed by Temporal. Each \`*.op.ts\` file declares an Op with named phases and activity steps.
54
+ An Op is a convergent verb. Each \`*.op.ts\` file declares one with named phases and activity steps; \`--on <lexicon>\` picks the runtime that hosts the run, and the built-in local runtime runs it in-process otherwise.
55
55
 
56
56
  ### Op MCP Tools
57
57
 
58
58
  | Tool | Description |
59
59
  |---|---|
60
- | \`op-list\` | List all discovered Ops with current run status. Optional \`profile\` param. |
61
- | \`op-run\` | Submit an Op workflow. Requires \`name\`. Worker must already be running via \`chant run <name>\`. |
62
- | \`op-status\` | Get current run state (status, activity counts, times). Requires \`name\`. |
63
- | \`op-signal\` | Send a signal to unblock a gate step. Requires \`name\` and \`signal\`. |
64
- | \`op-report\` | Return a markdown deployment report for the latest run. Requires \`name\`. |
60
+ | \`op-list\` | List all discovered Ops with their current run state. |
61
+ | \`op-run\` | Run an Op and return its result. Requires \`name\`. |
62
+ | \`op-status\` | Get current run state (state, step records, times). Requires \`name\`. |
63
+ | \`op-approve\` | Record a gate's resolution and wake the runtime hosting the run. Requires \`name\` and \`gate\`. |
64
+ | \`op-report\` | Return a markdown report for the latest run. Requires \`name\`. |
65
65
 
66
- All Op tools accept an optional \`profile\` parameter matching a profile name in \`chant.config.ts\` \`temporal.profiles\`.
66
+ All Op tools accept an optional \`runtime\` parameter: a lexicon name whose \`opRuntime\` hosts the run, or \`local\` (the default) for the built-in in-process runtime.
67
67
 
68
68
  ### Op MCP Resources
69
69
 
70
70
  | URI | Description |
71
71
  |---|---|
72
- | \`chant://ops\` | JSON array of all Op definitions (name, overview, phases, taskQueue, depends) |
73
- | \`chant://ops/{name}/runs\` | Workflow run history for a named Op |
72
+ | \`chant://ops\` | JSON array of all Op definitions (name, overview, phase count, labels, depends) |
73
+ | \`chant://ops/{name}/runs\` | Run ledger history for a named Op, newest first |
74
74
  | \`chant://ops/{name}/runs/latest\` | Latest run state for a named Op |
75
75
 
76
- ### Workflow IDs
77
- Ops use deterministic workflow IDs: \`chant-op-<opName>\` (e.g. \`chant-op-alb-deploy\`).
76
+ Both run resources read the built-in local runtime, the one an MCP client can address without naming a lexicon.
78
77
 
79
78
  ## Best Practices
80
79
 
@@ -467,50 +467,50 @@ describe("McpServer", () => {
467
467
  return tool.inputSchema.properties as Record<string, unknown>;
468
468
  }
469
469
 
470
- test("op-list has profile property", async () => {
470
+ test("op-list has a runtime property", async () => {
471
471
  const props = await getToolProps("op-list");
472
- expect(props.profile).toBeDefined();
472
+ expect(props.runtime).toBeDefined();
473
473
  });
474
474
 
475
- test("op-run has name (required) and profile", async () => {
475
+ test("op-run has name (required) and runtime", async () => {
476
476
  const response = await server.handleRequest({ jsonrpc: "2.0", id: 1, method: "tools/list" });
477
477
  const result = response.result as { tools: Array<{ name: string; inputSchema: Record<string, unknown> }> };
478
478
  const tool = result.tools.find((t) => t.name === "op-run")!;
479
479
  const props = tool.inputSchema.properties as Record<string, unknown>;
480
480
  expect(props.name).toBeDefined();
481
- expect(props.profile).toBeDefined();
481
+ expect(props.runtime).toBeDefined();
482
482
  expect(tool.inputSchema.required).toContain("name");
483
483
  });
484
484
 
485
- test("op-status has name (required) and profile", async () => {
485
+ test("op-status has name (required) and runtime", async () => {
486
486
  const response = await server.handleRequest({ jsonrpc: "2.0", id: 1, method: "tools/list" });
487
487
  const result = response.result as { tools: Array<{ name: string; inputSchema: Record<string, unknown> }> };
488
488
  const tool = result.tools.find((t) => t.name === "op-status")!;
489
489
  const props = tool.inputSchema.properties as Record<string, unknown>;
490
490
  expect(props.name).toBeDefined();
491
- expect(props.profile).toBeDefined();
491
+ expect(props.runtime).toBeDefined();
492
492
  expect(tool.inputSchema.required).toContain("name");
493
493
  });
494
494
 
495
- test("op-signal has name and signal (both required) and profile", async () => {
495
+ test("op-approve has name and gate (both required), plus runtime (#2121)", async () => {
496
496
  const response = await server.handleRequest({ jsonrpc: "2.0", id: 1, method: "tools/list" });
497
497
  const result = response.result as { tools: Array<{ name: string; inputSchema: Record<string, unknown> }> };
498
- const tool = result.tools.find((t) => t.name === "op-signal")!;
498
+ const tool = result.tools.find((t) => t.name === "op-approve")!;
499
499
  const props = tool.inputSchema.properties as Record<string, unknown>;
500
500
  expect(props.name).toBeDefined();
501
- expect(props.signal).toBeDefined();
502
- expect(props.profile).toBeDefined();
501
+ expect(props.gate).toBeDefined();
502
+ expect(props.runtime).toBeDefined();
503
503
  expect(tool.inputSchema.required).toContain("name");
504
- expect(tool.inputSchema.required).toContain("signal");
504
+ expect(tool.inputSchema.required).toContain("gate");
505
505
  });
506
506
 
507
- test("op-report has name (required) and profile", async () => {
507
+ test("op-report has name (required) and runtime", async () => {
508
508
  const response = await server.handleRequest({ jsonrpc: "2.0", id: 1, method: "tools/list" });
509
509
  const result = response.result as { tools: Array<{ name: string; inputSchema: Record<string, unknown> }> };
510
510
  const tool = result.tools.find((t) => t.name === "op-report")!;
511
511
  const props = tool.inputSchema.properties as Record<string, unknown>;
512
512
  expect(props.name).toBeDefined();
513
- expect(props.profile).toBeDefined();
513
+ expect(props.runtime).toBeDefined();
514
514
  expect(tool.inputSchema.required).toContain("name");
515
515
  });
516
516
  });
@@ -640,7 +640,7 @@ describe("McpServer", () => {
640
640
  });
641
641
 
642
642
  describe("Op tool handlers", () => {
643
- test("op-list returns list without throwing when Temporal unavailable", async () => {
643
+ test("op-list returns list without throwing when no runtime has a record", async () => {
644
644
  const response = await server.handleRequest({
645
645
  jsonrpc: "2.0",
646
646
  id: 1,
@@ -654,7 +654,7 @@ describe("McpServer", () => {
654
654
  expect(result.isError).toBeUndefined();
655
655
  });
656
656
 
657
- test("op-run returns isError when Temporal unavailable", async () => {
657
+ test("op-run answers for an Op that does not exist", async () => {
658
658
  const response = await server.handleRequest({
659
659
  jsonrpc: "2.0",
660
660
  id: 1,
@@ -663,11 +663,11 @@ describe("McpServer", () => {
663
663
  });
664
664
  expect(response.error).toBeUndefined();
665
665
  const result = response.result as { content: Array<{ text: string }>; isError?: boolean };
666
- // Either "not found" or Temporal error — either way should not be a protocol error
666
+ // Either "not found" or a runtime error — either way, not a protocol error
667
667
  expect(result.content[0].text.length).toBeGreaterThan(0);
668
668
  });
669
669
 
670
- test("op-status returns isError when Temporal unavailable", async () => {
670
+ test("op-status returns isError for an Op that does not exist", async () => {
671
671
  const response = await server.handleRequest({
672
672
  jsonrpc: "2.0",
673
673
  id: 1,
@@ -680,12 +680,12 @@ describe("McpServer", () => {
680
680
  expect(result.content[0].text).toContain("Error:");
681
681
  });
682
682
 
683
- test("op-signal returns isError when Temporal unavailable", async () => {
683
+ test("op-approve returns isError without a gate name (#2121)", async () => {
684
684
  const response = await server.handleRequest({
685
685
  jsonrpc: "2.0",
686
686
  id: 1,
687
687
  method: "tools/call",
688
- params: { name: "op-signal", arguments: { name: "nonexistent-op", signal: "gate" } },
688
+ params: { name: "op-approve", arguments: { name: "nonexistent-op" } },
689
689
  });
690
690
  expect(response.error).toBeUndefined();
691
691
  const result = response.result as { content: Array<{ text: string }>; isError: boolean };
@@ -702,7 +702,7 @@ describe("McpServer", () => {
702
702
  });
703
703
  expect(response.error).toBeUndefined();
704
704
  const result = response.result as { content: Array<{ text: string }>; isError?: boolean };
705
- // Op not found → returns a "not found" message or Temporal error, not a protocol error
705
+ // Op not found → returns a "not found" message or a runtime error, not a protocol error
706
706
  expect(result.content[0].text.length).toBeGreaterThan(0);
707
707
  });
708
708
  });
@@ -973,7 +973,7 @@ describe("McpServer", () => {
973
973
  expect(Array.isArray(ops)).toBe(true);
974
974
  });
975
975
 
976
- test("chant://ops/{name}/runs degrades gracefully when Temporal unavailable", async () => {
976
+ test("chant://ops/{name}/runs is an empty list for an Op with no recorded run", async () => {
977
977
  const response = await server.handleRequest({
978
978
  jsonrpc: "2.0",
979
979
  id: 1,
@@ -982,11 +982,10 @@ describe("McpServer", () => {
982
982
  });
983
983
  expect(response.error).toBeUndefined();
984
984
  const result = response.result as { contents: Array<{ text: string }> };
985
- const data = JSON.parse(result.contents[0].text);
986
- expect(data.error).toBeDefined();
985
+ expect(JSON.parse(result.contents[0].text)).toEqual([]);
987
986
  });
988
987
 
989
- test("chant://ops/{name}/runs/latest degrades gracefully when Temporal unavailable", async () => {
988
+ test("chant://ops/{name}/runs/latest is null for an Op with no recorded run", async () => {
990
989
  const response = await server.handleRequest({
991
990
  jsonrpc: "2.0",
992
991
  id: 1,
@@ -995,8 +994,7 @@ describe("McpServer", () => {
995
994
  });
996
995
  expect(response.error).toBeUndefined();
997
996
  const result = response.result as { contents: Array<{ text: string }> };
998
- const data = JSON.parse(result.contents[0].text);
999
- expect(data.error).toBeDefined();
997
+ expect(JSON.parse(result.contents[0].text)).toBeNull();
1000
998
  });
1001
999
  });
1002
1000
 
@@ -1471,7 +1469,7 @@ describe("McpServer", () => {
1471
1469
  expect(tools).toHaveLength(13);
1472
1470
  expect(tools.map((t) => t.name).sort()).toEqual([
1473
1471
  "build", "explain", "import", "lifecycle-diff", "lifecycle-snapshot", "lint",
1474
- "op-list", "op-report", "op-run", "op-signal", "op-status",
1472
+ "op-approve", "op-list", "op-report", "op-run", "op-status",
1475
1473
  "scaffold", "search",
1476
1474
  ]);
1477
1475