@intentius/chant 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +20 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +14 -8
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  34. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  35. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  36. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  38. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  40. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  41. package/dist/cli/commands/init.d.ts.map +1 -1
  42. package/dist/cli/commands/lint.d.ts.map +1 -1
  43. package/dist/cli/commands/onboard.d.ts +2 -0
  44. package/dist/cli/commands/onboard.d.ts.map +1 -1
  45. package/dist/cli/handlers/build.d.ts.map +1 -1
  46. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  47. package/dist/cli/handlers/operator.d.ts +82 -16
  48. package/dist/cli/handlers/operator.d.ts.map +1 -1
  49. package/dist/cli/handlers/run.d.ts +49 -42
  50. package/dist/cli/handlers/run.d.ts.map +1 -1
  51. package/dist/cli/main.d.ts +28 -1
  52. package/dist/cli/main.d.ts.map +1 -1
  53. package/dist/cli/mcp/op-tools.d.ts +16 -1
  54. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  55. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  56. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  57. package/dist/cli/registry.d.ts +26 -9
  58. package/dist/cli/registry.d.ts.map +1 -1
  59. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  60. package/dist/components/auto-release.d.ts +10 -20
  61. package/dist/components/auto-release.d.ts.map +1 -1
  62. package/dist/components/capability.d.ts +4 -4
  63. package/dist/components/cli-support.d.ts +20 -21
  64. package/dist/components/cli-support.d.ts.map +1 -1
  65. package/dist/components/component.d.ts +3 -3
  66. package/dist/components/component.d.ts.map +1 -1
  67. package/dist/components/driver-output.d.ts.map +1 -1
  68. package/dist/components/driver.d.ts +66 -36
  69. package/dist/components/driver.d.ts.map +1 -1
  70. package/dist/components/index.d.ts +1 -2
  71. package/dist/components/index.d.ts.map +1 -1
  72. package/dist/components/manifest-persistence.d.ts +1 -9
  73. package/dist/components/manifest-persistence.d.ts.map +1 -1
  74. package/dist/components/run-progress.d.ts +6 -6
  75. package/dist/components/run-progress.d.ts.map +1 -1
  76. package/dist/components/verbs/run-agent.d.ts +9 -15
  77. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  78. package/dist/components/verbs/verify.d.ts +2 -2
  79. package/dist/deep-observation.d.ts +17 -0
  80. package/dist/deep-observation.d.ts.map +1 -1
  81. package/dist/discovery/files.d.ts +4 -4
  82. package/dist/discovery/fold-import.d.ts.map +1 -1
  83. package/dist/discovery/param-deps.d.ts +33 -0
  84. package/dist/discovery/param-deps.d.ts.map +1 -1
  85. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  86. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  87. package/dist/fold/foldable-helpers.d.ts +5 -1
  88. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  89. package/dist/fold-provenance.d.ts +236 -0
  90. package/dist/fold-provenance.d.ts.map +1 -0
  91. package/dist/graph-ops.d.ts +1 -1
  92. package/dist/held-elsewhere.d.ts +85 -0
  93. package/dist/held-elsewhere.d.ts.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/kubectl-context.d.ts +3 -3
  97. package/dist/lexicon-config.d.ts +4 -4
  98. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  99. package/dist/lexicon.d.ts +104 -14
  100. package/dist/lexicon.d.ts.map +1 -1
  101. package/dist/lifecycle/change-set.d.ts +13 -0
  102. package/dist/lifecycle/change-set.d.ts.map +1 -1
  103. package/dist/lifecycle/deep-diff.d.ts +133 -6
  104. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  105. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  106. package/dist/lifecycle/gate-ledger.d.ts +71 -3
  107. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  108. package/dist/lifecycle/index.d.ts +1 -0
  109. package/dist/lifecycle/index.d.ts.map +1 -1
  110. package/dist/lifecycle/release-ledger.d.ts +2 -2
  111. package/dist/lifecycle/run-ledger.d.ts +53 -0
  112. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  113. package/dist/lifecycle/symptoms.d.ts +3 -3
  114. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  115. package/dist/lint/config.d.ts +81 -2
  116. package/dist/lint/config.d.ts.map +1 -1
  117. package/dist/lint/post-synth.d.ts +55 -2
  118. package/dist/lint/post-synth.d.ts.map +1 -1
  119. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  120. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  121. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  122. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  123. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  124. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  125. package/dist/lint/rules/comp/index.d.ts +1 -1
  126. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  127. package/dist/lint/rules/op/index.d.ts +16 -0
  128. package/dist/lint/rules/op/index.d.ts.map +1 -0
  129. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  130. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  131. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  132. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  133. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  134. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  135. package/dist/lint/rules/op/support.d.ts +12 -0
  136. package/dist/lint/rules/op/support.d.ts.map +1 -0
  137. package/dist/lint/suppressions.d.ts +108 -0
  138. package/dist/lint/suppressions.d.ts.map +1 -0
  139. package/dist/live-endpoint.d.ts +1 -1
  140. package/dist/op/activities/activity-contracts.d.ts +54 -0
  141. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  142. package/dist/op/activities/apply.d.ts +262 -0
  143. package/dist/op/activities/apply.d.ts.map +1 -0
  144. package/dist/op/activities/build.d.ts +13 -0
  145. package/dist/op/activities/build.d.ts.map +1 -0
  146. package/dist/op/activities/converge.d.ts +110 -0
  147. package/dist/op/activities/converge.d.ts.map +1 -0
  148. package/dist/op/activities/env-teardown.d.ts +76 -0
  149. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  150. package/dist/op/activities/guard-validate.d.ts +64 -0
  151. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  152. package/dist/op/activities/http-check.d.ts +34 -0
  153. package/dist/op/activities/http-check.d.ts.map +1 -0
  154. package/dist/op/activities/index.d.ts +31 -0
  155. package/dist/op/activities/index.d.ts.map +1 -0
  156. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  157. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  158. package/dist/op/activities/lifecycle.d.ts +42 -0
  159. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  160. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  161. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  162. package/dist/op/activities/policy.d.ts +17 -0
  163. package/dist/op/activities/policy.d.ts.map +1 -0
  164. package/dist/op/activities/reconcile.d.ts +89 -0
  165. package/dist/op/activities/reconcile.d.ts.map +1 -0
  166. package/dist/op/activities/shell.d.ts +13 -0
  167. package/dist/op/activities/shell.d.ts.map +1 -0
  168. package/dist/op/activities/teardown.d.ts +10 -0
  169. package/dist/op/activities/teardown.d.ts.map +1 -0
  170. package/dist/op/activities/util.d.ts +7 -0
  171. package/dist/op/activities/util.d.ts.map +1 -0
  172. package/dist/op/activities/wait.d.ts +28 -0
  173. package/dist/op/activities/wait.d.ts.map +1 -0
  174. package/dist/op/activities/workflow-audit.d.ts +92 -0
  175. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  176. package/dist/op/activity-contract-registry.d.ts +76 -0
  177. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  178. package/dist/op/activity-contract.d.ts +25 -18
  179. package/dist/op/activity-contract.d.ts.map +1 -1
  180. package/dist/op/activity-failure.d.ts +28 -0
  181. package/dist/op/activity-failure.d.ts.map +1 -0
  182. package/dist/op/activity-profiles.d.ts +118 -0
  183. package/dist/op/activity-profiles.d.ts.map +1 -0
  184. package/dist/op/activity-registry.d.ts +22 -38
  185. package/dist/op/activity-registry.d.ts.map +1 -1
  186. package/dist/op/activity-runtime.d.ts +3 -14
  187. package/dist/op/activity-runtime.d.ts.map +1 -1
  188. package/dist/op/builders.d.ts +84 -29
  189. package/dist/op/builders.d.ts.map +1 -1
  190. package/dist/op/composites/apply-op.d.ts +113 -0
  191. package/dist/op/composites/apply-op.d.ts.map +1 -0
  192. package/dist/op/composites/converge-op.d.ts +120 -0
  193. package/dist/op/composites/converge-op.d.ts.map +1 -0
  194. package/dist/op/composites/index.d.ts +26 -0
  195. package/dist/op/composites/index.d.ts.map +1 -0
  196. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  197. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  198. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  199. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  200. package/dist/op/composites/reconcile-op.d.ts +57 -0
  201. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  202. package/dist/op/composites/watch-op.d.ts +60 -0
  203. package/dist/op/composites/watch-op.d.ts.map +1 -0
  204. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  205. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  206. package/dist/op/converge-rule.d.ts +12 -10
  207. package/dist/op/converge-rule.d.ts.map +1 -1
  208. package/dist/op/cron.d.ts +51 -0
  209. package/dist/op/cron.d.ts.map +1 -0
  210. package/dist/op/discover.d.ts +9 -0
  211. package/dist/op/discover.d.ts.map +1 -1
  212. package/dist/op/duration.d.ts +11 -0
  213. package/dist/op/duration.d.ts.map +1 -0
  214. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  215. package/dist/op/gate.d.ts +90 -0
  216. package/dist/op/gate.d.ts.map +1 -0
  217. package/dist/op/generate-pipeline.d.ts +9 -0
  218. package/dist/op/generate-pipeline.d.ts.map +1 -1
  219. package/dist/op/index.d.ts +23 -7
  220. package/dist/op/index.d.ts.map +1 -1
  221. package/dist/op/local-executor.d.ts +114 -28
  222. package/dist/op/local-executor.d.ts.map +1 -1
  223. package/dist/op/local-output.d.ts +11 -1
  224. package/dist/op/local-output.d.ts.map +1 -1
  225. package/dist/op/op-ir.d.ts +184 -0
  226. package/dist/op/op-ir.d.ts.map +1 -0
  227. package/dist/op/op-verb-class.d.ts +10 -2
  228. package/dist/op/op-verb-class.d.ts.map +1 -1
  229. package/dist/op/operator.d.ts +30 -5
  230. package/dist/op/operator.d.ts.map +1 -1
  231. package/dist/op/receipt-store.d.ts +1 -1
  232. package/dist/op/receipt-store.d.ts.map +1 -1
  233. package/dist/op/resource.d.ts +15 -1
  234. package/dist/op/resource.d.ts.map +1 -1
  235. package/dist/op/runtime.d.ts +200 -0
  236. package/dist/op/runtime.d.ts.map +1 -0
  237. package/dist/op/runtimes/local.d.ts +29 -0
  238. package/dist/op/runtimes/local.d.ts.map +1 -0
  239. package/dist/op/step-output-ref.d.ts +15 -13
  240. package/dist/op/step-output-ref.d.ts.map +1 -1
  241. package/dist/op/types.d.ts +79 -27
  242. package/dist/op/types.d.ts.map +1 -1
  243. package/dist/ownership.d.ts +1 -1
  244. package/dist/provenance.d.ts +21 -0
  245. package/dist/provenance.d.ts.map +1 -1
  246. package/dist/serializer-walker.d.ts.map +1 -1
  247. package/package.json +6 -1
  248. package/src/audit/catalog.test.ts +79 -3
  249. package/src/audit/catalog.ts +111 -13
  250. package/src/audit/core.test.ts +26 -0
  251. package/src/audit/core.ts +61 -17
  252. package/src/audit/discover.test.ts +39 -0
  253. package/src/audit/discover.ts +91 -15
  254. package/src/audit/lineage.ts +100 -0
  255. package/src/audit/prior-art.ts +153 -0
  256. package/src/audit/proof.test.ts +67 -0
  257. package/src/audit/proof.ts +70 -0
  258. package/src/audit/report-html.ts +9 -4
  259. package/src/audit/report-model.ts +16 -2
  260. package/src/audit/report.test.ts +33 -0
  261. package/src/audit/report.ts +5 -3
  262. package/src/audit/rules-doc.test.ts +34 -2
  263. package/src/audit/rules-doc.ts +82 -9
  264. package/src/audit/secrets.ts +15 -3
  265. package/src/audit/terraform-state.test.ts +144 -0
  266. package/src/audit/terraform-state.ts +131 -0
  267. package/src/build.ts +31 -1
  268. package/src/claimed-fields.test.ts +145 -0
  269. package/src/claimed-fields.ts +208 -0
  270. package/src/cli/build-params-cli.ts +2 -2
  271. package/src/cli/command-group.ts +14 -0
  272. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  273. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  274. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  275. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  276. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  277. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  278. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  279. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  280. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  281. package/src/cli/commands/audit.test.ts +189 -11
  282. package/src/cli/commands/audit.ts +73 -27
  283. package/src/cli/commands/build.test.ts +292 -9
  284. package/src/cli/commands/build.ts +156 -24
  285. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  286. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  287. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  288. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  289. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  290. package/src/cli/commands/init-lexicon.test.ts +97 -2
  291. package/src/cli/commands/init-lexicon.ts +4 -2
  292. package/src/cli/commands/init.test.ts +35 -1
  293. package/src/cli/commands/init.ts +14 -3
  294. package/src/cli/commands/lint.test.ts +48 -0
  295. package/src/cli/commands/lint.ts +123 -0
  296. package/src/cli/commands/onboard.test.ts +75 -0
  297. package/src/cli/commands/onboard.ts +54 -23
  298. package/src/cli/handlers/build.test.ts +81 -1
  299. package/src/cli/handlers/build.ts +15 -1
  300. package/src/cli/handlers/graph.test.ts +3 -3
  301. package/src/cli/handlers/lifecycle.test.ts +195 -12
  302. package/src/cli/handlers/lifecycle.ts +123 -6
  303. package/src/cli/handlers/misc.ts +1 -1
  304. package/src/cli/handlers/operator.test.ts +183 -11
  305. package/src/cli/handlers/operator.ts +260 -55
  306. package/src/cli/handlers/run.test.ts +431 -1287
  307. package/src/cli/handlers/run.ts +365 -915
  308. package/src/cli/main.test.ts +23 -15
  309. package/src/cli/main.ts +88 -33
  310. package/src/cli/mcp/op-tools.ts +147 -88
  311. package/src/cli/mcp/resource-handlers.ts +10 -37
  312. package/src/cli/mcp/resources/context.ts +11 -12
  313. package/src/cli/mcp/server.test.ts +25 -27
  314. package/src/cli/mcp/server.ts +2 -2
  315. package/src/cli/registry.ts +26 -9
  316. package/src/codegen/docs.ts +1 -1
  317. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  318. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  319. package/src/components/README.md +3 -2
  320. package/src/components/auto-release.test.ts +4 -20
  321. package/src/components/auto-release.ts +17 -42
  322. package/src/components/capability.ts +4 -4
  323. package/src/components/cli-support.test.ts +10 -5
  324. package/src/components/cli-support.ts +52 -44
  325. package/src/components/component.schema.json +2 -2
  326. package/src/components/component.ts +3 -3
  327. package/src/components/driver-output.ts +14 -2
  328. package/src/components/driver.test.ts +92 -22
  329. package/src/components/driver.ts +193 -83
  330. package/src/components/index.ts +1 -6
  331. package/src/components/manifest-persistence.test.ts +2 -20
  332. package/src/components/manifest-persistence.ts +4 -24
  333. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  334. package/src/components/run-progress.ts +6 -6
  335. package/src/components/verbs/run-agent.ts +11 -17
  336. package/src/components/verbs/verify.ts +2 -2
  337. package/src/deep-observation.test.ts +75 -0
  338. package/src/deep-observation.ts +48 -0
  339. package/src/discovery/collect.test.ts +3 -3
  340. package/src/discovery/files.ts +4 -4
  341. package/src/discovery/fold-import.ts +105 -2
  342. package/src/discovery/param-deps.test.ts +112 -1
  343. package/src/discovery/param-deps.ts +193 -0
  344. package/src/discovery/sandbox/bundle.ts +15 -1
  345. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  346. package/src/discovery/sandbox/config-wire.ts +2 -2
  347. package/src/fold/fold.test.ts +56 -0
  348. package/src/fold/foldable-helpers.ts +81 -1
  349. package/src/fold-provenance-exclusion.test.ts +186 -0
  350. package/src/fold-provenance.test.ts +495 -0
  351. package/src/fold-provenance.ts +441 -0
  352. package/src/graph-ops.test.ts +2 -2
  353. package/src/graph-ops.ts +1 -1
  354. package/src/held-elsewhere.test.ts +102 -0
  355. package/src/held-elsewhere.ts +114 -0
  356. package/src/index.ts +3 -0
  357. package/src/kubectl-context.ts +3 -3
  358. package/src/lexicon-config.test.ts +5 -5
  359. package/src/lexicon-config.ts +4 -4
  360. package/src/lexicon-plugin-helpers.ts +1 -1
  361. package/src/lexicon.ts +120 -14
  362. package/src/lifecycle/change-set.test.ts +49 -0
  363. package/src/lifecycle/change-set.ts +67 -0
  364. package/src/lifecycle/converge-ledger.ts +1 -1
  365. package/src/lifecycle/deep-diff.test.ts +267 -14
  366. package/src/lifecycle/deep-diff.ts +217 -14
  367. package/src/lifecycle/deep-observe.test.ts +3 -1
  368. package/src/lifecycle/deep-observe.ts +16 -6
  369. package/src/lifecycle/gate-ledger.test.ts +74 -2
  370. package/src/lifecycle/gate-ledger.ts +143 -36
  371. package/src/lifecycle/index.ts +1 -0
  372. package/src/lifecycle/release-ledger.ts +2 -2
  373. package/src/lifecycle/run-ledger.test.ts +268 -0
  374. package/src/lifecycle/run-ledger.ts +201 -0
  375. package/src/lifecycle/symptoms.ts +3 -3
  376. package/src/lint/config.test.ts +82 -1
  377. package/src/lint/config.ts +112 -3
  378. package/src/lint/policy.test.ts +1 -1
  379. package/src/lint/post-synth.test.ts +31 -0
  380. package/src/lint/post-synth.ts +54 -1
  381. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  382. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  383. package/src/lint/rules/comp/comp.test.ts +1 -1
  384. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
  385. package/src/lint/rules/comp/index.ts +3 -3
  386. package/src/lint/rules/op/index.ts +23 -0
  387. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  388. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  389. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  390. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  391. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  392. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  393. package/src/lint/rules/op/support.ts +11 -0
  394. package/src/lint/suppressions.test.ts +163 -0
  395. package/src/lint/suppressions.ts +204 -0
  396. package/src/live-endpoint.ts +1 -1
  397. package/src/op/activities/activity-contracts.ts +66 -0
  398. package/src/op/activities/apply.test.ts +567 -0
  399. package/src/op/activities/apply.ts +662 -0
  400. package/src/op/activities/build.ts +26 -0
  401. package/src/op/activities/converge.test.ts +330 -0
  402. package/src/op/activities/converge.ts +449 -0
  403. package/src/op/activities/env-teardown.test.ts +187 -0
  404. package/src/op/activities/env-teardown.ts +171 -0
  405. package/src/op/activities/guard-validate.test.ts +139 -0
  406. package/src/op/activities/guard-validate.ts +223 -0
  407. package/src/op/activities/http-check.test.ts +48 -0
  408. package/src/op/activities/http-check.ts +55 -0
  409. package/src/op/activities/index.ts +119 -0
  410. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  411. package/src/op/activities/lexicon-upgrade.ts +673 -0
  412. package/src/op/activities/lifecycle.ts +85 -0
  413. package/src/op/activities/pipeline-audit.test.ts +67 -0
  414. package/src/op/activities/pipeline-audit.ts +201 -0
  415. package/src/op/activities/policy.test.ts +19 -0
  416. package/src/op/activities/policy.ts +37 -0
  417. package/src/op/activities/reconcile.test.ts +81 -0
  418. package/src/op/activities/reconcile.ts +187 -0
  419. package/src/op/activities/shell.ts +26 -0
  420. package/src/op/activities/teardown.ts +22 -0
  421. package/src/op/activities/util.ts +6 -0
  422. package/src/op/activities/wait.ts +69 -0
  423. package/src/op/activities/workflow-audit.test.ts +90 -0
  424. package/src/op/activities/workflow-audit.ts +203 -0
  425. package/src/op/activity-contract-registry.test.ts +98 -0
  426. package/src/op/activity-contract-registry.ts +114 -0
  427. package/src/op/activity-contract.test.ts +1 -1
  428. package/src/op/activity-contract.ts +37 -33
  429. package/src/op/activity-failure.ts +34 -0
  430. package/src/op/activity-profiles.test.ts +56 -0
  431. package/src/op/activity-profiles.ts +116 -0
  432. package/src/op/activity-registry.test.ts +37 -28
  433. package/src/op/activity-registry.ts +27 -56
  434. package/src/op/activity-runtime.ts +3 -47
  435. package/src/op/builders-exports.test.ts +0 -49
  436. package/src/op/builders-typed.test.ts +164 -0
  437. package/src/op/builders.ts +123 -39
  438. package/src/op/composites/apply-op.ts +208 -0
  439. package/src/op/composites/composites.test.ts +366 -0
  440. package/src/op/composites/converge-op.test.ts +168 -0
  441. package/src/op/composites/converge-op.ts +214 -0
  442. package/src/op/composites/index.ts +26 -0
  443. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  444. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  445. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  446. package/src/op/composites/pipeline-audit-op.ts +78 -0
  447. package/src/op/composites/reconcile-op.test.ts +51 -0
  448. package/src/op/composites/reconcile-op.ts +107 -0
  449. package/src/op/composites/watch-op.ts +108 -0
  450. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  451. package/src/op/composites/workflow-audit-op.ts +88 -0
  452. package/src/op/converge-rule.ts +12 -10
  453. package/src/op/cron.test.ts +128 -0
  454. package/src/op/cron.ts +149 -0
  455. package/src/op/discover-root.test.ts +105 -1
  456. package/src/op/discover.test.ts +6 -2
  457. package/src/op/discover.ts +84 -16
  458. package/src/op/duration.ts +21 -0
  459. package/src/op/effect-step.test.ts +26 -11
  460. package/src/op/emulator-lifecycle.ts +1 -2
  461. package/src/op/gate.ts +155 -0
  462. package/src/op/generate-pipeline.test.ts +65 -3
  463. package/src/op/generate-pipeline.ts +19 -2
  464. package/src/op/index.ts +39 -6
  465. package/src/op/local-executor.test.ts +163 -34
  466. package/src/op/local-executor.ts +370 -102
  467. package/src/op/local-output.test.ts +95 -11
  468. package/src/op/local-output.ts +33 -4
  469. package/src/op/op-ir.test.ts +281 -0
  470. package/src/op/op-ir.ts +417 -0
  471. package/src/op/op-verb-class.ts +19 -5
  472. package/src/op/op.test.ts +26 -5
  473. package/src/op/operator.test.ts +175 -6
  474. package/src/op/operator.ts +63 -16
  475. package/src/op/receipt-store.ts +1 -1
  476. package/src/op/resource.ts +20 -2
  477. package/src/op/runtime.ts +203 -0
  478. package/src/op/runtimes/local.test.ts +181 -0
  479. package/src/op/runtimes/local.ts +212 -0
  480. package/src/op/step-output-ref.ts +15 -13
  481. package/src/op/types.ts +84 -24
  482. package/src/ownership.ts +1 -1
  483. package/src/provenance.test.ts +6 -0
  484. package/src/provenance.ts +21 -1
  485. package/src/serializer-walker.test.ts +42 -0
  486. package/src/serializer-walker.ts +21 -2
  487. package/dist/cli/handlers/op-progress.d.ts +0 -90
  488. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  489. package/dist/cli/handlers/run-client.d.ts +0 -127
  490. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  491. package/dist/cli/handlers/run-report.d.ts +0 -5
  492. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  493. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  494. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  495. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  496. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  497. package/src/cli/handlers/op-progress.test.ts +0 -268
  498. package/src/cli/handlers/op-progress.ts +0 -248
  499. package/src/cli/handlers/run-client.test.ts +0 -82
  500. package/src/cli/handlers/run-client.ts +0 -219
  501. package/src/cli/handlers/run-report.test.ts +0 -62
  502. package/src/cli/handlers/run-report.ts +0 -122
  503. package/src/components/temporal-codegen-loader.ts +0 -41
  504. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -1,8 +1,12 @@
1
1
  import { describe, test, expect } from "vitest";
2
- import { countPropertyDrift, diffDeep, type DeclaredDeepEntity } from "./deep-diff";
2
+ import { countHeld, countUnclaimed, countPropertyDrift, diffDeep, suspiciousHeld, type DeclaredDeepEntity } from "./deep-diff";
3
3
  import { UNRESOLVED, type NormalizedDeepObservation } from "../deep-observation";
4
+ import { HELD_ELSEWHERE_TAG } from "../held-elsewhere";
4
5
  import type { BaselineLexicon } from "./observation-baseline";
5
6
 
7
+ /** A declared property's normalized held-elsewhere form, as `deep-observation.ts` produces it (#2162). Tests build this directly, same as they build every other already-normalized declared value in this file. */
8
+ const held = (by: string, reason: string) => ({ heldElsewhere: HELD_ELSEWHERE_TAG, by, reason });
9
+
6
10
  const live = (
7
11
  resources: Record<string, { type: string; properties: Record<string, unknown>; fieldOwners?: Record<string, string> }>,
8
12
  unobserved: NormalizedDeepObservation["unobserved"] = {},
@@ -33,14 +37,25 @@ describe("diffDeep", () => {
33
37
  expect(countPropertyDrift(result)).toBe(1);
34
38
  });
35
39
 
36
- test("a property only the cloud has is undeclared drift", () => {
40
+ test("a property only the cloud has is unclaimed, not drift", () => {
37
41
  const result = diffDeep({
38
42
  declared: { b: { type: "T", properties: {} } },
39
43
  live: live({ b: { type: "T", properties: { LoggingConfiguration: { TargetBucket: "logs" } } } }),
40
44
  });
41
- expect(result.drifted[0].changes).toEqual([
42
- { path: "LoggingConfiguration.TargetBucket", kind: "undeclared", live: "logs" },
45
+ expect(result.drifted).toEqual([]);
46
+ expect(countPropertyDrift(result)).toBe(0);
47
+ expect(result.unclaimed).toEqual([
48
+ {
49
+ name: "b",
50
+ type: "T",
51
+ fields: [
52
+ { path: "LoggingConfiguration.TargetBucket", live: "logs", source: "claimed-fields" },
53
+ ],
54
+ },
43
55
  ]);
56
+ // Every property chant declared matches, so the entity is clean: a field
57
+ // somebody else set must not keep an entity reported forever.
58
+ expect(result.unchanged).toEqual(["b"]);
44
59
  });
45
60
 
46
61
  test("a declared property the cloud does not carry is absent", () => {
@@ -107,17 +122,22 @@ describe("diffDeep with an accepted baseline", () => {
107
122
  accepted: [{ path: "Tags[0].Value", value: "platform", note: "set by the platform team" }],
108
123
  },
109
124
  };
125
+ // A path source DOES declare — since #2160 the baseline only ever has drift
126
+ // to suppress, because a path source never declared is unclaimed and was
127
+ // never reported in the first place.
128
+ const declared = { b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "ours" }] } } };
110
129
 
111
130
  test("an accepted deviation is not drift", () => {
112
131
  const result = diffDeep({
113
- declared: { b: { type: "AWS::S3::Bucket", properties: {} } },
132
+ declared,
114
133
  live: live({ b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "platform" }] } } }),
115
134
  baseline,
116
135
  });
117
136
  expect(result.drifted).toEqual([]);
118
137
  expect(result.accepted[0].changes[0]).toEqual({
119
138
  path: "Tags[0].Value",
120
- kind: "undeclared",
139
+ kind: "changed",
140
+ declared: "ours",
121
141
  live: "platform",
122
142
  baseline: "platform",
123
143
  });
@@ -125,13 +145,14 @@ describe("diffDeep with an accepted baseline", () => {
125
145
 
126
146
  test("a value that moved away from the accepted one is drift again, and shows all three axes", () => {
127
147
  const result = diffDeep({
128
- declared: { b: { type: "AWS::S3::Bucket", properties: {} } },
148
+ declared,
129
149
  live: live({ b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "someone-else" }] } } }),
130
150
  baseline,
131
151
  });
132
152
  expect(result.drifted[0].changes[0]).toEqual({
133
153
  path: "Tags[0].Value",
134
- kind: "undeclared",
154
+ kind: "changed",
155
+ declared: "ours",
135
156
  live: "someone-else",
136
157
  baseline: "platform",
137
158
  });
@@ -139,7 +160,7 @@ describe("diffDeep with an accepted baseline", () => {
139
160
 
140
161
  test("an entity with only accepted deviations is not counted as unchanged", () => {
141
162
  const result = diffDeep({
142
- declared: { b: { type: "AWS::S3::Bucket", properties: {} } },
163
+ declared,
143
164
  live: live({ b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "platform" }] } } }),
144
165
  baseline,
145
166
  });
@@ -148,12 +169,30 @@ describe("diffDeep with an accepted baseline", () => {
148
169
 
149
170
  test("the baseline never suppresses a different path", () => {
150
171
  const result = diffDeep({
151
- declared: { b: { type: "AWS::S3::Bucket", properties: {} } },
172
+ declared: { b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "ours" }], Extra: 0 } } },
152
173
  live: live({ b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "platform" }], Extra: 1 } } }),
153
174
  baseline,
154
175
  });
155
176
  expect(result.drifted[0].changes.map((c) => c.path)).toEqual(["Extra"]);
156
177
  });
178
+
179
+ test("a held field carries its accepted value but never needed one", () => {
180
+ // A baseline recorded before #2160 still names undeclared paths. The value
181
+ // rides along for continuity; the field is quiet either way.
182
+ const result = diffDeep({
183
+ declared: { b: { type: "AWS::S3::Bucket", properties: {} } },
184
+ live: live({ b: { type: "AWS::S3::Bucket", properties: { Tags: [{ Value: "platform" }] } } }),
185
+ baseline,
186
+ });
187
+ expect(result.drifted).toEqual([]);
188
+ expect(result.accepted).toEqual([]);
189
+ expect(result.unclaimed[0].fields[0]).toEqual({
190
+ path: "Tags[0].Value",
191
+ live: "platform",
192
+ source: "claimed-fields",
193
+ baseline: "platform",
194
+ });
195
+ });
157
196
  });
158
197
 
159
198
  // #1189 — `kind` says a path is undeclared or changed; `owner` says who did it.
@@ -252,7 +291,7 @@ describe("diffDeep — declared-side origin (#1443)", () => {
252
291
  expect(change.origin).toEqual({ kind: "composite", composite: "WebService", instance: "web" });
253
292
  });
254
293
 
255
- test("is absent on an undeclared path — nothing in source produced it", () => {
294
+ test("an undeclared path gets no origin because it is not a drift row at all", () => {
256
295
  const result = diffDeep({
257
296
  declared,
258
297
  live: live({
@@ -265,9 +304,9 @@ describe("diffDeep — declared-side origin (#1443)", () => {
265
304
  },
266
305
  }),
267
306
  });
268
- const change = result.drifted[0].changes.find((c) => c.path === "status.observed")!;
269
- expect(change.kind).toBe("undeclared");
270
- expect(change).not.toHaveProperty("origin");
307
+ expect(result.drifted).toEqual([]);
308
+ const held = result.unclaimed[0].fields.find((f) => f.path === "status.observed")!;
309
+ expect(held).toEqual({ path: "status.observed", live: 1, source: "claimed-fields" });
271
310
  });
272
311
 
273
312
  test("is absent when the build recorded no path origins", () => {
@@ -280,3 +319,217 @@ describe("diffDeep — declared-side origin (#1443)", () => {
280
319
  expect(result.drifted[0].changes[0]).not.toHaveProperty("origin");
281
320
  });
282
321
  });
322
+
323
+
324
+ // #2160 - the claimed-field set. A live value on a property this declaration
325
+ // never set belongs to whoever wrote it, and chant reports it as theirs rather
326
+ // than proposing to change it.
327
+ describe("diffDeep - the claimed-field set (#2160)", () => {
328
+ const declared: Record<string, DeclaredDeepEntity> = {
329
+ web: { type: "K8s::Apps::Deployment", properties: { spec: { replicas: 2 } } },
330
+ };
331
+
332
+ test("a declared path that differs is still drift, unchanged", () => {
333
+ const result = diffDeep({
334
+ declared,
335
+ live: live({ web: { type: "K8s::Apps::Deployment", properties: { spec: { replicas: 5 } } } }),
336
+ });
337
+ expect(result.drifted[0].changes).toEqual([
338
+ { path: "spec.replicas", kind: "changed", declared: 2, live: 5 },
339
+ ]);
340
+ expect(result.unclaimed).toEqual([]);
341
+ });
342
+
343
+ test("a declared path that matches is neither drift nor held", () => {
344
+ const result = diffDeep({
345
+ declared,
346
+ live: live({ web: { type: "K8s::Apps::Deployment", properties: { spec: { replicas: 2 } } } }),
347
+ });
348
+ expect(result.unchanged).toEqual(["web"]);
349
+ expect(result.unclaimed).toEqual([]);
350
+ });
351
+
352
+ test("the claim answers where the substrate records no manager", () => {
353
+ const result = diffDeep({
354
+ declared,
355
+ live: live({
356
+ web: {
357
+ type: "K8s::Apps::Deployment",
358
+ properties: { spec: { replicas: 2 }, metadata: { labels: { team: "platform" } } },
359
+ },
360
+ }),
361
+ });
362
+ expect(result.unclaimed[0].fields).toEqual([
363
+ { path: "metadata.labels.team", live: "platform", source: "claimed-fields" },
364
+ ]);
365
+ });
366
+
367
+ test("the manager wins over the claim where the substrate names one", () => {
368
+ const result = diffDeep({
369
+ declared,
370
+ live: live({
371
+ web: {
372
+ type: "K8s::Apps::Deployment",
373
+ properties: { spec: { replicas: 2 }, metadata: { labels: { team: "platform" } } },
374
+ fieldOwners: { "metadata.labels.team": "kubectl-edit" },
375
+ },
376
+ }),
377
+ });
378
+ expect(result.unclaimed[0].fields).toEqual([
379
+ { path: "metadata.labels.team", live: "platform", heldBy: "kubectl-edit", source: "field-manager" },
380
+ ]);
381
+ });
382
+
383
+ test("a field manager on a DECLARED path still reports drift and names the manager", () => {
384
+ // The contested case: chant's source asks for 2, an autoscaler holds 5.
385
+ // The claim covers the path, so the disagreement is real drift.
386
+ const result = diffDeep({
387
+ declared,
388
+ live: live({
389
+ web: {
390
+ type: "K8s::Apps::Deployment",
391
+ properties: { spec: { replicas: 5 } },
392
+ fieldOwners: { "spec.replicas": "hpa-controller" },
393
+ },
394
+ }),
395
+ });
396
+ expect(result.unclaimed).toEqual([]);
397
+ expect(result.drifted[0].changes[0]).toMatchObject({ kind: "changed", owner: "hpa-controller" });
398
+ });
399
+
400
+ test("held fields are never counted as drift", () => {
401
+ const result = diffDeep({
402
+ declared,
403
+ live: live({
404
+ web: {
405
+ type: "K8s::Apps::Deployment",
406
+ properties: { spec: { replicas: 5 }, status: { readyReplicas: 5, observedGeneration: 3 } },
407
+ },
408
+ }),
409
+ });
410
+ expect(countPropertyDrift(result)).toBe(1);
411
+ expect(countUnclaimed(result)).toBe(2);
412
+ });
413
+
414
+ test("an unevaluated intrinsic is claimed, so its live value is not unclaimed", () => {
415
+ // chant DID set the field; it just cannot know what the reference resolves
416
+ // to. Treating it as unclaimed would report an interpolated property as
417
+ // somebody else's on every read.
418
+ const result = diffDeep({
419
+ declared: { b: { type: "T", properties: { BucketName: UNRESOLVED } } },
420
+ live: live({ b: { type: "T", properties: { BucketName: "prod-data" } } }),
421
+ });
422
+ expect(result.drifted).toEqual([]);
423
+ expect(result.unclaimed).toEqual([]);
424
+ });
425
+ });
426
+
427
+ // #2162 — a `heldElsewhere()` marker is never drift: a difference on it is
428
+ // reported as held, with its holder and reason, and never as `changed`,
429
+ // `undeclared`, or `absent`. The honest example from the issue: an HPA owns
430
+ // a Deployment's `spec.replicas` after the first apply.
431
+ describe("diffDeep — heldElsewhere() (#2162)", () => {
432
+ test("a live value on a held path is reported as held, not drift", () => {
433
+ const result = diffDeep({
434
+ declared: {
435
+ web: {
436
+ type: "K8s::Apps::Deployment",
437
+ properties: { spec: { replicas: held("hpa", "the autoscaler owns replicas after the first apply") } },
438
+ },
439
+ },
440
+ live: live({ web: { type: "K8s::Apps::Deployment", properties: { spec: { replicas: 5 } } } }),
441
+ });
442
+ expect(result.drifted).toEqual([]);
443
+ expect(countPropertyDrift(result)).toBe(0);
444
+ expect(result.held).toEqual([
445
+ {
446
+ name: "web",
447
+ type: "K8s::Apps::Deployment",
448
+ held: [
449
+ {
450
+ path: "spec.replicas",
451
+ by: "hpa",
452
+ reason: "the autoscaler owns replicas after the first apply",
453
+ live: 5,
454
+ suspicious: false,
455
+ },
456
+ ],
457
+ },
458
+ ]);
459
+ expect(countHeld(result)).toBe(1);
460
+ // Metadata otherwise matched, so it is unchanged too — held is a
461
+ // separate axis, not a substitute for the drift/unchanged split.
462
+ expect(result.unchanged).toEqual(["web"]);
463
+ });
464
+
465
+ test("no live value at all on a held path is suspicious — the claimed hand-over never showed up", () => {
466
+ const result = diffDeep({
467
+ declared: {
468
+ web: {
469
+ type: "K8s::Apps::Deployment",
470
+ properties: { spec: { replicas: held("hpa", "x") } },
471
+ },
472
+ },
473
+ live: live({ web: { type: "K8s::Apps::Deployment", properties: {} } }),
474
+ });
475
+ expect(result.drifted).toEqual([]);
476
+ expect(result.held[0].held[0]).toEqual({
477
+ path: "spec.replicas",
478
+ by: "hpa",
479
+ reason: "x",
480
+ suspicious: true,
481
+ });
482
+ expect(result.held[0].held[0]).not.toHaveProperty("live");
483
+ expect(suspiciousHeld(result)).toEqual([
484
+ { name: "web", type: "K8s::Apps::Deployment", path: "spec.replicas", by: "hpa", reason: "x", suspicious: true },
485
+ ]);
486
+ });
487
+
488
+ test("carries the field manager that owns the path live, where the substrate records one (#1189)", () => {
489
+ const result = diffDeep({
490
+ declared: {
491
+ web: { type: "K8s::Apps::Deployment", properties: { spec: { replicas: held("hpa", "x") } } },
492
+ },
493
+ live: live({
494
+ web: {
495
+ type: "K8s::Apps::Deployment",
496
+ properties: { spec: { replicas: 5 } },
497
+ fieldOwners: { "spec.replicas": "hpa-controller" },
498
+ },
499
+ }),
500
+ });
501
+ expect(result.held[0].held[0]).toMatchObject({ owner: "hpa-controller" });
502
+ });
503
+
504
+ test("a held property never counts toward property drift, even alongside a genuine drift on another path", () => {
505
+ const result = diffDeep({
506
+ declared: {
507
+ web: {
508
+ type: "K8s::Apps::Deployment",
509
+ properties: { spec: { replicas: held("hpa", "x"), image: "app:1" } },
510
+ },
511
+ },
512
+ live: live({
513
+ web: { type: "K8s::Apps::Deployment", properties: { spec: { replicas: 7, image: "app:2" } } },
514
+ }),
515
+ });
516
+ expect(result.drifted).toEqual([
517
+ { name: "web", type: "K8s::Apps::Deployment", changes: [{ path: "spec.image", kind: "changed", declared: "app:1", live: "app:2" }] },
518
+ ]);
519
+ expect(countPropertyDrift(result)).toBe(1);
520
+ expect(countHeld(result)).toBe(1);
521
+ // A held+drifted entity is not unchanged — the same rule as accepted.
522
+ expect(result.unchanged).toEqual([]);
523
+ });
524
+
525
+ test("suspiciousHeld() reports nothing when the held property never differs from having no baseline to check", () => {
526
+ // A held property whose live value showed up is not suspicious, whatever
527
+ // that value is — chant has no seed to compare it against, so presence
528
+ // alone is the only evidence it can read in one observation.
529
+ const result = diffDeep({
530
+ declared: { web: { type: "T", properties: { A: held("controller", "x") } } },
531
+ live: live({ web: { type: "T", properties: { A: "anything" } } }),
532
+ });
533
+ expect(suspiciousHeld(result)).toEqual([]);
534
+ });
535
+ });