@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,131 @@
1
+ /**
2
+ * TF023 (#2110): Terraform state, or the `.terraform/` working directory,
3
+ * committed to the repository.
4
+ *
5
+ * Every other rule in the TF family is a post-synth check over a parsed root
6
+ * module, contributed by the terraform lexicon. This one is not about HCL at
7
+ * all: the finding is that a path exists in version control, so there is
8
+ * nothing for `chant build` to check and nothing for the lexicon's parser to
9
+ * read. It therefore takes the shape `secrets.ts` established and `wrangler.ts`
10
+ * and `nginx.ts` copied, a path detector plus a check over the discovered file
11
+ * list, called from the audit CLI beside `scanForSecrets`, with its catalog
12
+ * entry in core's own `RULE_CATALOG` (./catalog.ts) rather than a lexicon's.
13
+ * It runs whether or not the terraform lexicon is installed.
14
+ *
15
+ * A state file is a committed secret store: it records every attribute of every
16
+ * managed resource, including the ones providers mark sensitive, in plaintext
17
+ * JSON. `.terraform/` is milder (providers and vendored modules) but is still
18
+ * hundreds of megabytes of machine-generated content, and it can hold a
19
+ * `terraform.tfstate` of its own for the workspace-local backend.
20
+ *
21
+ * Pure: no fs, no network, no Node-only global, so it is Workers-safe (epic #350). The
22
+ * walk that decides which paths reach here is `discover.ts`'s
23
+ * `collectCandidates`, which is also where a locally ignored path is dropped:
24
+ * see `isTerraformStatePath` there and `gitignoreCoversTerraformState` below.
25
+ */
26
+
27
+ import type { AuditFinding } from "./core";
28
+
29
+ /** The minimal file shape the check needs (matches `discover.ts`'s `RepoFile`). */
30
+ export interface ScannableFile {
31
+ path: string;
32
+ content: string;
33
+ }
34
+
35
+ /** `terraform.tfstate`, `terraform.tfstate.backup`, and any other `*.tfstate`. */
36
+ export function isTerraformStateFile(path: string): boolean {
37
+ const name = path.split("/").pop() ?? path;
38
+ return /\.tfstate(\.backup)?$/i.test(name);
39
+ }
40
+
41
+ /** The `.terraform` working directory itself, or anything inside it. */
42
+ export function isTerraformWorkDir(path: string): boolean {
43
+ const parts = path.split("/");
44
+ return parts.includes(".terraform");
45
+ }
46
+
47
+ /** Either of the two shapes TF023 reports. */
48
+ export function isTerraformStatePath(path: string): boolean {
49
+ return isTerraformStateFile(path) || isTerraformWorkDir(path);
50
+ }
51
+
52
+ /**
53
+ * Does a `.gitignore` body already exclude Terraform state? Deliberately
54
+ * narrow: it recognises the handful of patterns the style guide's own
55
+ * `.gitignore` section and `github/gitignore`'s `Terraform.gitignore` use
56
+ * (`*.tfstate`, `*.tfstate.*`, `.terraform/`, `.terraform*`, with an optional
57
+ * leading slash or a leading double-star), not the whole gitignore grammar. A repository that
58
+ * writes something more exotic gets a finding it can suppress; the alternative,
59
+ * a partial gitignore engine, would be wrong in quieter ways.
60
+ *
61
+ * Used by the local walk only (`discover.ts`), where "on disk" and "tracked by
62
+ * git" are different questions and nearly every Terraform working tree has an
63
+ * ignored `.terraform/` in it. A fetched repository's file list is already
64
+ * exactly the tracked files, so nothing filters it.
65
+ */
66
+ function escapeRegExp(literal: string): string {
67
+ return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
68
+ }
69
+
70
+ export function gitignoreCoversTerraformState(gitignore: string, path: string): boolean {
71
+ const name = path.split("/").pop() ?? path;
72
+ for (const raw of gitignore.split("\n")) {
73
+ const line = raw.trim();
74
+ if (line === "" || line.startsWith("#") || line.startsWith("!")) continue;
75
+ const pattern = line.replace(/^\*\*\//, "").replace(/^\//, "").replace(/\/$/, "");
76
+ if (pattern === "" || pattern.includes("/")) continue;
77
+ // `*` matches within one path segment, as git's own glob does. The pattern
78
+ // is compared against the file's own name and against every segment of its
79
+ // path, which is what makes `.terraform/` match `infra/prod/.terraform`.
80
+ const re = new RegExp(`^${pattern.split("*").map(escapeRegExp).join("[^/]*")}$`);
81
+ if (re.test(name) || path.split("/").some((segment) => re.test(segment))) return true;
82
+ }
83
+ return false;
84
+ }
85
+
86
+ /**
87
+ * Report TF023 for every committed state file and `.terraform/` directory in
88
+ * the file list. One finding per path, and one for the `.terraform` directory
89
+ * as a whole rather than per file inside it: a vendored provider binary is not
90
+ * a separate finding from the directory that holds it.
91
+ */
92
+ export function auditTerraformState(files: ScannableFile[]): AuditFinding[] {
93
+ const findings: AuditFinding[] = [];
94
+ const workDirs = new Set<string>();
95
+
96
+ for (const file of files) {
97
+ if (isTerraformWorkDir(file.path)) {
98
+ const parts = file.path.split("/");
99
+ const dir = parts.slice(0, parts.indexOf(".terraform") + 1).join("/");
100
+ if (workDirs.has(dir)) continue;
101
+ workDirs.add(dir);
102
+ findings.push({
103
+ checkId: "TF023",
104
+ severity: "warning",
105
+ message:
106
+ `\`${dir}\` is committed to the repository. Terraform's working directory holds downloaded ` +
107
+ "providers and vendored child modules, and the local backend keeps its state there too. " +
108
+ "Delete it from version control and add `.terraform/` to .gitignore.",
109
+ file: dir,
110
+ lexicon: "terraform",
111
+ entity: ".terraform",
112
+ });
113
+ continue;
114
+ }
115
+ if (!isTerraformStateFile(file.path)) continue;
116
+ findings.push({
117
+ checkId: "TF023",
118
+ severity: "error",
119
+ message:
120
+ `\`${file.path}\` is committed to the repository. A state file records every attribute of every ` +
121
+ "managed resource in plaintext, including the ones providers mark sensitive, so a committed " +
122
+ "state file is a committed secret store. Remove it from version control, add `*.tfstate` and " +
123
+ "`*.tfstate.backup` to .gitignore, move the state to a remote backend, and rotate anything it held.",
124
+ file: file.path,
125
+ lexicon: "terraform",
126
+ entity: file.path.split("/").pop() ?? file.path,
127
+ });
128
+ }
129
+
130
+ return findings;
131
+ }
package/src/build.ts CHANGED
@@ -3,12 +3,14 @@ import type { Serializer, SerializerResult } from "./serializer";
3
3
  import type { OwnershipMarker } from "./ownership";
4
4
  import type { BuildError, DiscoveryErrorType } from "./errors";
5
5
  import type { IntrinsicDef, BuildRootContribution, BuildRootContributor } from "./lexicon";
6
- import type { BuildParamProvenance } from "./provenance";
6
+ import { getProvenance, type BuildParamProvenance } from "./provenance";
7
+ import { foldProvenanceOfEntities, type FoldProvenance } from "./fold-provenance";
7
8
  import { DiscoveryError, BuildError as BuildErrorClass } from "./errors";
8
9
  import { LexiconOutput, isLexiconOutput } from "./lexicon-output";
9
10
  import { isSecretDeclaration } from "./secret-provenance";
10
11
  import { splitReceiptEntities } from "./effect-receipt";
11
12
  import { isScenario } from "./lifecycle/scenario";
13
+ import { isOpEntity } from "./op/resource";
12
14
  import { AttrRef } from "./attrref";
13
15
  import { isAttrRefLike } from "./utils";
14
16
  import { isChildProject, type ChildProjectInstance } from "./child-project";
@@ -282,6 +284,22 @@ export interface BuildResult {
282
284
  * supplies none.
283
285
  */
284
286
  buildParams: BuildParamProvenance[];
287
+
288
+ /**
289
+ * chant #2161 — emitted property path to origin, per entity: which composite
290
+ * parameter produced the field, which literal the composite fixes, which the
291
+ * author declared directly, and which this build could not attribute.
292
+ *
293
+ * Beside the output on purpose, and never inside it. Nothing here is passed
294
+ * to a serializer, so it cannot reach the document an applier writes; see
295
+ * ./fold-provenance.ts's module doc and `fold-provenance-exclusion.test.ts`.
296
+ *
297
+ * Every entity with properties appears. The origins are as fine as the build
298
+ * managed: a run build, or a fold build over a factory outside the
299
+ * interpretable subset, records `unknown` for a composite's fields rather
300
+ * than guessing.
301
+ */
302
+ foldProvenance: FoldProvenance;
285
303
  }
286
304
 
287
305
  /**
@@ -308,6 +326,13 @@ export function partitionByLexicon(
308
326
  // Plan scenarios (#1292) are serializer-neutral the same way: a checkable
309
327
  // expectation the CLI reads off the entity map, never output.
310
328
  if (isScenario(entity)) continue;
329
+ // Op declarations (#2118) too. An Op's build output is its `op.json` IR,
330
+ // and core writes that itself from the entity map (`./cli/commands/build.ts`)
331
+ // rather than routing it through a lexicon serializer — the Op model, the
332
+ // executor and the IR are all core's, and no lexicon renders an Op entity
333
+ // into its own manifest. Keeping them out of every partition means no
334
+ // "No serializer found" warning fires for core's own `chant` lexicon.
335
+ if (isOpEntity(entity)) continue;
311
336
  const lexicon = entity.lexicon;
312
337
  if (!partitions.has(lexicon)) {
313
338
  partitions.set(lexicon, new Map());
@@ -852,6 +877,11 @@ async function buildFromDiscoveryResult(
852
877
  foldDecisions: discoveryResult.foldDecisions,
853
878
  lexiconVersions: { ...(options?.lexiconVersions ?? {}) },
854
879
  buildParams: options?.buildParams ?? [],
880
+ // chant #2161 — read off the entities AFTER every step that can change
881
+ // them (the shared-props merge in `expandComposite`, the build-root merge
882
+ // above), and deliberately after Step 7, so nothing about computing it can
883
+ // reach a serializer.
884
+ foldProvenance: foldProvenanceOfEntities(discoveryResult.entities, getProvenance),
855
885
  };
856
886
  }
857
887
 
@@ -0,0 +1,145 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import {
3
+ NO_CLAIMED_FIELDS,
4
+ claimedFieldPaths,
5
+ claimedFieldsFromPaths,
6
+ claimedFieldsOfProps,
7
+ claimedFieldsOfTree,
8
+ classifyLiveField,
9
+ heldBy,
10
+ isClaimed,
11
+ } from "./claimed-fields";
12
+ import { UNRESOLVED, type DeepNormalizationHooks } from "./deep-observation";
13
+
14
+ describe("claimedFieldsOfProps", () => {
15
+ test("walks props to leaf paths in the diff's grammar", () => {
16
+ const claimed = claimedFieldsOfProps(
17
+ { spec: { replicas: 2, template: { spec: { containers: [{ name: "app", image: "a:1" }] } } } },
18
+ { entityType: "K8s::Apps::Deployment" },
19
+ );
20
+ expect(claimedFieldPaths(claimed)).toEqual([
21
+ "spec.replicas",
22
+ "spec.template.spec.containers[0].image",
23
+ "spec.template.spec.containers[0].name",
24
+ ]);
25
+ });
26
+
27
+ test("addresses set-like arrays by the lexicon's own order key", () => {
28
+ const hooks: DeepNormalizationHooks = {
29
+ orderKey: (el) => (el.pattern === "Tags" ? String((el.element as { Key: string }).Key) : undefined),
30
+ };
31
+ const claimed = claimedFieldsOfProps(
32
+ { Tags: [{ Key: "env", Value: "prod" }] },
33
+ { entityType: "AWS::S3::Bucket", hooks },
34
+ );
35
+ expect(claimedFieldPaths(claimed)).toEqual(["Tags[#env].Key", "Tags[#env].Value"]);
36
+ });
37
+
38
+ test("a pruned property is not claimed", () => {
39
+ // The hooks decide what is even in the tree, so the claim inherits them
40
+ // rather than second-guessing them: a field the lexicon subtracts on both
41
+ // sides is not a field chant is asserting anything about.
42
+ const hooks: DeepNormalizationHooks = { prune: (node) => node.pattern.startsWith("status") };
43
+ const claimed = claimedFieldsOfProps(
44
+ { spec: { replicas: 2 }, status: { readyReplicas: 2 } },
45
+ { entityType: "T", hooks },
46
+ );
47
+ expect(claimedFieldPaths(claimed)).toEqual(["spec.replicas"]);
48
+ });
49
+
50
+ test("an unevaluated intrinsic is still claimed", () => {
51
+ // chant set the field; it just cannot say what the reference resolves to.
52
+ const claimed = claimedFieldsOfProps({ BucketName: UNRESOLVED }, { entityType: "T" });
53
+ expect(isClaimed(claimed, "BucketName")).toBe(true);
54
+ });
55
+
56
+ test("an empty declaration claims nothing", () => {
57
+ expect(claimedFieldPaths(claimedFieldsOfProps({}, { entityType: "T" }))).toEqual([]);
58
+ expect(claimedFieldPaths(NO_CLAIMED_FIELDS)).toEqual([]);
59
+ });
60
+
61
+ test("agrees with the tree form on an already-normalized tree", () => {
62
+ const props = { spec: { replicas: 2 } };
63
+ expect(claimedFieldPaths(claimedFieldsOfProps(props, { entityType: "T" }))).toEqual(
64
+ claimedFieldPaths(claimedFieldsOfTree(props, { entityType: "T" })),
65
+ );
66
+ });
67
+ });
68
+
69
+ describe("isClaimed", () => {
70
+ const claimed = claimedFieldsFromPaths(["Tags[0].Value", "spec.replicas"]);
71
+
72
+ test("matches exactly", () => {
73
+ expect(isClaimed(claimed, "spec.replicas")).toBe(true);
74
+ });
75
+
76
+ test("does not match by index-erased pattern", () => {
77
+ // A pattern match would answer "declared" for a path with no declared value
78
+ // to compare against, which is neither of the two declared classifications.
79
+ expect(isClaimed(claimed, "Tags[3].Value")).toBe(false);
80
+ });
81
+
82
+ test("does not match an ancestor's claim", () => {
83
+ // Declaring `spec.replicas` says nothing about `spec.strategy.type`.
84
+ expect(isClaimed(claimed, "spec.strategy.type")).toBe(false);
85
+ });
86
+
87
+ test("an absent claim claims nothing", () => {
88
+ expect(isClaimed(undefined, "spec.replicas")).toBe(false);
89
+ });
90
+ });
91
+
92
+ describe("classifyLiveField", () => {
93
+ const claimed = claimedFieldsFromPaths(["spec.replicas"]);
94
+
95
+ test("declared and equal", () => {
96
+ expect(
97
+ classifyLiveField({ claimed, path: "spec.replicas", declaredValue: 2, liveValue: 2 }),
98
+ ).toBe("declared-equal");
99
+ });
100
+
101
+ test("declared and different", () => {
102
+ expect(
103
+ classifyLiveField({ claimed, path: "spec.replicas", declaredValue: 2, liveValue: 5 }),
104
+ ).toBe("declared-changed");
105
+ });
106
+
107
+ test("undeclared", () => {
108
+ expect(
109
+ classifyLiveField({ claimed, path: "metadata.labels.team", declaredValue: undefined, liveValue: "platform" }),
110
+ ).toBe("undeclared");
111
+ });
112
+
113
+ test("structural equality, not identity", () => {
114
+ const shaped = claimedFieldsFromPaths(["spec.selector"]);
115
+ expect(
116
+ classifyLiveField({
117
+ claimed: shaped,
118
+ path: "spec.selector",
119
+ declaredValue: { app: "web" },
120
+ liveValue: { app: "web" },
121
+ }),
122
+ ).toBe("declared-equal");
123
+ });
124
+ });
125
+
126
+ describe("heldBy", () => {
127
+ test("the substrate's manager answers where it has one", () => {
128
+ expect(heldBy({ "spec.replicas": "hpa-controller" }, "spec.replicas")).toEqual({
129
+ holder: "hpa-controller",
130
+ source: "field-manager",
131
+ });
132
+ });
133
+
134
+ test("the claim answers where the substrate records nothing", () => {
135
+ expect(heldBy(undefined, "spec.replicas")).toEqual({ source: "claimed-fields" });
136
+ });
137
+
138
+ test("the claim answers for a path the ownership metadata does not cover", () => {
139
+ // Kubernetes' own case: a keyed list segment has no `managedFields` entry
140
+ // under that path, so the declaration is the only witness left.
141
+ expect(heldBy({ "spec.replicas": "hpa-controller" }, "spec.template.spec.containers[#sidecar].image")).toEqual({
142
+ source: "claimed-fields",
143
+ });
144
+ });
145
+ });
@@ -0,0 +1,208 @@
1
+ /**
2
+ * The claimed-field set (#2160) — which properties this declaration ever set.
3
+ *
4
+ * chant's ownership question has always been answered per resource, from a
5
+ * marker: is this thing mine. The finer question was never asked. A live
6
+ * property tree carries fields nobody declared — an autoscaler's replica count,
7
+ * a controller's annotation, a value a person typed into a console — and the
8
+ * deep diff (./lifecycle/deep-diff.ts) reported every one of them as a
9
+ * difference, because a difference is all a two-way comparison can produce.
10
+ *
11
+ * Every lexicon has been paying for that in hand-written knowledge.
12
+ * `DeepNormalizationHooks.prune` is where the noise goes, and three of the four
13
+ * hooks exist because the live tree holds fields the declaration never
14
+ * mentions. Kubernetes is the one substrate that escapes it: the API server
15
+ * records a field manager per field (`metadata.managedFields`), so a foreign
16
+ * write is a fact about the object rather than a rule somebody maintains.
17
+ * `lexicons/gcp/src/deep-observe.ts` says why nobody else can do that — "a REST
18
+ * payload carries no field ownership" — and answers with a static per-kind
19
+ * table instead.
20
+ *
21
+ * The declaration is the table they are missing. A `ResourceDeclarable`'s
22
+ * `props` are exactly the fields chant set, they are available on every
23
+ * substrate, and they come from the same build that produced the entity.
24
+ * Nothing has to come back from the provider.
25
+ *
26
+ * ## The grammar is the diff's grammar
27
+ *
28
+ * A claim is a set of property paths in the form `flattenDeepProperties`
29
+ * produces: `spec.replicas`, `Tags[#env].Value`, `ingress[0].fromPort`. Same
30
+ * hooks, same normalization, same flattening — so a path in the claim and a
31
+ * path in the diff are the same string or they are different fields. Deriving
32
+ * the claim any other way (walking raw props, say) would give a set that agrees
33
+ * with the diff for most trees and disagrees for exactly the ones the hooks
34
+ * were written for.
35
+ *
36
+ * ## Membership is exact, deliberately
37
+ *
38
+ * A claimed path is matched exactly, never by its index-erased pattern
39
+ * (`Tags[].Value`). The pattern is the right test for
40
+ * {@link import("./deep-observation").DeepNode.counterpart}, which asks a
41
+ * shape question ("did source declare tag values at all") before array order is
42
+ * canonical. Classification asks a value question, and it pairs a declared
43
+ * value with a live one at the same path. A pattern match would answer
44
+ * "declared" for a path that has no declared value to compare against, which is
45
+ * neither of the two declared classifications and would quietly become a third
46
+ * meaning of "drift".
47
+ *
48
+ * ## What the claim does not decide
49
+ *
50
+ * It does not prune. A field chant never declared still reaches the diff, still
51
+ * appears in the report, and still carries its live value — it is reported as
52
+ * unclaimed rather than dropped, because chant #1191 already lost a
53
+ * console-added label by pruning what it could not attribute. What the claim
54
+ * changes is the verdict: unclaimed is not drift, and drift is the only thing
55
+ * that may become an update.
56
+ */
57
+
58
+ import {
59
+ deepValueEqual,
60
+ flattenDeepProperties,
61
+ normalizeDeepProperties,
62
+ type DeepNormalizationHooks,
63
+ } from "./deep-observation";
64
+
65
+ /**
66
+ * The set of property paths one declaration claims — every path its `props`
67
+ * flatten to, in the diff's own grammar.
68
+ *
69
+ * Opaque on purpose: {@link isClaimed} is the only membership test, so a
70
+ * consumer cannot accidentally invent a looser one (see the module doc on
71
+ * pattern matching).
72
+ */
73
+ export interface ClaimedFieldSet {
74
+ /** Flattened property paths, exactly as the diff addresses them. */
75
+ readonly paths: ReadonlySet<string>;
76
+ }
77
+
78
+ /**
79
+ * How one LIVE value relates to the claim. Three answers where a two-way diff
80
+ * had two:
81
+ *
82
+ * - `declared-equal` — chant set this field and the cloud agrees. Nothing to say.
83
+ * - `declared-changed` — chant set this field and the cloud holds something
84
+ * else. This is drift, and it is the only classification that may become an
85
+ * update.
86
+ * - `undeclared` — the field has a value and chant never set it. Somebody else
87
+ * holds it. Reported, never proposed, never counted as drift.
88
+ *
89
+ * A declared path with no live value at all is not in this enumeration: there
90
+ * is no live value to classify. The diff keeps reporting that case as `absent`.
91
+ */
92
+ export type FieldClaim = "declared-equal" | "declared-changed" | "undeclared";
93
+
94
+ /** Which source answered "who holds this field". */
95
+ export type FieldClaimSource =
96
+ /**
97
+ * The substrate named the manager. Kubernetes' `metadata.managedFields`, and
98
+ * nowhere else today — strictly better than the claim, because it says who.
99
+ */
100
+ | "field-manager"
101
+ /**
102
+ * The declaration answered: the path is not in the claimed-field set, so
103
+ * chant never set it. Says that it is somebody else's without saying whose,
104
+ * which is the best any substrate without ownership metadata can do.
105
+ */
106
+ | "claimed-fields";
107
+
108
+ /** An empty claim — a declaration with no props, and the safe default. */
109
+ export const NO_CLAIMED_FIELDS: ClaimedFieldSet = { paths: new Set<string>() };
110
+
111
+ /**
112
+ * Build a claim from an already-normalized declared property tree.
113
+ *
114
+ * `options` must be the same {@link FlattenDeepOptions} the diff flattens the
115
+ * declared side with, or the two disagree about keyed list segments.
116
+ */
117
+ export function claimedFieldsOfTree(
118
+ declared: Record<string, unknown>,
119
+ options: { entityType: string; hooks?: DeepNormalizationHooks },
120
+ ): ClaimedFieldSet {
121
+ const flat = flattenDeepProperties(declared, {
122
+ entityType: options.entityType,
123
+ side: "declared",
124
+ ...(options.hooks ? { hooks: options.hooks } : {}),
125
+ });
126
+ return { paths: new Set(flat.keys()) };
127
+ }
128
+
129
+ /**
130
+ * Build a claim straight from a declaration's raw `props` — the entry point for
131
+ * a consumer that has an entity and no diff.
132
+ *
133
+ * Normalizes with the lexicon's own hooks first, exactly as the diff does, so
134
+ * pruned and masked paths land the same way on both routes. `livePaths` is the
135
+ * counterpart set (`deepPathSet` over the live tree) where the caller has one:
136
+ * without it the pass runs one-sided and any hook gated on
137
+ * {@link import("./deep-observation").DeepNode.counterpart} sees `"unknown"`,
138
+ * which is the honest answer and prunes nothing default-related.
139
+ */
140
+ export function claimedFieldsOfProps(
141
+ props: Record<string, unknown>,
142
+ options: {
143
+ entityType: string;
144
+ hooks?: DeepNormalizationHooks;
145
+ livePaths?: ReadonlySet<string>;
146
+ },
147
+ ): ClaimedFieldSet {
148
+ const normalized = normalizeDeepProperties(props, {
149
+ entityType: options.entityType,
150
+ side: "declared",
151
+ ...(options.hooks ? { hooks: options.hooks } : {}),
152
+ ...(options.livePaths ? { counterpartPaths: options.livePaths } : {}),
153
+ });
154
+ return claimedFieldsOfTree(normalized, options);
155
+ }
156
+
157
+ /** True when this declaration set the property at `path`. */
158
+ export function isClaimed(claimed: ClaimedFieldSet | undefined, path: string): boolean {
159
+ return claimed !== undefined && claimed.paths.has(path);
160
+ }
161
+
162
+ /**
163
+ * The claim as a sorted array — the wire form, for
164
+ * {@link import("./deep-observation").DeepResourceObservation.claimedFields}
165
+ * and for anything serializing a result to JSON.
166
+ */
167
+ export function claimedFieldPaths(claimed: ClaimedFieldSet): string[] {
168
+ return [...claimed.paths].sort();
169
+ }
170
+
171
+ /** Rebuild a claim from its wire form. */
172
+ export function claimedFieldsFromPaths(paths: Iterable<string>): ClaimedFieldSet {
173
+ return { paths: new Set(paths) };
174
+ }
175
+
176
+ /**
177
+ * Classify one live value against the claim.
178
+ *
179
+ * `declaredValue` is only read when the path is claimed; pass whatever the
180
+ * declared tree holds there (including `undefined`, which is a legal declared
181
+ * value on a claimed path only in the sense that the flattener never emits it).
182
+ */
183
+ export function classifyLiveField(input: {
184
+ claimed: ClaimedFieldSet | undefined;
185
+ path: string;
186
+ declaredValue: unknown;
187
+ liveValue: unknown;
188
+ }): FieldClaim {
189
+ if (!isClaimed(input.claimed, input.path)) return "undeclared";
190
+ return deepValueEqual(input.declaredValue, input.liveValue) ? "declared-equal" : "declared-changed";
191
+ }
192
+
193
+ /**
194
+ * Who holds an undeclared live field, and which source said so.
195
+ *
196
+ * The manager wins where the substrate records one: "owned by `hpa-controller`"
197
+ * and "chant never set it" are the same verdict with very different amounts of
198
+ * information in them, and an operator can act on the first. The claim is the
199
+ * fallback, and it answers on every substrate.
200
+ */
201
+ export function heldBy(fieldOwners: Record<string, string> | undefined, path: string): {
202
+ holder?: string;
203
+ source: FieldClaimSource;
204
+ } {
205
+ const manager = fieldOwners?.[path];
206
+ if (manager) return { holder: manager, source: "field-manager" };
207
+ return { source: "claimed-fields" };
208
+ }
@@ -9,8 +9,8 @@ import { formatError, formatInfo } from "./format";
9
9
  * out (chant #1108) so every command that discovers project source before
10
10
  * running it resolves `chant.config.ts`'s declared `buildParams` the exact
11
11
  * same way: `chant build` (`../commands/build.ts`'s `buildCommand`), the
12
- * component deploy driver (`./handlers/run.ts`'s `chant run --components`
13
- * local + `--temporal` paths), and generate mode (`./handlers/build.ts`'s
12
+ * component deploy driver (`./handlers/run.ts`'s `chant run --components`),
13
+ * and generate mode (`./handlers/build.ts`'s
14
14
  * `chant build --components --generate <lexicon>`).
15
15
  *
16
16
  * Before #1108, only `buildCommand` ran this sequence — `chant run
@@ -57,6 +57,20 @@ export interface CommandGroup {
57
57
  description: string;
58
58
  /** Verbs in this group. */
59
59
  commands: CommandGroupCommand[];
60
+ /**
61
+ * The verb to run when the group name is given on its own — `chant acp`
62
+ * rather than `chant acp serve` (#2125). Named here rather than assumed to
63
+ * be the first verb, because a group whose bare form should be a usage
64
+ * error (`chant kube`) must stay one: omitting this field is how a group
65
+ * says it has no default.
66
+ *
67
+ * The token after the group name decides which reading applies, and that
68
+ * decision belongs to the caller that still holds the raw argv
69
+ * (`../cli/main.ts`'s `tryPluginCommand`): with a default verb, `chant acp
70
+ * --durable-requests` has no verb token to consume, so the flag is the
71
+ * default verb's argument rather than a verb it does not have.
72
+ */
73
+ defaultVerb?: string;
60
74
  }
61
75
 
62
76
  /**
@@ -0,0 +1 @@
1
+ resource "null_resource" "root" {}
@@ -0,0 +1 @@
1
+ resource "null_resource" "foo" {}
@@ -0,0 +1,3 @@
1
+ variable "region" {
2
+ type = string
3
+ }
@@ -8,8 +8,16 @@
8
8
  "dist/"
9
9
  ],
10
10
  "exports": {
11
- ".": "./src/index.ts",
12
- "./*": "./src/*",
11
+ ".": {
12
+ "development": "./src/index.ts",
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./src/index.ts"
15
+ },
16
+ "./*": {
17
+ "development": "./src/*.ts",
18
+ "types": "./dist/*.d.ts",
19
+ "default": "./src/*.ts"
20
+ },
13
21
  "./manifest": "./dist/manifest.json",
14
22
  "./meta": "./dist/meta.json",
15
23
  "./types": "./dist/types/index.d.ts"
@@ -18,8 +26,9 @@
18
26
  "generate": "npx tsx src/codegen/generate-cli.ts",
19
27
  "validate": "npx tsx src/validate-cli.ts",
20
28
  "docs": "npx tsx src/codegen/docs-cli.ts",
21
- "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
22
- "prepack": "npm run generate && npm run validate && npm run build"
29
+ "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && find dist -type f \\( -name \"*.js\" -o -name \"*.js.map\" \\) -delete",
30
+ "prepack": "npm run generate && npm run bundle && npm run validate && npm run build",
31
+ "bundle": "tsx src/package-cli.ts"
23
32
  },
24
33
  "devDependencies": {
25
34
  "@intentius/chant": "*",
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env tsx
2
+ import { generateDocs } from "./docs";
3
+
4
+ await generateDocs({ verbose: true });
@@ -15,6 +15,7 @@ export async function packageLexicon(options?: { verbose?: boolean; force?: bool
15
15
  buildManifest: (genResult) => ({
16
16
  name: "fixture",
17
17
  version: "0.0.1",
18
+ chantVersion: ">=0.1.0",
18
19
  }),
19
20
  srcDir,
20
21
  collectSkills: () => new Map(),
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env tsx
2
+ import { generate, writeGeneratedFiles } from "./codegen/generate";
3
+ import { packageLexicon } from "./codegen/package";
4
+ import { writeBundleSpec } from "@intentius/chant/codegen/package";
5
+ import { join, dirname } from "path";
6
+ import { fileURLToPath } from "url";
7
+
8
+ const srcDir = dirname(fileURLToPath(import.meta.url));
9
+
10
+ // 1. Generate src/generated/ files (writeGeneratedFiles resolves its own target)
11
+ const genResult = await generate({ verbose: true });
12
+ writeGeneratedFiles(genResult);
13
+
14
+ // 2. Run package pipeline and write dist/
15
+ const { spec, stats } = await packageLexicon({ verbose: true });
16
+
17
+ const distDir = join(dirname(srcDir), "dist");
18
+ writeBundleSpec(spec, distDir);
19
+
20
+ console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
21
+ console.error(`dist/ written to ${distDir}`);