@intentius/chant 0.57.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (558) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +36 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +26 -9
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/carve-bridge.d.ts.map +1 -1
  34. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  35. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  36. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  38. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  40. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  41. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/lint.d.ts +13 -0
  44. package/dist/cli/commands/lint.d.ts.map +1 -1
  45. package/dist/cli/commands/onboard.d.ts +2 -0
  46. package/dist/cli/commands/onboard.d.ts.map +1 -1
  47. package/dist/cli/handlers/build.d.ts.map +1 -1
  48. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  49. package/dist/cli/handlers/operator.d.ts +82 -16
  50. package/dist/cli/handlers/operator.d.ts.map +1 -1
  51. package/dist/cli/handlers/run.d.ts +49 -42
  52. package/dist/cli/handlers/run.d.ts.map +1 -1
  53. package/dist/cli/main.d.ts +12 -1
  54. package/dist/cli/main.d.ts.map +1 -1
  55. package/dist/cli/mcp/op-tools.d.ts +16 -1
  56. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  57. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  58. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  59. package/dist/cli/plugins.d.ts +22 -0
  60. package/dist/cli/plugins.d.ts.map +1 -1
  61. package/dist/cli/registry.d.ts +40 -9
  62. package/dist/cli/registry.d.ts.map +1 -1
  63. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  64. package/dist/components/auto-release.d.ts +10 -20
  65. package/dist/components/auto-release.d.ts.map +1 -1
  66. package/dist/components/capability.d.ts +4 -4
  67. package/dist/components/cli-support.d.ts +24 -22
  68. package/dist/components/cli-support.d.ts.map +1 -1
  69. package/dist/components/component.d.ts +21 -6
  70. package/dist/components/component.d.ts.map +1 -1
  71. package/dist/components/driver-output.d.ts.map +1 -1
  72. package/dist/components/driver.d.ts +73 -37
  73. package/dist/components/driver.d.ts.map +1 -1
  74. package/dist/components/index.d.ts +1 -2
  75. package/dist/components/index.d.ts.map +1 -1
  76. package/dist/components/manifest-persistence.d.ts +1 -9
  77. package/dist/components/manifest-persistence.d.ts.map +1 -1
  78. package/dist/components/run-progress.d.ts +6 -6
  79. package/dist/components/run-progress.d.ts.map +1 -1
  80. package/dist/components/verbs/run-agent.d.ts +10 -22
  81. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  82. package/dist/components/verbs/verify.d.ts +2 -2
  83. package/dist/deep-observation.d.ts +17 -0
  84. package/dist/deep-observation.d.ts.map +1 -1
  85. package/dist/detectLexicon.d.ts +13 -0
  86. package/dist/detectLexicon.d.ts.map +1 -1
  87. package/dist/discovery/files.d.ts +4 -4
  88. package/dist/discovery/fold-import.d.ts.map +1 -1
  89. package/dist/discovery/param-deps.d.ts +33 -0
  90. package/dist/discovery/param-deps.d.ts.map +1 -1
  91. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  92. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  93. package/dist/fold/foldable-helpers.d.ts +5 -1
  94. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  95. package/dist/fold-provenance.d.ts +236 -0
  96. package/dist/fold-provenance.d.ts.map +1 -0
  97. package/dist/graph-ops.d.ts +1 -1
  98. package/dist/held-elsewhere.d.ts +85 -0
  99. package/dist/held-elsewhere.d.ts.map +1 -0
  100. package/dist/index.d.ts +3 -0
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/kubectl-context.d.ts +3 -3
  103. package/dist/lexicon-config.d.ts +4 -4
  104. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  105. package/dist/lexicon.d.ts +273 -16
  106. package/dist/lexicon.d.ts.map +1 -1
  107. package/dist/lifecycle/change-set.d.ts +13 -0
  108. package/dist/lifecycle/change-set.d.ts.map +1 -1
  109. package/dist/lifecycle/deep-diff.d.ts +133 -6
  110. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  111. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  112. package/dist/lifecycle/gate-ledger.d.ts +79 -3
  113. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  114. package/dist/lifecycle/index.d.ts +1 -0
  115. package/dist/lifecycle/index.d.ts.map +1 -1
  116. package/dist/lifecycle/release-ledger.d.ts +2 -2
  117. package/dist/lifecycle/run-ledger.d.ts +53 -0
  118. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  119. package/dist/lifecycle/symptoms.d.ts +3 -3
  120. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  121. package/dist/lint/config.d.ts +81 -2
  122. package/dist/lint/config.d.ts.map +1 -1
  123. package/dist/lint/post-synth.d.ts +55 -2
  124. package/dist/lint/post-synth.d.ts.map +1 -1
  125. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  126. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  127. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  128. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  129. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  130. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  131. package/dist/lint/rules/comp/index.d.ts +1 -1
  132. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  133. package/dist/lint/rules/op/index.d.ts +16 -0
  134. package/dist/lint/rules/op/index.d.ts.map +1 -0
  135. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  136. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  137. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  138. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  139. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  140. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  141. package/dist/lint/rules/op/support.d.ts +12 -0
  142. package/dist/lint/rules/op/support.d.ts.map +1 -0
  143. package/dist/lint/suppressions.d.ts +108 -0
  144. package/dist/lint/suppressions.d.ts.map +1 -0
  145. package/dist/live-endpoint.d.ts +1 -1
  146. package/dist/op/activities/activity-contracts.d.ts +54 -0
  147. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  148. package/dist/op/activities/apply.d.ts +262 -0
  149. package/dist/op/activities/apply.d.ts.map +1 -0
  150. package/dist/op/activities/build.d.ts +13 -0
  151. package/dist/op/activities/build.d.ts.map +1 -0
  152. package/dist/op/activities/converge.d.ts +110 -0
  153. package/dist/op/activities/converge.d.ts.map +1 -0
  154. package/dist/op/activities/env-teardown.d.ts +76 -0
  155. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  156. package/dist/op/activities/guard-validate.d.ts +64 -0
  157. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  158. package/dist/op/activities/http-check.d.ts +34 -0
  159. package/dist/op/activities/http-check.d.ts.map +1 -0
  160. package/dist/op/activities/index.d.ts +31 -0
  161. package/dist/op/activities/index.d.ts.map +1 -0
  162. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  163. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  164. package/dist/op/activities/lifecycle.d.ts +42 -0
  165. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  166. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  167. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  168. package/dist/op/activities/policy.d.ts +17 -0
  169. package/dist/op/activities/policy.d.ts.map +1 -0
  170. package/dist/op/activities/reconcile.d.ts +149 -0
  171. package/dist/op/activities/reconcile.d.ts.map +1 -0
  172. package/dist/op/activities/shell.d.ts +13 -0
  173. package/dist/op/activities/shell.d.ts.map +1 -0
  174. package/dist/op/activities/teardown.d.ts +10 -0
  175. package/dist/op/activities/teardown.d.ts.map +1 -0
  176. package/dist/op/activities/util.d.ts +7 -0
  177. package/dist/op/activities/util.d.ts.map +1 -0
  178. package/dist/op/activities/wait.d.ts +28 -0
  179. package/dist/op/activities/wait.d.ts.map +1 -0
  180. package/dist/op/activities/workflow-audit.d.ts +92 -0
  181. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  182. package/dist/op/activity-contract-registry.d.ts +76 -0
  183. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  184. package/dist/op/activity-contract.d.ts +25 -18
  185. package/dist/op/activity-contract.d.ts.map +1 -1
  186. package/dist/op/activity-failure.d.ts +28 -0
  187. package/dist/op/activity-failure.d.ts.map +1 -0
  188. package/dist/op/activity-profiles.d.ts +118 -0
  189. package/dist/op/activity-profiles.d.ts.map +1 -0
  190. package/dist/op/activity-registry.d.ts +22 -38
  191. package/dist/op/activity-registry.d.ts.map +1 -1
  192. package/dist/op/activity-runtime.d.ts +3 -14
  193. package/dist/op/activity-runtime.d.ts.map +1 -1
  194. package/dist/op/builders.d.ts +85 -30
  195. package/dist/op/builders.d.ts.map +1 -1
  196. package/dist/op/change-signal.d.ts +91 -0
  197. package/dist/op/change-signal.d.ts.map +1 -0
  198. package/dist/op/composites/apply-op.d.ts +118 -0
  199. package/dist/op/composites/apply-op.d.ts.map +1 -0
  200. package/dist/op/composites/converge-op.d.ts +120 -0
  201. package/dist/op/composites/converge-op.d.ts.map +1 -0
  202. package/dist/op/composites/index.d.ts +26 -0
  203. package/dist/op/composites/index.d.ts.map +1 -0
  204. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  205. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  206. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  207. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  208. package/dist/op/composites/reconcile-op.d.ts +57 -0
  209. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  210. package/dist/op/composites/watch-op.d.ts +60 -0
  211. package/dist/op/composites/watch-op.d.ts.map +1 -0
  212. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  213. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  214. package/dist/op/converge-rule.d.ts +12 -10
  215. package/dist/op/converge-rule.d.ts.map +1 -1
  216. package/dist/op/cron.d.ts +51 -0
  217. package/dist/op/cron.d.ts.map +1 -0
  218. package/dist/op/discover.d.ts +9 -0
  219. package/dist/op/discover.d.ts.map +1 -1
  220. package/dist/op/duration.d.ts +11 -0
  221. package/dist/op/duration.d.ts.map +1 -0
  222. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  223. package/dist/op/gate-name.d.ts +40 -0
  224. package/dist/op/gate-name.d.ts.map +1 -0
  225. package/dist/op/gate-summary.d.ts +43 -0
  226. package/dist/op/gate-summary.d.ts.map +1 -0
  227. package/dist/op/gate.d.ts +90 -0
  228. package/dist/op/gate.d.ts.map +1 -0
  229. package/dist/op/generate-pipeline.d.ts +9 -0
  230. package/dist/op/generate-pipeline.d.ts.map +1 -1
  231. package/dist/op/index.d.ts +29 -9
  232. package/dist/op/index.d.ts.map +1 -1
  233. package/dist/op/local-executor.d.ts +114 -28
  234. package/dist/op/local-executor.d.ts.map +1 -1
  235. package/dist/op/local-output.d.ts +11 -1
  236. package/dist/op/local-output.d.ts.map +1 -1
  237. package/dist/op/op-ir.d.ts +185 -0
  238. package/dist/op/op-ir.d.ts.map +1 -0
  239. package/dist/op/op-verb-class.d.ts +10 -2
  240. package/dist/op/op-verb-class.d.ts.map +1 -1
  241. package/dist/op/operator.d.ts +93 -5
  242. package/dist/op/operator.d.ts.map +1 -1
  243. package/dist/op/receipt-store.d.ts +1 -1
  244. package/dist/op/receipt-store.d.ts.map +1 -1
  245. package/dist/op/resource.d.ts +15 -1
  246. package/dist/op/resource.d.ts.map +1 -1
  247. package/dist/op/runtime.d.ts +200 -0
  248. package/dist/op/runtime.d.ts.map +1 -0
  249. package/dist/op/runtimes/local.d.ts +29 -0
  250. package/dist/op/runtimes/local.d.ts.map +1 -0
  251. package/dist/op/step-output-ref.d.ts +15 -13
  252. package/dist/op/step-output-ref.d.ts.map +1 -1
  253. package/dist/op/types.d.ts +96 -29
  254. package/dist/op/types.d.ts.map +1 -1
  255. package/dist/ownership.d.ts +1 -1
  256. package/dist/provenance.d.ts +21 -0
  257. package/dist/provenance.d.ts.map +1 -1
  258. package/dist/serializer-walker.d.ts.map +1 -1
  259. package/dist/terraform/bridge.d.ts +26 -7
  260. package/dist/terraform/bridge.d.ts.map +1 -1
  261. package/dist/terraform/carve-provider.d.ts +28 -2
  262. package/dist/terraform/carve-provider.d.ts.map +1 -1
  263. package/dist/terraform/data-source-shape.d.ts +77 -0
  264. package/dist/terraform/data-source-shape.d.ts.map +1 -0
  265. package/dist/terraform/graph.d.ts.map +1 -1
  266. package/dist/terraform/providers/kubernetes.d.ts +5 -0
  267. package/dist/terraform/providers/kubernetes.d.ts.map +1 -1
  268. package/dist/terraform/tier-map.d.ts +16 -4
  269. package/dist/terraform/tier-map.d.ts.map +1 -1
  270. package/dist/terraform/types.d.ts +8 -0
  271. package/dist/terraform/types.d.ts.map +1 -1
  272. package/package.json +6 -1
  273. package/src/audit/catalog.test.ts +79 -3
  274. package/src/audit/catalog.ts +111 -13
  275. package/src/audit/core.test.ts +26 -0
  276. package/src/audit/core.ts +84 -18
  277. package/src/audit/discover.test.ts +39 -0
  278. package/src/audit/discover.ts +202 -18
  279. package/src/audit/lineage.ts +100 -0
  280. package/src/audit/prior-art.ts +153 -0
  281. package/src/audit/proof.test.ts +67 -0
  282. package/src/audit/proof.ts +70 -0
  283. package/src/audit/report-html.ts +9 -4
  284. package/src/audit/report-model.ts +16 -2
  285. package/src/audit/report.test.ts +33 -0
  286. package/src/audit/report.ts +5 -3
  287. package/src/audit/rules-doc.test.ts +34 -2
  288. package/src/audit/rules-doc.ts +82 -9
  289. package/src/audit/secrets.ts +15 -3
  290. package/src/audit/terraform-state.test.ts +144 -0
  291. package/src/audit/terraform-state.ts +131 -0
  292. package/src/build.ts +31 -1
  293. package/src/claimed-fields.test.ts +145 -0
  294. package/src/claimed-fields.ts +208 -0
  295. package/src/cli/build-params-cli.ts +2 -2
  296. package/src/cli/command-group.ts +14 -0
  297. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  298. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  299. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  300. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  301. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  302. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  303. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  304. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  305. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  306. package/src/cli/commands/audit.test.ts +191 -11
  307. package/src/cli/commands/audit.ts +78 -28
  308. package/src/cli/commands/build.test.ts +330 -9
  309. package/src/cli/commands/build.ts +170 -24
  310. package/src/cli/commands/carve-bridge.test.ts +237 -14
  311. package/src/cli/commands/carve-bridge.ts +21 -17
  312. package/src/cli/commands/carve-emit-k8s.test.ts +17 -10
  313. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  314. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  315. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  316. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  317. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  318. package/src/cli/commands/init-lexicon.test.ts +97 -2
  319. package/src/cli/commands/init-lexicon.ts +4 -2
  320. package/src/cli/commands/init.test.ts +35 -1
  321. package/src/cli/commands/init.ts +14 -3
  322. package/src/cli/commands/lint.test.ts +194 -1
  323. package/src/cli/commands/lint.ts +205 -7
  324. package/src/cli/commands/onboard.test.ts +75 -0
  325. package/src/cli/commands/onboard.ts +54 -23
  326. package/src/cli/handlers/build.test.ts +81 -1
  327. package/src/cli/handlers/build.ts +15 -1
  328. package/src/cli/handlers/graph.test.ts +3 -3
  329. package/src/cli/handlers/lifecycle.test.ts +195 -12
  330. package/src/cli/handlers/lifecycle.ts +123 -6
  331. package/src/cli/handlers/misc.ts +1 -1
  332. package/src/cli/handlers/operator.test.ts +183 -11
  333. package/src/cli/handlers/operator.ts +341 -55
  334. package/src/cli/handlers/run.test.ts +568 -1295
  335. package/src/cli/handlers/run.ts +446 -912
  336. package/src/cli/main.test.ts +22 -16
  337. package/src/cli/main.ts +66 -33
  338. package/src/cli/mcp/op-tools.ts +147 -88
  339. package/src/cli/mcp/resource-handlers.ts +10 -37
  340. package/src/cli/mcp/resources/context.ts +11 -12
  341. package/src/cli/mcp/server.test.ts +25 -27
  342. package/src/cli/mcp/server.ts +2 -2
  343. package/src/cli/plugins.test.ts +68 -2
  344. package/src/cli/plugins.ts +39 -0
  345. package/src/cli/registry.ts +40 -9
  346. package/src/codegen/docs.ts +1 -1
  347. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  348. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  349. package/src/components/README.md +4 -3
  350. package/src/components/__fixtures__/neo4j-fanout.json +1 -1
  351. package/src/components/auto-release.test.ts +4 -20
  352. package/src/components/auto-release.ts +17 -42
  353. package/src/components/capability.ts +4 -4
  354. package/src/components/cli-support.test.ts +28 -12
  355. package/src/components/cli-support.ts +60 -47
  356. package/src/components/component-schema.test.ts +18 -2
  357. package/src/components/component.schema.json +18 -5
  358. package/src/components/component.test.ts +2 -2
  359. package/src/components/component.ts +27 -7
  360. package/src/components/config-defaults.test.ts +2 -2
  361. package/src/components/driver-output.ts +14 -2
  362. package/src/components/driver.test.ts +109 -20
  363. package/src/components/driver.ts +201 -84
  364. package/src/components/index.ts +1 -6
  365. package/src/components/manifest-persistence.test.ts +2 -20
  366. package/src/components/manifest-persistence.ts +4 -24
  367. package/src/components/pilots/neo4j-fanout.pilot.ts +3 -3
  368. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  369. package/src/components/run-progress.ts +6 -6
  370. package/src/components/verbs/run-agent.test.ts +19 -0
  371. package/src/components/verbs/run-agent.ts +12 -24
  372. package/src/components/verbs/verify.ts +2 -2
  373. package/src/deep-observation.test.ts +75 -0
  374. package/src/deep-observation.ts +48 -0
  375. package/src/detectLexicon.ts +18 -1
  376. package/src/discovery/collect.test.ts +3 -3
  377. package/src/discovery/files.ts +4 -4
  378. package/src/discovery/fold-import.test.ts +1 -1
  379. package/src/discovery/fold-import.ts +105 -2
  380. package/src/discovery/param-deps.test.ts +112 -1
  381. package/src/discovery/param-deps.ts +193 -0
  382. package/src/discovery/sandbox/bundle.ts +15 -1
  383. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  384. package/src/discovery/sandbox/config-wire.ts +2 -2
  385. package/src/fold/fold.test.ts +56 -0
  386. package/src/fold/foldable-helpers.ts +82 -2
  387. package/src/fold-provenance-exclusion.test.ts +186 -0
  388. package/src/fold-provenance.test.ts +495 -0
  389. package/src/fold-provenance.ts +441 -0
  390. package/src/graph-ops.test.ts +3 -3
  391. package/src/graph-ops.ts +1 -1
  392. package/src/held-elsewhere.test.ts +102 -0
  393. package/src/held-elsewhere.ts +114 -0
  394. package/src/index.ts +3 -0
  395. package/src/kubectl-context.ts +3 -3
  396. package/src/lexicon-config.test.ts +5 -5
  397. package/src/lexicon-config.ts +4 -4
  398. package/src/lexicon-plugin-helpers.ts +1 -1
  399. package/src/lexicon.ts +296 -16
  400. package/src/lifecycle/change-set.test.ts +49 -0
  401. package/src/lifecycle/change-set.ts +67 -0
  402. package/src/lifecycle/converge-ledger.ts +1 -1
  403. package/src/lifecycle/deep-diff.test.ts +267 -14
  404. package/src/lifecycle/deep-diff.ts +217 -14
  405. package/src/lifecycle/deep-observe.test.ts +3 -1
  406. package/src/lifecycle/deep-observe.ts +16 -6
  407. package/src/lifecycle/gate-ledger.test.ts +74 -2
  408. package/src/lifecycle/gate-ledger.ts +154 -36
  409. package/src/lifecycle/index.ts +1 -0
  410. package/src/lifecycle/release-ledger.ts +2 -2
  411. package/src/lifecycle/run-ledger.test.ts +268 -0
  412. package/src/lifecycle/run-ledger.ts +201 -0
  413. package/src/lifecycle/symptoms.ts +3 -3
  414. package/src/lint/config.test.ts +82 -1
  415. package/src/lint/config.ts +112 -3
  416. package/src/lint/pipeline-change-gate.test.ts +2 -2
  417. package/src/lint/policy.test.ts +1 -1
  418. package/src/lint/post-synth.test.ts +31 -0
  419. package/src/lint/post-synth.ts +54 -1
  420. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  421. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  422. package/src/lint/rules/comp/comp.test.ts +27 -1
  423. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +76 -0
  424. package/src/lint/rules/comp/index.ts +3 -3
  425. package/src/lint/rules/op/index.ts +23 -0
  426. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  427. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  428. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  429. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  430. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  431. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  432. package/src/lint/rules/op/support.ts +11 -0
  433. package/src/lint/suppressions.test.ts +163 -0
  434. package/src/lint/suppressions.ts +204 -0
  435. package/src/live-endpoint.ts +1 -1
  436. package/src/op/activities/activity-contracts.ts +66 -0
  437. package/src/op/activities/apply.test.ts +567 -0
  438. package/src/op/activities/apply.ts +662 -0
  439. package/src/op/activities/build.ts +26 -0
  440. package/src/op/activities/converge.test.ts +330 -0
  441. package/src/op/activities/converge.ts +449 -0
  442. package/src/op/activities/env-teardown.test.ts +187 -0
  443. package/src/op/activities/env-teardown.ts +171 -0
  444. package/src/op/activities/guard-validate.test.ts +139 -0
  445. package/src/op/activities/guard-validate.ts +223 -0
  446. package/src/op/activities/http-check.test.ts +48 -0
  447. package/src/op/activities/http-check.ts +55 -0
  448. package/src/op/activities/index.ts +119 -0
  449. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  450. package/src/op/activities/lexicon-upgrade.ts +673 -0
  451. package/src/op/activities/lifecycle.ts +85 -0
  452. package/src/op/activities/pipeline-audit.test.ts +67 -0
  453. package/src/op/activities/pipeline-audit.ts +201 -0
  454. package/src/op/activities/policy.test.ts +19 -0
  455. package/src/op/activities/policy.ts +37 -0
  456. package/src/op/activities/reconcile.test.ts +161 -0
  457. package/src/op/activities/reconcile.ts +354 -0
  458. package/src/op/activities/shell.ts +26 -0
  459. package/src/op/activities/teardown.ts +22 -0
  460. package/src/op/activities/util.ts +6 -0
  461. package/src/op/activities/wait.ts +69 -0
  462. package/src/op/activities/workflow-audit.test.ts +90 -0
  463. package/src/op/activities/workflow-audit.ts +203 -0
  464. package/src/op/activity-contract-registry.test.ts +98 -0
  465. package/src/op/activity-contract-registry.ts +114 -0
  466. package/src/op/activity-contract.test.ts +1 -1
  467. package/src/op/activity-contract.ts +37 -33
  468. package/src/op/activity-failure.ts +34 -0
  469. package/src/op/activity-profiles.test.ts +56 -0
  470. package/src/op/activity-profiles.ts +116 -0
  471. package/src/op/activity-registry.test.ts +37 -28
  472. package/src/op/activity-registry.ts +27 -56
  473. package/src/op/activity-runtime.ts +3 -47
  474. package/src/op/builders-exports.test.ts +0 -49
  475. package/src/op/builders-typed.test.ts +164 -0
  476. package/src/op/builders.ts +125 -41
  477. package/src/op/change-signal.test.ts +117 -0
  478. package/src/op/change-signal.ts +169 -0
  479. package/src/op/composites/apply-op.ts +218 -0
  480. package/src/op/composites/composites.test.ts +379 -0
  481. package/src/op/composites/converge-op.test.ts +168 -0
  482. package/src/op/composites/converge-op.ts +214 -0
  483. package/src/op/composites/index.ts +26 -0
  484. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  485. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  486. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  487. package/src/op/composites/pipeline-audit-op.ts +78 -0
  488. package/src/op/composites/reconcile-op.test.ts +51 -0
  489. package/src/op/composites/reconcile-op.ts +110 -0
  490. package/src/op/composites/watch-op.ts +108 -0
  491. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  492. package/src/op/composites/workflow-audit-op.ts +88 -0
  493. package/src/op/converge-rule.ts +12 -10
  494. package/src/op/cron.test.ts +128 -0
  495. package/src/op/cron.ts +149 -0
  496. package/src/op/discover-root.test.ts +105 -1
  497. package/src/op/discover.test.ts +6 -2
  498. package/src/op/discover.ts +84 -16
  499. package/src/op/duration.ts +21 -0
  500. package/src/op/effect-step.test.ts +29 -14
  501. package/src/op/emulator-lifecycle.ts +1 -2
  502. package/src/op/gate-name.test.ts +65 -0
  503. package/src/op/gate-name.ts +60 -0
  504. package/src/op/gate-summary.ts +84 -0
  505. package/src/op/gate.ts +155 -0
  506. package/src/op/generate-pipeline.test.ts +65 -3
  507. package/src/op/generate-pipeline.ts +19 -2
  508. package/src/op/index.ts +48 -8
  509. package/src/op/local-executor.test.ts +178 -34
  510. package/src/op/local-executor.ts +371 -102
  511. package/src/op/local-output.test.ts +95 -11
  512. package/src/op/local-output.ts +33 -4
  513. package/src/op/op-ir.test.ts +292 -0
  514. package/src/op/op-ir.ts +419 -0
  515. package/src/op/op-verb-class.test.ts +2 -2
  516. package/src/op/op-verb-class.ts +19 -5
  517. package/src/op/op.test.ts +28 -7
  518. package/src/op/operator.test.ts +543 -6
  519. package/src/op/operator.ts +203 -20
  520. package/src/op/receipt-store.ts +1 -1
  521. package/src/op/resource.ts +20 -2
  522. package/src/op/runtime.ts +203 -0
  523. package/src/op/runtimes/local.test.ts +181 -0
  524. package/src/op/runtimes/local.ts +212 -0
  525. package/src/op/step-output-ref.ts +15 -13
  526. package/src/op/types.ts +106 -26
  527. package/src/ownership.ts +1 -1
  528. package/src/provenance.test.ts +6 -0
  529. package/src/provenance.ts +21 -1
  530. package/src/serializer-walker.test.ts +42 -0
  531. package/src/serializer-walker.ts +21 -2
  532. package/src/terraform/aws-resources.test.ts +13 -4
  533. package/src/terraform/bridge.test.ts +22 -9
  534. package/src/terraform/bridge.ts +89 -28
  535. package/src/terraform/carve-provider.ts +38 -2
  536. package/src/terraform/data-source-shape.ts +95 -0
  537. package/src/terraform/graph.ts +35 -7
  538. package/src/terraform/providers/kubernetes.ts +48 -2
  539. package/src/terraform/tier-map.ts +21 -6
  540. package/src/terraform/types.ts +8 -0
  541. package/dist/cli/handlers/op-progress.d.ts +0 -90
  542. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  543. package/dist/cli/handlers/run-client.d.ts +0 -127
  544. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  545. package/dist/cli/handlers/run-report.d.ts +0 -5
  546. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  547. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  548. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  549. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  550. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  551. package/src/cli/handlers/op-progress.test.ts +0 -268
  552. package/src/cli/handlers/op-progress.ts +0 -248
  553. package/src/cli/handlers/run-client.test.ts +0 -82
  554. package/src/cli/handlers/run-client.ts +0 -219
  555. package/src/cli/handlers/run-report.test.ts +0 -62
  556. package/src/cli/handlers/run-report.ts +0 -122
  557. package/src/components/temporal-codegen-loader.ts +0 -41
  558. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -0,0 +1,662 @@
1
+ /**
2
+ * `nativeApply` — push declared source to the cloud through the target's own
3
+ * mechanism. Authority stays with the platform; chant hosts no state file.
4
+ *
5
+ * ## Where the shell went (chant #1075, #1448, #1449)
6
+ *
7
+ * This used to build a shell command for every target — `kubectl apply -f`,
8
+ * `az deployment group create`, `aws cloudformation deploy`. Two things were
9
+ * wrong with that. The shell commands carried product knowledge that belongs to
10
+ * each product's lexicon, against the one-lexicon-per-product rule that already
11
+ * moved `kubectlApply`, `k3dUp`/`k3dDown` and `waitForArgoSync` out (chant
12
+ * #809). And each CLI's semantics diverged from what the docblocks promised —
13
+ * `kubectl apply`'s client-side merge gave the diff engine nothing to key on
14
+ * (#1075), and ARM Complete mode deleted resources chant never applied (#1448).
15
+ *
16
+ * So each branch moved to its product's lexicon: `kubectl`/`kustomize` are a
17
+ * server-side apply over the k8s lexicon's typed client (#1075, #1548), `arm`
18
+ * is the azure lexicon's per-resource `azApply` (#1448), `cloudformation`
19
+ * is the aws lexicon's `awsApply` — the CloudFormation Query API directly, no
20
+ * CLI in the path (#1449) — and `gcp`/`fly` are the gcp lexicon's
21
+ * per-resource `gcpApply` and the fly lexicon's `flyApply`, which never had a
22
+ * CLI in the path to begin with: gcp maps each CNRM kind to its REST API
23
+ * itself, and fly speaks the Machines API (flaps) directly, no flyctl.
24
+ * **The dispatcher stayed here**, because "which
25
+ * mechanism applies this target" is not any one product's knowledge — and
26
+ * because the activity keeps its name, its arguments and its place in
27
+ * `ApplyOp`, so no existing Op changes shape.
28
+ *
29
+ * The lexicons are reached by dynamic import at call time, never by a static
30
+ * one: this package must not depend on them. A project applying a target
31
+ * already lists that lexicon in its config, so the module is there; when it is
32
+ * not, the failure names the package to install.
33
+ */
34
+
35
+ import { exec } from "node:child_process";
36
+ import { promisify } from "node:util";
37
+ import { normalizeApply, type ApplyResult } from "../../apply";
38
+
39
+ const execAsync = promisify(exec);
40
+
41
+ /** The native apply mechanism for a target. */
42
+ export type ApplyTarget = "cloudformation" | "kubectl" | "arm" | "kustomize" | "gcp" | "fly";
43
+
44
+ /**
45
+ * How apply treats resources no longer declared.
46
+ * - `never` — additive only; never deletes.
47
+ * - `owned-only` — enables the target's own delete path. What bounds that path
48
+ * differs per target, and all of them are genuinely owned-only: `kubectl`
49
+ * sweeps by the ownership marker, `arm` prunes by the ownership tag
50
+ * (`isChantOwned`, via the azure lexicon's `azApply`), `gcp` prunes by the
51
+ * ownership label (via the gcp lexicon's `gcpApply` — only kinds it can
52
+ * list; the rest are reported not-prunable), `fly` prunes machines by the
53
+ * metadata marker and the metadata-less types (volumes/ips/certs/secrets)
54
+ * app-scoped under a managed app (via the fly lexicon's `flyApply`), and
55
+ * `cloudformation` is bounded by the stack — which holds, because a
56
+ * resource CFN did not create is not in the stack.
57
+ * - `gated` — same delete scope as `owned-only`, but an approval gate precedes
58
+ * the destructive apply, so an unapproved run ends `gated` before deleting
59
+ * anything (the gate lives in the composite).
60
+ */
61
+ export type DeleteMode = "never" | "owned-only" | "gated";
62
+
63
+ export interface NativeApplyArgs {
64
+ /** Native mechanism to delegate to. */
65
+ target: ApplyTarget;
66
+ /** Environment. What it means is per target: the CFN stack name on
67
+ * `cloudformation`, the ARM resource group on `arm`, the chant environment
68
+ * on `kubectl`/`kustomize`. On `gcp` and `fly` it is a log label only — the
69
+ * gcp applier resolves the project (`GOOGLE_CLOUD_PROJECT` env / CNRM
70
+ * annotation) and endpoint (`GCP_ENDPOINT_URL` env) itself, and the fly
71
+ * applier resolves its endpoint (`FLY_FLAPS_BASE_URL` env) and token
72
+ * (`FLY_API_TOKEN` env) itself, with the app names coming from the plan. */
73
+ env: string;
74
+ /** Built manifest/template path. Default per target ({@link defaultOutput}):
75
+ * `dist` (a dir) for kubectl, `template.json` (a file) for
76
+ * CloudFormation/ARM, `dist/gcp.yaml` for gcp, `dist/fly.json` for fly. */
77
+ output?: string;
78
+ /** Delete handling. Default: never. */
79
+ deleteMode?: DeleteMode;
80
+ /**
81
+ * kubectl target only (chant #1075). Take ownership of fields another field
82
+ * manager owns instead of failing with a conflict that names them.
83
+ * **Opt-in, and never defaulted on**: transferring ownership of a live field
84
+ * is a decision, not a retry.
85
+ */
86
+ forceConflicts?: boolean;
87
+ }
88
+
89
+ /**
90
+ * What an apply did — one shape for every target: the count projection of
91
+ * core's `NormalizedApply` (#1446, collapsed here in #1449). The per-target
92
+ * shapes this used to carry (`fieldManager`, `stackName`/`status`/`action`,
93
+ * a separate `notPrunable`) belong to the appliers and stay in their lexicons;
94
+ * this activity's result is the shape every Op reads back regardless of
95
+ * target, and the target-specific detail still reaches the operator on the
96
+ * activity log.
97
+ */
98
+ export interface NativeApplyResult {
99
+ /** Resources the provider was called for and which converged — created,
100
+ * updated or unchanged. On `cloudformation` the unit is the stack, so a
101
+ * settled deploy is `1`. */
102
+ applied: number;
103
+ /** Owned, no-longer-declared resources deleted. */
104
+ pruned: number;
105
+ /** Declared resources no provider call was made for (#1447), including
106
+ * kinds an owned-only prune could not consider (`not-prunable`). Zero on a
107
+ * complete apply. */
108
+ notAttempted: number;
109
+ }
110
+
111
+ /**
112
+ * The k8s lexicon's server-side apply, as this module needs to call it.
113
+ * Structural, so nothing here imports the k8s lexicon's types.
114
+ */
115
+ export type K8sApplier = (
116
+ args: {
117
+ manifest: string;
118
+ /** Already-rendered documents (#1548) — the kustomize target hands the
119
+ * render straight in; `manifest` is then only the log label. */
120
+ documents?: Array<Record<string, unknown>>;
121
+ environment?: string;
122
+ deleteMode?: DeleteMode;
123
+ force?: boolean;
124
+ },
125
+ signal?: AbortSignal,
126
+ ) => Promise<{ applied: unknown[]; pruned: unknown[]; fieldManager: string }>;
127
+
128
+ /**
129
+ * The azure lexicon's per-resource ARM applier, as this module needs to call
130
+ * it: `azApply` composed with the lexicon's own `toApplyResult` projection, so
131
+ * what crosses this seam is core's versioned apply envelope (#1446) and
132
+ * nothing ARM-shaped.
133
+ */
134
+ export type AzureApplier = (
135
+ args: {
136
+ templatePath: string;
137
+ resourceGroup: string;
138
+ endpoint?: string;
139
+ prune?: boolean;
140
+ },
141
+ signal?: AbortSignal,
142
+ ) => Promise<ApplyResult>;
143
+
144
+ /**
145
+ * The gcp lexicon's per-resource applier, as this module needs to call it
146
+ * (#1449): `gcpApply` composed with the lexicon's own `toApplyResult`
147
+ * projection, so what crosses this seam is core's versioned apply envelope
148
+ * (#1446) — the skips of #1447 ride it as NOT-ATTEMPTED entries, and a kind
149
+ * the prune could not consider rides it as `not-prunable`.
150
+ *
151
+ * Deliberately narrow: no `endpoint`, because `gcpApply` resolves
152
+ * `GCP_ENDPOINT_URL` itself — the same variable gcp's read path honours, so an
153
+ * apply lands wherever `--live` is already looking (floci-gcp, or real GCP
154
+ * when unset); and no `project`, because `gcpApply` resolves
155
+ * `GOOGLE_CLOUD_PROJECT` / the CNRM project-id annotation itself.
156
+ */
157
+ export type GcpApplier = (
158
+ args: {
159
+ manifestPath: string;
160
+ prune?: boolean;
161
+ },
162
+ signal?: AbortSignal,
163
+ ) => Promise<ApplyResult>;
164
+
165
+ /**
166
+ * The fly lexicon's flaps applier, as this module needs to call it (#1449):
167
+ * `flyApply` composed with the lexicon's own `toApplyResult` projection. The
168
+ * eleven arrays flyApply returns — six entity classes applied, five pruned —
169
+ * are its own contract and stay in the fly lexicon; what crosses this seam is
170
+ * core's versioned apply envelope (#1446).
171
+ *
172
+ * Deliberately narrow: no `endpoint`, because `flyApply` resolves
173
+ * `FLY_FLAPS_BASE_URL` itself — mudflaps locally, real Fly when unset; and no
174
+ * `token`, because it resolves `FLY_API_TOKEN` itself.
175
+ */
176
+ export type FlyApplier = (
177
+ args: {
178
+ planPath: string;
179
+ prune?: boolean;
180
+ },
181
+ signal?: AbortSignal,
182
+ ) => Promise<ApplyResult>;
183
+
184
+ /**
185
+ * The aws lexicon's CloudFormation applier, as this module needs to call it
186
+ * (#1449). Structural, like {@link K8sApplier} and {@link AzureApplier}.
187
+ *
188
+ * Deliberately narrow: no `endpoint`, because `awsApply` resolves
189
+ * `AWS_ENDPOINT_URL_CLOUDFORMATION` then `AWS_ENDPOINT_URL` itself (#1694) —
190
+ * the rule that used to live here as `applyEndpoint` (#926); and no
191
+ * `capabilities`, because `awsApply` derives them from the template body
192
+ * (`CAPABILITY_NAMED_IAM`, plus `CAPABILITY_AUTO_EXPAND` for a top-level
193
+ * `Transform` — #980), the rule that used to live here as `cfnCapabilities`.
194
+ */
195
+ export type AwsApplier = (
196
+ args: { templatePath: string; stackName: string },
197
+ signal?: AbortSignal,
198
+ ) => Promise<{ stackName: string; status: string; action: "created" | "updated" | "unchanged" }>;
199
+
200
+ /**
201
+ * The aws lexicon's CloudFormation rollback (saga compensation), as
202
+ * {@link compensateApply} needs to call it. Structural, like the appliers.
203
+ */
204
+ export type AwsRollback = (
205
+ args: { stackName: string },
206
+ signal?: AbortSignal,
207
+ ) => Promise<{ stackName: string; rolledBack: boolean; status?: string }>;
208
+
209
+ /**
210
+ * Render a kustomization directory to parsed documents (#1548): `kustomize
211
+ * build`, falling back to kubectl's vendored kustomize when the standalone
212
+ * binary is absent. The 64MiB buffer matches the k8s/helm lexicons' bound —
213
+ * a big overlay renders megabytes. YAML parsing is js-yaml's multi-doc
214
+ * loader, the same one the k8s applier uses on files.
215
+ */
216
+ async function renderKustomization(dir: string): Promise<Array<Record<string, unknown>>> {
217
+ const quoted = `'${dir.replace(/'/g, "'\\''")}'`;
218
+ const run = (cmd: string) => execAsync(cmd, { maxBuffer: 64 * 1024 * 1024 });
219
+ let stdout: string;
220
+ try {
221
+ ({ stdout } = await run(`kustomize build ${quoted}`));
222
+ } catch (err) {
223
+ const message = err instanceof Error ? err.message : String(err);
224
+ if (!/ENOENT|not found|command not found|127/.test(message)) throw err;
225
+ ({ stdout } = await run(`kubectl kustomize ${quoted}`));
226
+ }
227
+ const { loadAll } = await import("js-yaml");
228
+ const documents: Array<Record<string, unknown>> = [];
229
+ for (const doc of loadAll(stdout)) {
230
+ if (doc && typeof doc === "object" && !Array.isArray(doc)) documents.push(doc as Record<string, unknown>);
231
+ }
232
+ return documents;
233
+ }
234
+
235
+ /**
236
+ * Load the k8s lexicon's apply. A variable specifier, so `tsc` does not
237
+ * statically resolve a package this one deliberately does not depend on — the
238
+ * same mechanism core's activity registry uses to load a lexicon's activities.
239
+ */
240
+ async function loadK8sApplier(): Promise<K8sApplier> {
241
+ const spec = "@intentius/chant-lexicon-k8s/op/activities";
242
+ let mod: { applyManifest?: K8sApplier };
243
+ try {
244
+ mod = (await import(spec)) as { applyManifest?: K8sApplier };
245
+ } catch (err) {
246
+ throw new Error(
247
+ `apply target "kubectl" needs @intentius/chant-lexicon-k8s, which could not be loaded ` +
248
+ `(${err instanceof Error ? err.message : String(err)}). Kubernetes applies moved out of the ` +
249
+ `op lexicon in chant #1075; install the k8s lexicon and list it in chant.config.ts.`,
250
+ );
251
+ }
252
+ if (typeof mod.applyManifest !== "function") {
253
+ throw new Error(
254
+ "the installed @intentius/chant-lexicon-k8s exports no applyManifest — it predates chant #1075",
255
+ );
256
+ }
257
+ return mod.applyManifest;
258
+ }
259
+
260
+ /**
261
+ * Load the azure lexicon's `azApply` (#1448). Same variable-specifier trick as
262
+ * {@link loadK8sApplier}, for the same reason.
263
+ */
264
+ async function loadAzureApplier(): Promise<AzureApplier> {
265
+ const spec = "@intentius/chant-lexicon-azure/op/activities";
266
+ type AzureModule = {
267
+ azApply?: (args: Parameters<AzureApplier>[0], signal?: AbortSignal) => Promise<unknown>;
268
+ toApplyResult?: (result: unknown) => ApplyResult;
269
+ };
270
+ let mod: AzureModule;
271
+ try {
272
+ mod = (await import(spec)) as AzureModule;
273
+ } catch (err) {
274
+ throw new Error(
275
+ `apply target "arm" needs @intentius/chant-lexicon-azure, which could not be loaded ` +
276
+ `(${err instanceof Error ? err.message : String(err)}). ARM applies go through the azure ` +
277
+ `lexicon's per-resource applier since chant #1448; install the azure lexicon and list it ` +
278
+ `in chant.config.ts.`,
279
+ );
280
+ }
281
+ const { azApply, toApplyResult } = mod;
282
+ if (typeof azApply !== "function") {
283
+ throw new Error(
284
+ "the installed @intentius/chant-lexicon-azure exports no azApply — it predates chant #707",
285
+ );
286
+ }
287
+ if (typeof toApplyResult !== "function") {
288
+ throw new Error(
289
+ "the installed @intentius/chant-lexicon-azure exports no toApplyResult — it predates chant #1449",
290
+ );
291
+ }
292
+ return async (args, signal) => toApplyResult(await azApply(args, signal));
293
+ }
294
+
295
+ /**
296
+ * Load the gcp lexicon's `gcpApply` (#1449). Same variable-specifier trick as
297
+ * {@link loadK8sApplier}, for the same reason.
298
+ */
299
+ async function loadGcpApplier(): Promise<GcpApplier> {
300
+ const spec = "@intentius/chant-lexicon-gcp/op/activities";
301
+ type GcpModule = {
302
+ gcpApply?: (args: Parameters<GcpApplier>[0], signal?: AbortSignal) => Promise<unknown>;
303
+ toApplyResult?: (result: unknown) => ApplyResult;
304
+ };
305
+ let mod: GcpModule;
306
+ try {
307
+ mod = (await import(spec)) as GcpModule;
308
+ } catch (err) {
309
+ throw new Error(
310
+ `apply target "gcp" needs @intentius/chant-lexicon-gcp, which could not be loaded ` +
311
+ `(${err instanceof Error ? err.message : String(err)}). GCP applies go through the gcp ` +
312
+ `lexicon's native applier since chant #1449; install the gcp lexicon and list it ` +
313
+ `in chant.config.ts.`,
314
+ );
315
+ }
316
+ const { gcpApply, toApplyResult } = mod;
317
+ if (typeof gcpApply !== "function") {
318
+ throw new Error(
319
+ "the installed @intentius/chant-lexicon-gcp exports no gcpApply — it predates chant #706",
320
+ );
321
+ }
322
+ if (typeof toApplyResult !== "function") {
323
+ throw new Error(
324
+ "the installed @intentius/chant-lexicon-gcp exports no toApplyResult — it predates chant #1449",
325
+ );
326
+ }
327
+ return async (args, signal) => toApplyResult(await gcpApply(args, signal));
328
+ }
329
+
330
+ /**
331
+ * Load the fly lexicon's `flyApply` (#1449). Same variable-specifier trick as
332
+ * {@link loadK8sApplier}, for the same reason.
333
+ */
334
+ async function loadFlyApplier(): Promise<FlyApplier> {
335
+ const spec = "@intentius/chant-lexicon-fly/op/activities";
336
+ type FlyModule = {
337
+ flyApply?: (args: Parameters<FlyApplier>[0], signal?: AbortSignal) => Promise<unknown>;
338
+ toApplyResult?: (result: unknown) => ApplyResult;
339
+ };
340
+ let mod: FlyModule;
341
+ try {
342
+ mod = (await import(spec)) as FlyModule;
343
+ } catch (err) {
344
+ throw new Error(
345
+ `apply target "fly" needs @intentius/chant-lexicon-fly, which could not be loaded ` +
346
+ `(${err instanceof Error ? err.message : String(err)}). Fly applies go through the fly ` +
347
+ `lexicon's native flaps applier since chant #1449; install the fly lexicon and list it ` +
348
+ `in chant.config.ts.`,
349
+ );
350
+ }
351
+ const { flyApply, toApplyResult } = mod;
352
+ if (typeof flyApply !== "function") {
353
+ throw new Error(
354
+ "the installed @intentius/chant-lexicon-fly exports no flyApply — it predates chant #739",
355
+ );
356
+ }
357
+ if (typeof toApplyResult !== "function") {
358
+ throw new Error(
359
+ "the installed @intentius/chant-lexicon-fly exports no toApplyResult — it predates chant #1449",
360
+ );
361
+ }
362
+ return async (args, signal) => toApplyResult(await flyApply(args, signal));
363
+ }
364
+
365
+ /**
366
+ * Load the aws lexicon's `awsApply` (#1449). Same variable-specifier trick as
367
+ * {@link loadK8sApplier}, for the same reason.
368
+ */
369
+ async function loadAwsApplier(): Promise<AwsApplier> {
370
+ const spec = "@intentius/chant-lexicon-aws/op/activities";
371
+ let mod: { awsApply?: AwsApplier };
372
+ try {
373
+ mod = (await import(spec)) as { awsApply?: AwsApplier };
374
+ } catch (err) {
375
+ throw new Error(
376
+ `apply target "cloudformation" needs @intentius/chant-lexicon-aws, which could not be loaded ` +
377
+ `(${err instanceof Error ? err.message : String(err)}). CloudFormation applies go through the ` +
378
+ `aws lexicon's native applier since chant #1449; install the aws lexicon and list it ` +
379
+ `in chant.config.ts.`,
380
+ );
381
+ }
382
+ if (typeof mod.awsApply !== "function") {
383
+ throw new Error(
384
+ "the installed @intentius/chant-lexicon-aws exports no awsApply — it predates chant #1446",
385
+ );
386
+ }
387
+ return mod.awsApply;
388
+ }
389
+
390
+ /**
391
+ * Load the aws lexicon's `rollbackStack` (#1449) — the compensation twin of
392
+ * {@link loadAwsApplier}.
393
+ */
394
+ async function loadAwsRollback(): Promise<AwsRollback> {
395
+ const spec = "@intentius/chant-lexicon-aws/op/activities";
396
+ let mod: { rollbackStack?: AwsRollback };
397
+ try {
398
+ mod = (await import(spec)) as { rollbackStack?: AwsRollback };
399
+ } catch (err) {
400
+ throw new Error(
401
+ `rollback for target "cloudformation" needs @intentius/chant-lexicon-aws, which could not be ` +
402
+ `loaded (${err instanceof Error ? err.message : String(err)}). CloudFormation rollback goes ` +
403
+ `through the aws lexicon's rollbackStack since chant #1449; install the aws lexicon and ` +
404
+ `list it in chant.config.ts.`,
405
+ );
406
+ }
407
+ if (typeof mod.rollbackStack !== "function") {
408
+ throw new Error(
409
+ "the installed @intentius/chant-lexicon-aws exports no rollbackStack — it predates chant #1449",
410
+ );
411
+ }
412
+ return mod.rollbackStack;
413
+ }
414
+
415
+ /**
416
+ * Sensible default build output per target. kubectl takes a directory (all
417
+ * manifests), so `dist`; kustomize's "output" is the kustomization DIRECTORY
418
+ * the render reads. The file targets take the file their lexicon's build
419
+ * conventionally emits: `template.json` for CloudFormation/ARM, `dist/gcp.yaml`
420
+ * (the CNRM manifest) for gcp, `dist/fly.json` (the serialized plan) for fly.
421
+ * Pure — exported for testing.
422
+ */
423
+ export function defaultOutput(target: ApplyTarget): string {
424
+ switch (target) {
425
+ case "kubectl":
426
+ case "kustomize":
427
+ return "dist";
428
+ case "gcp":
429
+ return "dist/gcp.yaml";
430
+ case "fly":
431
+ return "dist/fly.json";
432
+ default:
433
+ return "template.json";
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Collapse a #1446 apply envelope onto the one result shape this activity
439
+ * returns, logging the counts (and warning on skips) as it goes. The envelope
440
+ * is normalized through core's `normalizeApply`, so the counts are the lengths
441
+ * of `NormalizedApply`'s three arrays — nothing re-derived, nothing invented.
442
+ */
443
+ function collapseEnvelope(envelope: ApplyResult, label: string): NativeApplyResult {
444
+ const n = normalizeApply(envelope);
445
+ console.log(
446
+ `[${label}] applied ${n.applied.length} resource(s)` +
447
+ (n.pruned.length > 0 ? `; pruned ${n.pruned.length}` : ""),
448
+ );
449
+ // #1447: a resource the applier made no call for is reported, not dropped —
450
+ // otherwise a partial apply reads as a full one. The per-resource reasons
451
+ // ride the envelope; the count is what a later step reads.
452
+ if (n.notAttempted.length > 0) {
453
+ console.warn(`[${label}] NOT attempted: ${n.notAttempted.length} resource(s)`);
454
+ for (const skip of n.notAttempted) {
455
+ console.warn(
456
+ `[${label}] ${skip.kind}/${skip.name}: ${skip.reason}${skip.detail ? ` (${skip.detail})` : ""}`,
457
+ );
458
+ }
459
+ }
460
+ return {
461
+ applied: n.applied.length,
462
+ pruned: n.pruned.length,
463
+ notAttempted: n.notAttempted.length,
464
+ };
465
+ }
466
+
467
+ /**
468
+ * Apply declared source to the cloud via the target's native mechanism.
469
+ * Deletes (when enabled) ride that mechanism's own delete path — marker-scoped
470
+ * on `kubectl`, tag-scoped on `arm`, label-scoped on `gcp`, marker- and
471
+ * app-scoped on `fly`, and stack-scoped on `cloudformation`, where the deploy
472
+ * itself removes resources dropped from the template and `deleteMode` changes
473
+ * nothing: a resource CFN did not create is not in the stack. See
474
+ * {@link DeleteMode}.
475
+ *
476
+ * The appliers are injectable so this dispatcher can be tested without the
477
+ * product lexicons present; production resolves them through
478
+ * {@link loadK8sApplier} / {@link loadAzureApplier} / {@link loadAwsApplier} /
479
+ * {@link loadGcpApplier} / {@link loadFlyApplier}.
480
+ */
481
+ export async function nativeApply(
482
+ args: NativeApplyArgs,
483
+ signal?: AbortSignal,
484
+ applier?: K8sApplier,
485
+ azureApplier?: AzureApplier,
486
+ renderer: (dir: string) => Promise<Array<Record<string, unknown>>> = renderKustomization,
487
+ awsApplier?: AwsApplier,
488
+ gcpApplier?: GcpApplier,
489
+ flyApplier?: FlyApplier,
490
+ ): Promise<NativeApplyResult> {
491
+ const output = args.output ?? defaultOutput(args.target);
492
+ const deleteMode = args.deleteMode ?? "never";
493
+
494
+ if (args.target === "kubectl" || args.target === "kustomize") {
495
+ const apply = applier ?? (await loadK8sApplier());
496
+ // kustomize (#1548): `output` is the kustomization DIRECTORY; render it
497
+ // and hand the documents to the SAME k8s applier inline — stamping, the
498
+ // marker-scoped prune, and the conflict semantics are identical.
499
+ const kustomized =
500
+ args.target === "kustomize"
501
+ ? { documents: await renderer(output), manifest: `kustomize:${output}` }
502
+ : { manifest: output };
503
+ const result = await apply(
504
+ {
505
+ ...kustomized,
506
+ environment: args.env,
507
+ deleteMode,
508
+ ...(args.forceConflicts !== undefined ? { force: args.forceConflicts } : {}),
509
+ },
510
+ signal,
511
+ );
512
+ // The field manager is the operator's detail and stays on the log; the
513
+ // result is the count projection like every other target's. The k8s
514
+ // applier's contract has no skip path — a document it cannot classify
515
+ // throws — so NOT-ATTEMPTED is structurally zero here.
516
+ console.log(
517
+ `applied ${result.applied.length} object(s) as field manager "${result.fieldManager}"` +
518
+ (result.pruned.length > 0 ? `; pruned ${result.pruned.length}` : ""),
519
+ );
520
+ return {
521
+ applied: result.applied.length,
522
+ pruned: result.pruned.length,
523
+ notAttempted: 0,
524
+ };
525
+ }
526
+
527
+ if (args.target === "arm") {
528
+ const apply = azureApplier ?? (await loadAzureApplier());
529
+ const envelope = await apply(
530
+ {
531
+ templatePath: output,
532
+ resourceGroup: args.env,
533
+ // The same variable azure's read path honours, so an ARM apply lands
534
+ // wherever `--live` is already looking (floci-az, or real Azure when
535
+ // unset).
536
+ ...(process.env.AZURE_ENDPOINT_URL ? { endpoint: process.env.AZURE_ENDPOINT_URL } : {}),
537
+ prune: deleteMode !== "never",
538
+ },
539
+ signal,
540
+ );
541
+ return collapseEnvelope(envelope, args.env);
542
+ }
543
+
544
+ if (args.target === "gcp") {
545
+ // gcp (#1449): the gcp lexicon's per-resource applier. Only the manifest
546
+ // path and the prune switch cross this seam — endpoint (`GCP_ENDPOINT_URL`)
547
+ // and project (`GOOGLE_CLOUD_PROJECT` / CNRM annotation) are gcpApply's own
548
+ // env resolution, and `env` is a log label here: GCP has no stack or
549
+ // resource-group equivalent for it to name.
550
+ const apply = gcpApplier ?? (await loadGcpApplier());
551
+ const envelope = await apply({ manifestPath: output, prune: deleteMode !== "never" }, signal);
552
+ // #1447's skips and the not-prunable kinds both ride the envelope as
553
+ // NOT-ATTEMPTED entries — one bucket, per-entry reasons, one count out.
554
+ return collapseEnvelope(envelope, args.env);
555
+ }
556
+
557
+ if (args.target === "fly") {
558
+ // fly (#1449): the fly lexicon's flaps applier. Only the plan path and the
559
+ // prune switch cross this seam — the endpoint (`FLY_FLAPS_BASE_URL`,
560
+ // mudflaps locally) and token (`FLY_API_TOKEN`) are flyApply's own env
561
+ // resolution, and `env` is a log label here: the app names live in the
562
+ // plan itself.
563
+ const apply = flyApplier ?? (await loadFlyApplier());
564
+ const envelope = await apply({ planPath: output, prune: deleteMode !== "never" }, signal);
565
+ // The six applied classes and five pruned classes are already flattened
566
+ // into the envelope by fly's own toApplyResult; here they are just counts.
567
+ return collapseEnvelope(envelope, args.env);
568
+ }
569
+
570
+ // cloudformation (#1449): the aws lexicon's native applier. env is the stack
571
+ // name and output the template path; endpoint resolution (#1694) and
572
+ // capability derivation (#980) are awsApply's own, so nothing else is passed.
573
+ const apply = awsApplier ?? (await loadAwsApplier());
574
+ const result = await apply({ templatePath: output, stackName: args.env }, signal);
575
+ // The stack, its settled status and the action are the operator's detail and
576
+ // stay on the log. The result is the same count projection as every other
577
+ // target's, with the stack as the unit: one settled deploy, one applied.
578
+ console.log(`${result.action}: stack ${result.stackName} (${result.status})`);
579
+ return { applied: 1, pruned: 0, notAttempted: 0 };
580
+ }
581
+
582
+ /**
583
+ * Whether a target has a mapped native rollback for {@link compensateApply} to
584
+ * run without an explicit `compensate.command`. `cloudformation` is the only
585
+ * one today — the aws lexicon's `rollbackStack`. This is the totality
586
+ * predicate `ApplyOp` checks at build time (#1449): a target outside it with
587
+ * no command has nothing a compensation could run, so the op refuses to build
588
+ * with compensation on rather than warn at rollback time.
589
+ */
590
+ export function hasNativeRollback(target: ApplyTarget): boolean {
591
+ return target === "cloudformation";
592
+ }
593
+
594
+ export interface CompensateApplyArgs {
595
+ /** Native mechanism that was applied. */
596
+ target: ApplyTarget;
597
+ /** Environment — CFN stack name / ARM resource group. */
598
+ env: string;
599
+ /** Explicit rollback command, used in preference to the native default. */
600
+ command?: string;
601
+ }
602
+
603
+ /** What a compensation did. */
604
+ export interface CompensateApplyResult {
605
+ /** The explicit rollback command that ran, when one was supplied. */
606
+ command?: string;
607
+ /** The stack rolled back — cloudformation. */
608
+ stackName?: string;
609
+ /** Whether the native rollback actually ran — cloudformation. `false` when
610
+ * the stack was absent or the target does not implement RollbackStack (Floci). */
611
+ rolledBack?: boolean;
612
+ /** The settled post-rollback stack status — cloudformation. */
613
+ status?: string;
614
+ }
615
+
616
+ /**
617
+ * Compensation step (saga rollback) for a partial apply failure. Runs the
618
+ * explicit `command` if given; otherwise `cloudformation` rolls back natively
619
+ * through the aws lexicon's `rollbackStack` (#1449 — CloudFormation
620
+ * `RollbackStack` over the Query API, no CLI in the path).
621
+ *
622
+ * Compensation is total for built ops: `ApplyOp` refuses at build time to wire
623
+ * this activity for a target with neither a native rollback
624
+ * ({@link hasNativeRollback}) nor an explicit `command`, so the no-rollback
625
+ * branch below is unreachable from an op it built. It stays as a throw, not a
626
+ * warn — a hand-assembled op that reaches it must fail loudly, because partial
627
+ * state should never look reverted when it isn't.
628
+ *
629
+ * `rollback` is injectable for tests; production resolves it through
630
+ * {@link loadAwsRollback}.
631
+ */
632
+ export async function compensateApply(
633
+ args: CompensateApplyArgs,
634
+ signal?: AbortSignal,
635
+ rollback?: AwsRollback,
636
+ ): Promise<CompensateApplyResult> {
637
+ if (args.command) {
638
+ const { stdout, stderr } = await execAsync(args.command, { signal });
639
+ if (stdout) console.log(stdout);
640
+ if (stderr) console.error(stderr);
641
+ return { command: args.command };
642
+ }
643
+
644
+ if (args.target === "cloudformation") {
645
+ const roll = rollback ?? (await loadAwsRollback());
646
+ const result = await roll({ stackName: args.env }, signal);
647
+ return {
648
+ stackName: result.stackName,
649
+ rolledBack: result.rolledBack,
650
+ ...(result.status !== undefined ? { status: result.status } : {}),
651
+ };
652
+ }
653
+
654
+ // Defensive: unreachable from an ApplyOp, which refuses this combination at
655
+ // build time (#1449). Reaching it means the op was assembled without that
656
+ // check, and the honest outcome is a failure that says the state stands.
657
+ throw new Error(
658
+ `no automatic rollback for target "${args.target}" — the partial apply to ${args.env} was NOT ` +
659
+ `reverted and cannot be. ApplyOp refuses compensate for this target at build time; either ` +
660
+ `supply compensate.command or use a target with a mapped rollback (cloudformation).`,
661
+ );
662
+ }
@@ -0,0 +1,26 @@
1
+ import { exec } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+
4
+ const execAsync = promisify(exec);
5
+
6
+ export interface ChantBuildArgs {
7
+ path: string;
8
+ /** npm script to run. Default: `build`. Set e.g. `build:aws` to build one target. */
9
+ script?: string;
10
+ /** Optional extra env vars to pass to the build command. */
11
+ env?: Record<string, string>;
12
+ }
13
+
14
+ /**
15
+ * Run an npm build script (`build` by default) in the given project directory.
16
+ * Uses fastIdempotent profile — 5m timeout, 3 retries.
17
+ */
18
+ export async function chantBuild(args: ChantBuildArgs, signal?: AbortSignal): Promise<void> {
19
+ const { stdout, stderr } = await execAsync(`npm run ${args.script ?? "build"}`, {
20
+ cwd: args.path,
21
+ env: { ...process.env, ...args.env },
22
+ signal,
23
+ });
24
+ if (stdout) console.log(stdout);
25
+ if (stderr) console.error(stderr);
26
+ }