@intentius/chant 0.57.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 (504) 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/init-lexicon/templates/codegen.d.ts +1 -0
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  38. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  40. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  41. package/dist/cli/commands/init.d.ts.map +1 -1
  42. package/dist/cli/commands/lint.d.ts.map +1 -1
  43. package/dist/cli/commands/onboard.d.ts +2 -0
  44. package/dist/cli/commands/onboard.d.ts.map +1 -1
  45. package/dist/cli/handlers/build.d.ts.map +1 -1
  46. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  47. package/dist/cli/handlers/operator.d.ts +82 -16
  48. package/dist/cli/handlers/operator.d.ts.map +1 -1
  49. package/dist/cli/handlers/run.d.ts +49 -42
  50. package/dist/cli/handlers/run.d.ts.map +1 -1
  51. package/dist/cli/main.d.ts +28 -1
  52. package/dist/cli/main.d.ts.map +1 -1
  53. package/dist/cli/mcp/op-tools.d.ts +16 -1
  54. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  55. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  56. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  57. package/dist/cli/registry.d.ts +26 -9
  58. package/dist/cli/registry.d.ts.map +1 -1
  59. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  60. package/dist/components/auto-release.d.ts +10 -20
  61. package/dist/components/auto-release.d.ts.map +1 -1
  62. package/dist/components/capability.d.ts +4 -4
  63. package/dist/components/cli-support.d.ts +20 -21
  64. package/dist/components/cli-support.d.ts.map +1 -1
  65. package/dist/components/component.d.ts +3 -3
  66. package/dist/components/component.d.ts.map +1 -1
  67. package/dist/components/driver-output.d.ts.map +1 -1
  68. package/dist/components/driver.d.ts +66 -36
  69. package/dist/components/driver.d.ts.map +1 -1
  70. package/dist/components/index.d.ts +1 -2
  71. package/dist/components/index.d.ts.map +1 -1
  72. package/dist/components/manifest-persistence.d.ts +1 -9
  73. package/dist/components/manifest-persistence.d.ts.map +1 -1
  74. package/dist/components/run-progress.d.ts +6 -6
  75. package/dist/components/run-progress.d.ts.map +1 -1
  76. package/dist/components/verbs/run-agent.d.ts +9 -15
  77. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  78. package/dist/components/verbs/verify.d.ts +2 -2
  79. package/dist/deep-observation.d.ts +17 -0
  80. package/dist/deep-observation.d.ts.map +1 -1
  81. package/dist/discovery/files.d.ts +4 -4
  82. package/dist/discovery/fold-import.d.ts.map +1 -1
  83. package/dist/discovery/param-deps.d.ts +33 -0
  84. package/dist/discovery/param-deps.d.ts.map +1 -1
  85. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  86. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  87. package/dist/fold/foldable-helpers.d.ts +5 -1
  88. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  89. package/dist/fold-provenance.d.ts +236 -0
  90. package/dist/fold-provenance.d.ts.map +1 -0
  91. package/dist/graph-ops.d.ts +1 -1
  92. package/dist/held-elsewhere.d.ts +85 -0
  93. package/dist/held-elsewhere.d.ts.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/kubectl-context.d.ts +3 -3
  97. package/dist/lexicon-config.d.ts +4 -4
  98. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  99. package/dist/lexicon.d.ts +104 -14
  100. package/dist/lexicon.d.ts.map +1 -1
  101. package/dist/lifecycle/change-set.d.ts +13 -0
  102. package/dist/lifecycle/change-set.d.ts.map +1 -1
  103. package/dist/lifecycle/deep-diff.d.ts +133 -6
  104. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  105. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  106. package/dist/lifecycle/gate-ledger.d.ts +71 -3
  107. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  108. package/dist/lifecycle/index.d.ts +1 -0
  109. package/dist/lifecycle/index.d.ts.map +1 -1
  110. package/dist/lifecycle/release-ledger.d.ts +2 -2
  111. package/dist/lifecycle/run-ledger.d.ts +53 -0
  112. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  113. package/dist/lifecycle/symptoms.d.ts +3 -3
  114. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  115. package/dist/lint/config.d.ts +81 -2
  116. package/dist/lint/config.d.ts.map +1 -1
  117. package/dist/lint/post-synth.d.ts +55 -2
  118. package/dist/lint/post-synth.d.ts.map +1 -1
  119. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  120. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  121. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  122. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  123. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  124. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  125. package/dist/lint/rules/comp/index.d.ts +1 -1
  126. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  127. package/dist/lint/rules/op/index.d.ts +16 -0
  128. package/dist/lint/rules/op/index.d.ts.map +1 -0
  129. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  130. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  131. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  132. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  133. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  134. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  135. package/dist/lint/rules/op/support.d.ts +12 -0
  136. package/dist/lint/rules/op/support.d.ts.map +1 -0
  137. package/dist/lint/suppressions.d.ts +108 -0
  138. package/dist/lint/suppressions.d.ts.map +1 -0
  139. package/dist/live-endpoint.d.ts +1 -1
  140. package/dist/op/activities/activity-contracts.d.ts +54 -0
  141. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  142. package/dist/op/activities/apply.d.ts +262 -0
  143. package/dist/op/activities/apply.d.ts.map +1 -0
  144. package/dist/op/activities/build.d.ts +13 -0
  145. package/dist/op/activities/build.d.ts.map +1 -0
  146. package/dist/op/activities/converge.d.ts +110 -0
  147. package/dist/op/activities/converge.d.ts.map +1 -0
  148. package/dist/op/activities/env-teardown.d.ts +76 -0
  149. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  150. package/dist/op/activities/guard-validate.d.ts +64 -0
  151. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  152. package/dist/op/activities/http-check.d.ts +34 -0
  153. package/dist/op/activities/http-check.d.ts.map +1 -0
  154. package/dist/op/activities/index.d.ts +31 -0
  155. package/dist/op/activities/index.d.ts.map +1 -0
  156. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  157. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  158. package/dist/op/activities/lifecycle.d.ts +42 -0
  159. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  160. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  161. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  162. package/dist/op/activities/policy.d.ts +17 -0
  163. package/dist/op/activities/policy.d.ts.map +1 -0
  164. package/dist/op/activities/reconcile.d.ts +89 -0
  165. package/dist/op/activities/reconcile.d.ts.map +1 -0
  166. package/dist/op/activities/shell.d.ts +13 -0
  167. package/dist/op/activities/shell.d.ts.map +1 -0
  168. package/dist/op/activities/teardown.d.ts +10 -0
  169. package/dist/op/activities/teardown.d.ts.map +1 -0
  170. package/dist/op/activities/util.d.ts +7 -0
  171. package/dist/op/activities/util.d.ts.map +1 -0
  172. package/dist/op/activities/wait.d.ts +28 -0
  173. package/dist/op/activities/wait.d.ts.map +1 -0
  174. package/dist/op/activities/workflow-audit.d.ts +92 -0
  175. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  176. package/dist/op/activity-contract-registry.d.ts +76 -0
  177. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  178. package/dist/op/activity-contract.d.ts +25 -18
  179. package/dist/op/activity-contract.d.ts.map +1 -1
  180. package/dist/op/activity-failure.d.ts +28 -0
  181. package/dist/op/activity-failure.d.ts.map +1 -0
  182. package/dist/op/activity-profiles.d.ts +118 -0
  183. package/dist/op/activity-profiles.d.ts.map +1 -0
  184. package/dist/op/activity-registry.d.ts +22 -38
  185. package/dist/op/activity-registry.d.ts.map +1 -1
  186. package/dist/op/activity-runtime.d.ts +3 -14
  187. package/dist/op/activity-runtime.d.ts.map +1 -1
  188. package/dist/op/builders.d.ts +84 -29
  189. package/dist/op/builders.d.ts.map +1 -1
  190. package/dist/op/composites/apply-op.d.ts +113 -0
  191. package/dist/op/composites/apply-op.d.ts.map +1 -0
  192. package/dist/op/composites/converge-op.d.ts +120 -0
  193. package/dist/op/composites/converge-op.d.ts.map +1 -0
  194. package/dist/op/composites/index.d.ts +26 -0
  195. package/dist/op/composites/index.d.ts.map +1 -0
  196. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  197. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  198. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  199. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  200. package/dist/op/composites/reconcile-op.d.ts +57 -0
  201. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  202. package/dist/op/composites/watch-op.d.ts +60 -0
  203. package/dist/op/composites/watch-op.d.ts.map +1 -0
  204. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  205. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  206. package/dist/op/converge-rule.d.ts +12 -10
  207. package/dist/op/converge-rule.d.ts.map +1 -1
  208. package/dist/op/cron.d.ts +51 -0
  209. package/dist/op/cron.d.ts.map +1 -0
  210. package/dist/op/discover.d.ts +9 -0
  211. package/dist/op/discover.d.ts.map +1 -1
  212. package/dist/op/duration.d.ts +11 -0
  213. package/dist/op/duration.d.ts.map +1 -0
  214. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  215. package/dist/op/gate.d.ts +90 -0
  216. package/dist/op/gate.d.ts.map +1 -0
  217. package/dist/op/generate-pipeline.d.ts +9 -0
  218. package/dist/op/generate-pipeline.d.ts.map +1 -1
  219. package/dist/op/index.d.ts +23 -7
  220. package/dist/op/index.d.ts.map +1 -1
  221. package/dist/op/local-executor.d.ts +114 -28
  222. package/dist/op/local-executor.d.ts.map +1 -1
  223. package/dist/op/local-output.d.ts +11 -1
  224. package/dist/op/local-output.d.ts.map +1 -1
  225. package/dist/op/op-ir.d.ts +184 -0
  226. package/dist/op/op-ir.d.ts.map +1 -0
  227. package/dist/op/op-verb-class.d.ts +10 -2
  228. package/dist/op/op-verb-class.d.ts.map +1 -1
  229. package/dist/op/operator.d.ts +30 -5
  230. package/dist/op/operator.d.ts.map +1 -1
  231. package/dist/op/receipt-store.d.ts +1 -1
  232. package/dist/op/receipt-store.d.ts.map +1 -1
  233. package/dist/op/resource.d.ts +15 -1
  234. package/dist/op/resource.d.ts.map +1 -1
  235. package/dist/op/runtime.d.ts +200 -0
  236. package/dist/op/runtime.d.ts.map +1 -0
  237. package/dist/op/runtimes/local.d.ts +29 -0
  238. package/dist/op/runtimes/local.d.ts.map +1 -0
  239. package/dist/op/step-output-ref.d.ts +15 -13
  240. package/dist/op/step-output-ref.d.ts.map +1 -1
  241. package/dist/op/types.d.ts +79 -27
  242. package/dist/op/types.d.ts.map +1 -1
  243. package/dist/ownership.d.ts +1 -1
  244. package/dist/provenance.d.ts +21 -0
  245. package/dist/provenance.d.ts.map +1 -1
  246. package/dist/serializer-walker.d.ts.map +1 -1
  247. package/package.json +6 -1
  248. package/src/audit/catalog.test.ts +79 -3
  249. package/src/audit/catalog.ts +111 -13
  250. package/src/audit/core.test.ts +26 -0
  251. package/src/audit/core.ts +61 -17
  252. package/src/audit/discover.test.ts +39 -0
  253. package/src/audit/discover.ts +91 -15
  254. package/src/audit/lineage.ts +100 -0
  255. package/src/audit/prior-art.ts +153 -0
  256. package/src/audit/proof.test.ts +67 -0
  257. package/src/audit/proof.ts +70 -0
  258. package/src/audit/report-html.ts +9 -4
  259. package/src/audit/report-model.ts +16 -2
  260. package/src/audit/report.test.ts +33 -0
  261. package/src/audit/report.ts +5 -3
  262. package/src/audit/rules-doc.test.ts +34 -2
  263. package/src/audit/rules-doc.ts +82 -9
  264. package/src/audit/secrets.ts +15 -3
  265. package/src/audit/terraform-state.test.ts +144 -0
  266. package/src/audit/terraform-state.ts +131 -0
  267. package/src/build.ts +31 -1
  268. package/src/claimed-fields.test.ts +145 -0
  269. package/src/claimed-fields.ts +208 -0
  270. package/src/cli/build-params-cli.ts +2 -2
  271. package/src/cli/command-group.ts +14 -0
  272. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  273. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  274. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  275. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  276. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  277. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  278. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  279. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  280. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  281. package/src/cli/commands/audit.test.ts +189 -11
  282. package/src/cli/commands/audit.ts +73 -27
  283. package/src/cli/commands/build.test.ts +292 -9
  284. package/src/cli/commands/build.ts +156 -24
  285. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  286. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  287. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  288. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  289. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  290. package/src/cli/commands/init-lexicon.test.ts +97 -2
  291. package/src/cli/commands/init-lexicon.ts +4 -2
  292. package/src/cli/commands/init.test.ts +35 -1
  293. package/src/cli/commands/init.ts +14 -3
  294. package/src/cli/commands/lint.test.ts +48 -0
  295. package/src/cli/commands/lint.ts +123 -0
  296. package/src/cli/commands/onboard.test.ts +75 -0
  297. package/src/cli/commands/onboard.ts +54 -23
  298. package/src/cli/handlers/build.test.ts +81 -1
  299. package/src/cli/handlers/build.ts +15 -1
  300. package/src/cli/handlers/graph.test.ts +3 -3
  301. package/src/cli/handlers/lifecycle.test.ts +195 -12
  302. package/src/cli/handlers/lifecycle.ts +123 -6
  303. package/src/cli/handlers/misc.ts +1 -1
  304. package/src/cli/handlers/operator.test.ts +183 -11
  305. package/src/cli/handlers/operator.ts +260 -55
  306. package/src/cli/handlers/run.test.ts +431 -1287
  307. package/src/cli/handlers/run.ts +365 -915
  308. package/src/cli/main.test.ts +23 -15
  309. package/src/cli/main.ts +88 -33
  310. package/src/cli/mcp/op-tools.ts +147 -88
  311. package/src/cli/mcp/resource-handlers.ts +10 -37
  312. package/src/cli/mcp/resources/context.ts +11 -12
  313. package/src/cli/mcp/server.test.ts +25 -27
  314. package/src/cli/mcp/server.ts +2 -2
  315. package/src/cli/registry.ts +26 -9
  316. package/src/codegen/docs.ts +1 -1
  317. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  318. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  319. package/src/components/README.md +3 -2
  320. package/src/components/auto-release.test.ts +4 -20
  321. package/src/components/auto-release.ts +17 -42
  322. package/src/components/capability.ts +4 -4
  323. package/src/components/cli-support.test.ts +10 -5
  324. package/src/components/cli-support.ts +52 -44
  325. package/src/components/component.schema.json +2 -2
  326. package/src/components/component.ts +3 -3
  327. package/src/components/driver-output.ts +14 -2
  328. package/src/components/driver.test.ts +92 -22
  329. package/src/components/driver.ts +193 -83
  330. package/src/components/index.ts +1 -6
  331. package/src/components/manifest-persistence.test.ts +2 -20
  332. package/src/components/manifest-persistence.ts +4 -24
  333. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  334. package/src/components/run-progress.ts +6 -6
  335. package/src/components/verbs/run-agent.ts +11 -17
  336. package/src/components/verbs/verify.ts +2 -2
  337. package/src/deep-observation.test.ts +75 -0
  338. package/src/deep-observation.ts +48 -0
  339. package/src/discovery/collect.test.ts +3 -3
  340. package/src/discovery/files.ts +4 -4
  341. package/src/discovery/fold-import.ts +105 -2
  342. package/src/discovery/param-deps.test.ts +112 -1
  343. package/src/discovery/param-deps.ts +193 -0
  344. package/src/discovery/sandbox/bundle.ts +15 -1
  345. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  346. package/src/discovery/sandbox/config-wire.ts +2 -2
  347. package/src/fold/fold.test.ts +56 -0
  348. package/src/fold/foldable-helpers.ts +81 -1
  349. package/src/fold-provenance-exclusion.test.ts +186 -0
  350. package/src/fold-provenance.test.ts +495 -0
  351. package/src/fold-provenance.ts +441 -0
  352. package/src/graph-ops.test.ts +2 -2
  353. package/src/graph-ops.ts +1 -1
  354. package/src/held-elsewhere.test.ts +102 -0
  355. package/src/held-elsewhere.ts +114 -0
  356. package/src/index.ts +3 -0
  357. package/src/kubectl-context.ts +3 -3
  358. package/src/lexicon-config.test.ts +5 -5
  359. package/src/lexicon-config.ts +4 -4
  360. package/src/lexicon-plugin-helpers.ts +1 -1
  361. package/src/lexicon.ts +120 -14
  362. package/src/lifecycle/change-set.test.ts +49 -0
  363. package/src/lifecycle/change-set.ts +67 -0
  364. package/src/lifecycle/converge-ledger.ts +1 -1
  365. package/src/lifecycle/deep-diff.test.ts +267 -14
  366. package/src/lifecycle/deep-diff.ts +217 -14
  367. package/src/lifecycle/deep-observe.test.ts +3 -1
  368. package/src/lifecycle/deep-observe.ts +16 -6
  369. package/src/lifecycle/gate-ledger.test.ts +74 -2
  370. package/src/lifecycle/gate-ledger.ts +143 -36
  371. package/src/lifecycle/index.ts +1 -0
  372. package/src/lifecycle/release-ledger.ts +2 -2
  373. package/src/lifecycle/run-ledger.test.ts +268 -0
  374. package/src/lifecycle/run-ledger.ts +201 -0
  375. package/src/lifecycle/symptoms.ts +3 -3
  376. package/src/lint/config.test.ts +82 -1
  377. package/src/lint/config.ts +112 -3
  378. package/src/lint/policy.test.ts +1 -1
  379. package/src/lint/post-synth.test.ts +31 -0
  380. package/src/lint/post-synth.ts +54 -1
  381. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  382. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  383. package/src/lint/rules/comp/comp.test.ts +1 -1
  384. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
  385. package/src/lint/rules/comp/index.ts +3 -3
  386. package/src/lint/rules/op/index.ts +23 -0
  387. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  388. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  389. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  390. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  391. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  392. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  393. package/src/lint/rules/op/support.ts +11 -0
  394. package/src/lint/suppressions.test.ts +163 -0
  395. package/src/lint/suppressions.ts +204 -0
  396. package/src/live-endpoint.ts +1 -1
  397. package/src/op/activities/activity-contracts.ts +66 -0
  398. package/src/op/activities/apply.test.ts +567 -0
  399. package/src/op/activities/apply.ts +662 -0
  400. package/src/op/activities/build.ts +26 -0
  401. package/src/op/activities/converge.test.ts +330 -0
  402. package/src/op/activities/converge.ts +449 -0
  403. package/src/op/activities/env-teardown.test.ts +187 -0
  404. package/src/op/activities/env-teardown.ts +171 -0
  405. package/src/op/activities/guard-validate.test.ts +139 -0
  406. package/src/op/activities/guard-validate.ts +223 -0
  407. package/src/op/activities/http-check.test.ts +48 -0
  408. package/src/op/activities/http-check.ts +55 -0
  409. package/src/op/activities/index.ts +119 -0
  410. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  411. package/src/op/activities/lexicon-upgrade.ts +673 -0
  412. package/src/op/activities/lifecycle.ts +85 -0
  413. package/src/op/activities/pipeline-audit.test.ts +67 -0
  414. package/src/op/activities/pipeline-audit.ts +201 -0
  415. package/src/op/activities/policy.test.ts +19 -0
  416. package/src/op/activities/policy.ts +37 -0
  417. package/src/op/activities/reconcile.test.ts +81 -0
  418. package/src/op/activities/reconcile.ts +187 -0
  419. package/src/op/activities/shell.ts +26 -0
  420. package/src/op/activities/teardown.ts +22 -0
  421. package/src/op/activities/util.ts +6 -0
  422. package/src/op/activities/wait.ts +69 -0
  423. package/src/op/activities/workflow-audit.test.ts +90 -0
  424. package/src/op/activities/workflow-audit.ts +203 -0
  425. package/src/op/activity-contract-registry.test.ts +98 -0
  426. package/src/op/activity-contract-registry.ts +114 -0
  427. package/src/op/activity-contract.test.ts +1 -1
  428. package/src/op/activity-contract.ts +37 -33
  429. package/src/op/activity-failure.ts +34 -0
  430. package/src/op/activity-profiles.test.ts +56 -0
  431. package/src/op/activity-profiles.ts +116 -0
  432. package/src/op/activity-registry.test.ts +37 -28
  433. package/src/op/activity-registry.ts +27 -56
  434. package/src/op/activity-runtime.ts +3 -47
  435. package/src/op/builders-exports.test.ts +0 -49
  436. package/src/op/builders-typed.test.ts +164 -0
  437. package/src/op/builders.ts +123 -39
  438. package/src/op/composites/apply-op.ts +208 -0
  439. package/src/op/composites/composites.test.ts +366 -0
  440. package/src/op/composites/converge-op.test.ts +168 -0
  441. package/src/op/composites/converge-op.ts +214 -0
  442. package/src/op/composites/index.ts +26 -0
  443. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  444. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  445. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  446. package/src/op/composites/pipeline-audit-op.ts +78 -0
  447. package/src/op/composites/reconcile-op.test.ts +51 -0
  448. package/src/op/composites/reconcile-op.ts +107 -0
  449. package/src/op/composites/watch-op.ts +108 -0
  450. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  451. package/src/op/composites/workflow-audit-op.ts +88 -0
  452. package/src/op/converge-rule.ts +12 -10
  453. package/src/op/cron.test.ts +128 -0
  454. package/src/op/cron.ts +149 -0
  455. package/src/op/discover-root.test.ts +105 -1
  456. package/src/op/discover.test.ts +6 -2
  457. package/src/op/discover.ts +84 -16
  458. package/src/op/duration.ts +21 -0
  459. package/src/op/effect-step.test.ts +26 -11
  460. package/src/op/emulator-lifecycle.ts +1 -2
  461. package/src/op/gate.ts +155 -0
  462. package/src/op/generate-pipeline.test.ts +65 -3
  463. package/src/op/generate-pipeline.ts +19 -2
  464. package/src/op/index.ts +39 -6
  465. package/src/op/local-executor.test.ts +163 -34
  466. package/src/op/local-executor.ts +370 -102
  467. package/src/op/local-output.test.ts +95 -11
  468. package/src/op/local-output.ts +33 -4
  469. package/src/op/op-ir.test.ts +281 -0
  470. package/src/op/op-ir.ts +417 -0
  471. package/src/op/op-verb-class.ts +19 -5
  472. package/src/op/op.test.ts +26 -5
  473. package/src/op/operator.test.ts +175 -6
  474. package/src/op/operator.ts +63 -16
  475. package/src/op/receipt-store.ts +1 -1
  476. package/src/op/resource.ts +20 -2
  477. package/src/op/runtime.ts +203 -0
  478. package/src/op/runtimes/local.test.ts +181 -0
  479. package/src/op/runtimes/local.ts +212 -0
  480. package/src/op/step-output-ref.ts +15 -13
  481. package/src/op/types.ts +84 -24
  482. package/src/ownership.ts +1 -1
  483. package/src/provenance.test.ts +6 -0
  484. package/src/provenance.ts +21 -1
  485. package/src/serializer-walker.test.ts +42 -0
  486. package/src/serializer-walker.ts +21 -2
  487. package/dist/cli/handlers/op-progress.d.ts +0 -90
  488. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  489. package/dist/cli/handlers/run-client.d.ts +0 -127
  490. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  491. package/dist/cli/handlers/run-report.d.ts +0 -5
  492. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  493. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  494. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  495. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  496. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  497. package/src/cli/handlers/op-progress.test.ts +0 -268
  498. package/src/cli/handlers/op-progress.ts +0 -248
  499. package/src/cli/handlers/run-client.test.ts +0 -82
  500. package/src/cli/handlers/run-client.ts +0 -219
  501. package/src/cli/handlers/run-report.test.ts +0 -62
  502. package/src/cli/handlers/run-report.ts +0 -122
  503. package/src/components/temporal-codegen-loader.ts +0 -41
  504. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  export * from "./declarable";
8
+ export * from "./held-elsewhere";
8
9
  export * from "./composite";
9
10
  export * from "./provenance";
10
11
  export * from "./secret-provenance";
@@ -56,6 +57,8 @@ export * from "./observation";
56
57
  export * from "./identity";
57
58
  export * from "./apply";
58
59
  export * from "./deep-observation";
60
+ export * from "./claimed-fields";
61
+ export * from "./fold-provenance";
59
62
  export * from "./owner-chain";
60
63
  export * from "./lexicon-integrity";
61
64
  export * from "./lexicon-manifest";
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Every cloud lexicon binds an environment to a scope: AWS resolves `<env>`
5
5
  * to a CloudFormation stack, Azure treats `<env>` as the resource group,
6
- * Temporal looks up `temporal.profiles.<env>` in `chant.config.ts`. K8s (and
6
+ * Fly resolves it to an app. K8s (and
7
7
  * GCP-via-Config-Connector, which observes through the same kubectl path)
8
8
  * bound nothing — `describeResources` shelled out to `kubectl get` with no
9
9
  * `--context`, so it read whatever cluster `kubectl config current-context`
@@ -111,8 +111,8 @@ export interface ResolveClusterTargetOptions {
111
111
  * Resolve the kubectl context an environment should be observed/applied
112
112
  * against, reading `k8s.profiles.<environment>.context` from `chant.config.ts`
113
113
  * (the `config` passed in is the passthrough `ChantConfig`, cast loosely since
114
- * the `k8s` key isn't declared on the core schema — same pattern as
115
- * `temporal.profiles`).
114
+ * the `k8s` key isn't declared on the core schema — the same pattern every
115
+ * lexicon namespace follows).
116
116
  *
117
117
  * - No binding declared: returns `{ source: "ambient" }` — unchanged
118
118
  * behavior — but logs a visible warning identifying the caller and
@@ -67,15 +67,15 @@ describe("validateLexiconConfig (#1344)", () => {
67
67
  });
68
68
 
69
69
  test("validates each declaring lexicon independently", () => {
70
- const temporal = {
71
- name: "temporal",
70
+ const k8s = {
71
+ name: "k8s",
72
72
  configSchema: z.strictObject({ defaultProfile: z.string().optional() }),
73
73
  };
74
74
  const problems = validateLexiconConfig(
75
- [forgejo, temporal],
76
- cfg({ forgejo: { actionsRoot: "https://x" }, temporal: { defaultProfil: "local" } }),
75
+ [forgejo, k8s],
76
+ cfg({ forgejo: { actionsRoot: "https://x" }, k8s: { defaultProfil: "local" } }),
77
77
  );
78
- expect(problems.map((p) => p.lexicon)).toEqual(["temporal"]);
78
+ expect(problems.map((p) => p.lexicon)).toEqual(["k8s"]);
79
79
  });
80
80
 
81
81
  test("no config at all is not a problem", () => {
@@ -2,7 +2,7 @@
2
2
  * The config namespace a lexicon owns (#1344).
3
3
  *
4
4
  * Three lexicons read a top-level `chant.config.ts` key named after themselves —
5
- * `k8s.profiles.<env>.context`, `temporal.profiles`, `forgejo.runnerLabels` and
5
+ * `k8s.profiles.<env>.context`, `forgejo.runnerLabels` and
6
6
  * `forgejo.actionsRoot` — all documented for users, none declared anywhere.
7
7
  * `ChantConfigSchema` is `.passthrough()`, so at runtime any key is accepted and
8
8
  * a typo is silently ignored: write `runnerLabel` and the Forgejo dialect just
@@ -12,9 +12,9 @@
12
12
  * error TS2353: Object literal may only specify known properties,
13
13
  * and 'forgejo' does not exist in type 'ChantConfig'.
14
14
  *
15
- * Three lexicons had arrived at three different workarounds: temporal exported
16
- * its own widened `TemporalChantConfig`, k8s's docs dropped `satisfies`, and
17
- * forgejo's kept it and were wrong.
15
+ * The lexicons had arrived at different workarounds: one exported its own
16
+ * widened config type, k8s's docs dropped `satisfies`, and forgejo's kept it
17
+ * and were wrong.
18
18
  *
19
19
  * A lexicon now declares the shape of its namespace. The declaration is both
20
20
  * halves of the fix at once: core validates against it at load, and the lexicon
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Shared helpers for lexicon plugin implementations.
3
3
  *
4
- * Eliminates boilerplate across the 8 lexicon plugins by providing
4
+ * Eliminates boilerplate across the 15 lexicon plugins that use it by providing
5
5
  * factory functions for common plugin methods: skills loading,
6
6
  * MCP diff tool, and MCP catalog resource.
7
7
  */
package/src/lexicon.ts CHANGED
@@ -12,6 +12,9 @@ import type { CompletionContext, CompletionItem, HoverContext, HoverInfo, CodeAc
12
12
  import type { McpToolContribution, McpResourceContribution } from "./mcp/types";
13
13
  import type { DriverComponent } from "./components/driver";
14
14
  import type { EmulatorDeclaration } from "./op/emulator-lifecycle";
15
+ import type { OpRuntimeProvider } from "./op/runtime";
16
+ import type { OpSchedule } from "./op/types";
17
+ import type { ActivityContract } from "./op/activity-contract";
15
18
  import type { OwnershipChannel, OwnershipMarker } from "./ownership";
16
19
  import type { LexiconConfigSchema } from "./lexicon-config";
17
20
  import type { RuleMeta } from "./audit/catalog";
@@ -24,6 +27,17 @@ import type { DisruptionQuery, DisruptionVerdict } from "./lifecycle/disruption"
24
27
  import type { OwnerChainVerdict } from "./owner-chain";
25
28
  import type { CommandGroup } from "./cli/command-group";
26
29
 
30
+ // Re-exported so a lexicon that hosts Op runs (#2121) can type its
31
+ // `opRuntime` from the same entry it imports the plugin contract from.
32
+ export type {
33
+ OpRuntimeProvider,
34
+ OpRunHandle,
35
+ OpRunRecord,
36
+ OpRunStartOptions,
37
+ OpRunState,
38
+ OpRunStatus,
39
+ } from "./op/runtime";
40
+
27
41
  // Re-exported so a lexicon can author its command group (#1078) from the
28
42
  // same `@intentius/chant/lexicon` entry it imports the plugin contract from.
29
43
  export type { CommandGroup, CommandGroupCommand, CommandGroupContext } from "./cli/command-group";
@@ -472,9 +486,9 @@ export interface ComponentPipelineResult {
472
486
  }
473
487
 
474
488
  /**
475
- * Finding-mode a scheduled Op surfaces on drift — the vocabulary the
476
- * temporal-lexicon composites (`WorkflowAuditOp`/`PipelineAuditOp`/
477
- * `ReconcileOp`) already declare on the Op itself (#927). The mode is baked
489
+ * Finding-mode a scheduled Op surfaces on drift — the vocabulary the core
490
+ * composites (`WorkflowAuditOp`/`PipelineAuditOp`/`ReconcileOp`) already
491
+ * declare on the Op itself (#927). The mode is baked
478
492
  * into the Op's own activity args at build time and is never re-passed on the
479
493
  * generated CI invocation; here it decides only what token/permission wiring
480
494
  * the generated job needs to act on a finding — elevated write access for
@@ -482,24 +496,74 @@ export interface ComponentPipelineResult {
482
496
  */
483
497
  export type OpFindingMode = "report" | "issue" | "pull-request" | "merge-request";
484
498
 
499
+ /**
500
+ * The CI-native trigger driving a scheduled Op's generated workflow. `cron`
501
+ * is the historical shape — the CI-only way to give an Op a cadence.
502
+ * `pull_request` and `push` are generic beyond cron: a
503
+ * Terraform CI shape needs `plan` on `pull_request` (posted as a PR comment)
504
+ * and `apply` on `push` to the default branch, each its own Op with its own
505
+ * trigger (#2081, #2084).
506
+ */
507
+ export type OpTrigger =
508
+ | { kind: "cron"; schedule: string }
509
+ | { kind: "pull_request"; branches?: string[] }
510
+ | { kind: "push"; branches?: string[] };
511
+
485
512
  /** One scheduled Op to generate CI for — the cron-triggered counterpart to a component (generate mode). */
486
513
  export interface ScheduledOpSpec {
487
514
  /** Op name (`*.op.ts`'s `Op({ name })`) — what `chant run <name>` targets. */
488
515
  name: string;
489
- /** Cron expression driving the CI-native trigger — the CI-only alternative to a Temporal `TemporalSchedule`. */
490
- schedule: string;
516
+ /**
517
+ * Cron expression driving the CI-native trigger. Superseded by `trigger`; kept for
518
+ * backward compatibility, so an omitted `trigger` with `schedule` present
519
+ * still means `{ kind: "cron", schedule }` (see {@link resolveOpTrigger}).
520
+ */
521
+ schedule?: string;
522
+ /**
523
+ * The CI-native trigger driving this Op's generated workflow (#2084).
524
+ * Omit this and set only `schedule` for the pre-existing cron behavior;
525
+ * set explicitly for `pull_request`/`push`, or to spell cron the same way.
526
+ */
527
+ trigger?: OpTrigger;
528
+ /**
529
+ * The declaring Op's own cadence (#2120) — `OpConfig.schedule`, filled in
530
+ * by `generateOpsPipeline` from the discovered Op so a scheduled Op needs
531
+ * no second cron declaration on the CI side. The lowest-precedence source
532
+ * of a trigger: an explicit `trigger` first, then an explicit `schedule` on
533
+ * this spec, then this (see {@link resolveOpTrigger}).
534
+ */
535
+ opSchedule?: OpSchedule;
491
536
  /** This Op's finding-mode, for permission/token wiring only (see {@link OpFindingMode}). Default: "report" — no elevated permissions. */
492
537
  findingMode?: OpFindingMode;
493
538
  }
494
539
 
540
+ /**
541
+ * Resolve a `ScheduledOpSpec`'s effective trigger, most specific first:
542
+ * `trigger` when given; else the backward-compatible `{ kind: "cron",
543
+ * schedule }` built from this spec's own `schedule` — every pre-#2084 caller
544
+ * (`WorkflowAuditOp`, `PipelineAuditOp`, `ReconcileOp`, …, and their tests)
545
+ * sets only that and keeps meaning cron unchanged; else the declaring Op's
546
+ * own `schedule.cron` (#2120), so an Op that already carries its cadence
547
+ * needs no second cron declaration on the CI side. Throws when none of the
548
+ * three is present — a `ScheduledOpSpec` needs exactly one trigger.
549
+ */
550
+ export function resolveOpTrigger(spec: ScheduledOpSpec): OpTrigger {
551
+ if (spec.trigger) return spec.trigger;
552
+ if (spec.schedule) return { kind: "cron", schedule: spec.schedule };
553
+ if (spec.opSchedule) return { kind: "cron", schedule: spec.opSchedule.cron };
554
+ throw new Error(
555
+ `Scheduled Op "${spec.name}" has neither \`trigger\` nor \`schedule\`, and the Op itself declares no \`schedule\` — one is required.`,
556
+ );
557
+ }
558
+
495
559
  /** One CI job generated for a scheduled Op. */
496
560
  export interface OpPipelineJob {
497
561
  /** CI job name (safe as a YAML key). */
498
562
  jobName: string;
499
563
  /** The Op this job runs. */
500
564
  op: string;
501
- /** Cron expression this job's workflow is scheduled on. */
502
- schedule: string;
565
+ /** The trigger driving this job's generated workflow (#2084) — lets a consumer tell cron/`pull_request`/`push` jobs apart. */
566
+ trigger: OpTrigger;
503
567
  /** The finding-mode wired for this job. */
504
568
  findingMode: OpFindingMode;
505
569
  }
@@ -623,8 +687,8 @@ export interface LexiconPlugin {
623
687
  * The shape of this lexicon's own `chant.config.ts` namespace — the top-level
624
688
  * key named after the lexicon (#1344).
625
689
  *
626
- * k8s reads `k8s.profiles.<env>.context`, temporal `temporal.profiles`,
627
- * forgejo `forgejo.runnerLabels` and `forgejo.actionsRoot`. All were
690
+ * k8s reads `k8s.profiles.<env>.context`, forgejo `forgejo.runnerLabels`
691
+ * and `forgejo.actionsRoot`. All were
628
692
  * documented for users and declared nowhere: the config schema is
629
693
  * `.passthrough()`, so a typo was accepted and silently ignored, and the
630
694
  * `ChantConfig` interface is closed, so the documented examples did not
@@ -680,6 +744,22 @@ export interface LexiconPlugin {
680
744
  /** Return post-synthesis checks for build validation */
681
745
  postSynthChecks?(): PostSynthCheck[];
682
746
 
747
+ /**
748
+ * Activity contracts (`ActivityContract`, `./op/activity-contract.ts`) for
749
+ * the activities this lexicon implements, so another lexicon's post-synth
750
+ * check can validate an Op step calling one of them (chant #2101).
751
+ *
752
+ * The ordinary way to contribute these is the same convention activities
753
+ * themselves use: export them from
754
+ * `@intentius/chant-lexicon-<name>/op/activity-contracts`, and
755
+ * `loadActivityContracts` (`./op/activity-contract-registry.ts`) finds them
756
+ * with no plugin member at all. This member is the escape hatch for a
757
+ * lexicon whose contracts are not reachable at that subpath — a bundled
758
+ * single-file plugin, a project-local one — and both sources are merged
759
+ * when both are present. Omit it in the common case.
760
+ */
761
+ activityContracts?(): ActivityContract[];
762
+
683
763
  /**
684
764
  * Audit catalog metadata (title/tier/fix/authority/category) for this
685
765
  * lexicon's `postSynthChecks`, keyed by check id — the per-provider half of
@@ -689,6 +769,17 @@ export interface LexiconPlugin {
689
769
  */
690
770
  auditCatalog?(): Record<string, RuleMeta>;
691
771
 
772
+ /**
773
+ * Preset name mapped to the post-synth check ids that preset enables
774
+ * (chant #2113), e.g. `{ recommended: ["TF001", ...], all: ["TF001", ..., "TF011"] }`.
775
+ * A project selects one via `lint.presets: { "<this lexicon's name>": "<preset>" }`
776
+ * (`./lint/config.ts`'s `LintConfig.presets`). `resolvePresetIds` and
777
+ * `applyConfiguredPreset` (same file) do the filtering. Omit for a lexicon
778
+ * that ships no presets. Its post-synth findings are unaffected by
779
+ * `lint.presets`, exactly as before this existed.
780
+ */
781
+ lintPresets?(): Record<string, string[]>;
782
+
692
783
  /**
693
784
  * Parse standalone template content (a file audit discovery classified for
694
785
  * this lexicon) into the lexicon's entity graph, keyed the way `ctx.entities`
@@ -696,9 +787,12 @@ export interface LexiconPlugin {
696
787
  * `chant audit` of hand-written manifests — parse-to-graph rather than
697
788
  * output-reading rule variants (#1567). Implementations must tolerate
698
789
  * arbitrary external content: a malformed document yields no entities, never
699
- * a throw. Omit for lexicons whose audit checks read `ctx.outputs`.
790
+ * a throw. Omit for lexicons whose audit checks read `ctx.outputs`. May
791
+ * return a `Promise` for a lexicon whose parser is inherently async (e.g.
792
+ * terraform's HCL parser, a lazy-loaded wasm module). `auditLexicon` awaits
793
+ * it before reading `ctx.entities`.
700
794
  */
701
- auditEntities?(content: string): Map<string, Declarable>;
795
+ auditEntities?(content: string): Map<string, Declarable> | Promise<Map<string, Declarable>>;
702
796
 
703
797
  /**
704
798
  * Machine-readable spec-coverage accounting for `check-lexicon` (#1330).
@@ -785,6 +879,18 @@ export interface LexiconPlugin {
785
879
  options?: ComponentPipelineOptions,
786
880
  ): OpPipelineResult;
787
881
 
882
+ /**
883
+ * Host Op runs — the seam `chant run <op> --on <this lexicon>` dispatches to
884
+ * (#2121, epic #2114). Core ships one provider of its own, `local`, and
885
+ * selects it when no `--on` is passed; a lexicon that can start, watch,
886
+ * cancel and wake runs somewhere else implements the same contract and
887
+ * every `chant run` subcommand goes through it unchanged.
888
+ *
889
+ * Core never imports a hosting lexicon, so this is the only direction the
890
+ * dependency runs. Omit for lexicons that host nothing.
891
+ */
892
+ readonly opRuntime?: OpRuntimeProvider;
893
+
788
894
  /**
789
895
  * Render this lexicon's config-declared build roots into entities (#1548
790
896
  * piece 3) — the seam for a build root that is NOT typed chant source. The
@@ -842,7 +948,7 @@ export interface LexiconPlugin {
842
948
  * Query deployed resources and return API metadata. Opt-in.
843
949
  *
844
950
  * Use this when each chant entity has a 1:1 cloud equivalent — e.g. an
845
- * AWS CFN resource, a K8s object, an ARM resource, a Temporal namespace.
951
+ * AWS CFN resource, a K8s object, an ARM resource, a Fly app.
846
952
  *
847
953
  * **The observation contract (#1089).** Returning nothing for a declared
848
954
  * entity is a claim, and there are two different claims to make. Either the
@@ -875,8 +981,8 @@ export interface LexiconPlugin {
875
981
  * `entities` carries the chant-side entity declarations for this lexicon,
876
982
  * keyed by chant entity name (e.g. the export name from a `*.ts` file).
877
983
  * Implementations that need to map cloud-side names back to chant entity
878
- * names (e.g. Temporal — server-side namespace `prod` ↔ chant entity `ns`
879
- * declared with `name: "prod"`) read this; implementations that already
984
+ * names (server-side name `prod` ↔ chant entity `ns` declared with
985
+ * `name: "prod"`) read this; implementations that already
880
986
  * have name parity (e.g. AWS CloudFormation logical IDs == chant entity
881
987
  * names) can ignore it.
882
988
  *
@@ -8,6 +8,7 @@ import {
8
8
  unobservedPlanNotice,
9
9
  type ChangeSet,
10
10
  type ChangeSetEntry,
11
+ type HeldEntitySet,
11
12
  } from "./change-set";
12
13
  import type { ResourceMetadata } from "../lexicon";
13
14
 
@@ -589,3 +590,51 @@ describe("renderChangeSetMarkdown (#1983)", () => {
589
590
  expect(few).not.toContain("<details>");
590
591
  });
591
592
  });
593
+
594
+ // #2162 — a held property is never a `ChangeAction`: it rides beside
595
+ // `entries` on the change set, in its own section, in both renders.
596
+ describe("ChangeSet.held (#2162)", () => {
597
+ const heldEntities: HeldEntitySet[] = [
598
+ {
599
+ name: "web",
600
+ type: "K8s::Apps::Deployment",
601
+ lexicon: "k8s",
602
+ held: [
603
+ { path: "spec.replicas", by: "hpa", reason: "the autoscaler owns replicas after the first apply", live: 5, suspicious: false },
604
+ ],
605
+ },
606
+ ];
607
+
608
+ test("renderChangeSet: a HELD section, separate from every action group", () => {
609
+ const cs: ChangeSet = { ...set([entry({ action: "noop" })]), held: heldEntities };
610
+ const out = renderChangeSet(cs);
611
+ expect(out).toContain("HELD (declared heldElsewhere(); not drift, never proposed for update)");
612
+ expect(out).toContain("web (K8s::Apps::Deployment) k8s");
613
+ expect(out).toContain("spec.replicas: held by hpa — 5 (the autoscaler owns replicas after the first apply)");
614
+ });
615
+
616
+ test("renderChangeSetMarkdown: its own section, held entries never counted in the header", () => {
617
+ const cs: ChangeSet = { ...set([entry({ action: "noop" })]), held: heldEntities };
618
+ const out = renderChangeSetMarkdown(cs);
619
+ expect(out).toContain("### HELD (declared heldElsewhere(); not drift, never proposed for update)");
620
+ expect(out).toContain("`web` (K8s::Apps::Deployment) `k8s`");
621
+ expect(out).toContain("spec.replicas: held by hpa — 5");
622
+ // The counts header only ever tallies `ChangeAction`s.
623
+ expect(out).toContain("0 create, 0 update, 0 effect, 0 delete, 0 adopt, 0 runtime, 1 noop, 0 unobserved");
624
+ });
625
+
626
+ test("a suspicious held property is marked in both renders", () => {
627
+ const suspicious: HeldEntitySet[] = [
628
+ { name: "cfg", type: "T", held: [{ path: "A", by: "controller", reason: "x", suspicious: true }] },
629
+ ];
630
+ const cs: ChangeSet = { ...set([]), held: suspicious };
631
+ expect(renderChangeSet(cs)).toContain("[SUSPICIOUS: no live value ever showed up here]");
632
+ expect(renderChangeSetMarkdown(cs)).toContain("SUSPICIOUS: no live value ever showed up here");
633
+ });
634
+
635
+ test("omitted entirely when nothing is held — no empty section in either render", () => {
636
+ const cs = set([entry({ action: "noop" })]);
637
+ expect(renderChangeSet(cs)).not.toContain("HELD");
638
+ expect(renderChangeSetMarkdown(cs)).not.toContain("HELD");
639
+ });
640
+ });
@@ -15,6 +15,7 @@
15
15
  import { diffLive, type AttributeChange, type DiffLiveInput } from "./live-diff";
16
16
  import { unobservedReasonText, type UnobservedReason } from "../observation";
17
17
  import { renderDisruption, summarizeDisruption, type Disruption } from "./disruption";
18
+ import type { DeepEntityHeld } from "./deep-diff";
18
19
 
19
20
  /**
20
21
  * What the projection proposes for a single resource.
@@ -148,9 +149,22 @@ export interface ChangeSetEntry {
148
149
  disruptionDetail?: string;
149
150
  }
150
151
 
152
+ /** One entity's held properties (#2162), attributed to the lexicon that observed it — a plan merges every lexicon's, so the attribution has to survive the merge the same way {@link ChangeSetEntry.lexicon} does. */
153
+ export interface HeldEntitySet extends DeepEntityHeld {
154
+ lexicon?: string;
155
+ }
156
+
151
157
  export interface ChangeSet {
152
158
  env: string;
153
159
  entries: ChangeSetEntry[];
160
+ /**
161
+ * Properties declared `heldElsewhere()` (#2162), across every lexicon this
162
+ * plan checked. Not part of `entries`: a held property is never a proposal
163
+ * — it carries no `ChangeAction` — so it rides beside the actionable set
164
+ * rather than inside it, the same way `unobservedPlanNotice` rides beside
165
+ * rather than inside. Omitted when nothing declared one.
166
+ */
167
+ held?: HeldEntitySet[];
154
168
  }
155
169
 
156
170
  /**
@@ -407,9 +421,58 @@ export function renderChangeSet(cs: ChangeSet): string {
407
421
  }
408
422
  }
409
423
 
424
+ if (cs.held && cs.held.length > 0) {
425
+ lines.push(`\n${heldSectionLabel()}:`);
426
+ for (const line of heldLines(cs.held)) lines.push(line);
427
+ }
428
+
410
429
  return lines.join("\n");
411
430
  }
412
431
 
432
+ /**
433
+ * Section heading for the held set (#2162) — shared between {@link renderChangeSet}
434
+ * and {@link renderChangeSetMarkdown}.
435
+ */
436
+ function heldSectionLabel(): string {
437
+ return "HELD (declared heldElsewhere(); not drift, never proposed for update)";
438
+ }
439
+
440
+ /** One held property's plain-text line, indented under its entity. */
441
+ function heldLines(held: readonly HeldEntitySet[]): string[] {
442
+ const lines: string[] = [];
443
+ for (const entity of held) {
444
+ const lexicon = entity.lexicon ? ` ${entity.lexicon}` : "";
445
+ lines.push(` ${entity.name} (${entity.type})${lexicon}`);
446
+ for (const h of entity.held) {
447
+ const live = "live" in h ? fmt(h.live) : "<absent>";
448
+ const suspicious = h.suspicious
449
+ ? " [SUSPICIOUS: no live value ever showed up here]"
450
+ : "";
451
+ lines.push(` ${h.path}: held by ${h.by} — ${live} (${h.reason})${suspicious}`);
452
+ }
453
+ }
454
+ return lines;
455
+ }
456
+
457
+ /** One held property's markdown line, mirroring {@link renderMarkdownEntry}'s formatting. */
458
+ function heldLinesMarkdown(held: readonly HeldEntitySet[]): string[] {
459
+ const lines: string[] = [];
460
+ for (const entity of held) {
461
+ const lexicon = entity.lexicon ? ` \`${entity.lexicon}\`` : "";
462
+ lines.push(`- \`${entity.name}\` (${entity.type})${lexicon}`);
463
+ if (entity.held.length > 0) {
464
+ lines.push(" ```");
465
+ for (const h of entity.held) {
466
+ const live = "live" in h ? fmt(h.live) : "<absent>";
467
+ const suspicious = h.suspicious ? " SUSPICIOUS: no live value ever showed up here" : "";
468
+ lines.push(` ${h.path}: held by ${h.by} — ${live} (${h.reason})${suspicious}`);
469
+ }
470
+ lines.push(" ```");
471
+ }
472
+ }
473
+ return lines;
474
+ }
475
+
413
476
  /**
414
477
  * Entries beyond this in one action group are collapsed into a `<details>`
415
478
  * block in {@link renderChangeSetMarkdown} — a group's worth of rows is fine
@@ -500,6 +563,10 @@ export function renderChangeSetMarkdown(cs: ChangeSet): string {
500
563
  }
501
564
  }
502
565
 
566
+ if (cs.held && cs.held.length > 0) {
567
+ lines.push("", `### ${heldSectionLabel()}`, "", ...heldLinesMarkdown(cs.held));
568
+ }
569
+
503
570
  return lines.join("\n").trimEnd() + "\n";
504
571
  }
505
572
 
@@ -28,7 +28,7 @@ const FILENAME = "converge.jsonl";
28
28
  * record. A record here is one line of JSON, so a multi-line or unbounded
29
29
  * string folded into any field would break the line the ledger is built out
30
30
  * of. Every free-text field a tick writes goes through this: a dispatch
31
- * failure's `stderr` (lexicons/temporal's `sanitizeOneLine`, which delegates
31
+ * failure's `stderr` (a hosting lexicon's own one-line sanitizer delegates
32
32
  * here) and a component verdict's lexicon-authored `detail`.
33
33
  */
34
34
  const MAX_LEDGER_TEXT_LEN = 300;