@intentius/chant 0.56.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +20 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +14 -8
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  34. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  35. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  36. package/dist/cli/commands/import.d.ts.map +1 -1
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  38. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  40. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  41. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/lint.d.ts.map +1 -1
  44. package/dist/cli/commands/onboard.d.ts +2 -0
  45. package/dist/cli/commands/onboard.d.ts.map +1 -1
  46. package/dist/cli/handlers/build.d.ts.map +1 -1
  47. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  48. package/dist/cli/handlers/operator.d.ts +82 -16
  49. package/dist/cli/handlers/operator.d.ts.map +1 -1
  50. package/dist/cli/handlers/run.d.ts +49 -42
  51. package/dist/cli/handlers/run.d.ts.map +1 -1
  52. package/dist/cli/main.d.ts +28 -1
  53. package/dist/cli/main.d.ts.map +1 -1
  54. package/dist/cli/mcp/op-tools.d.ts +16 -1
  55. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  56. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  57. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  58. package/dist/cli/registry.d.ts +26 -9
  59. package/dist/cli/registry.d.ts.map +1 -1
  60. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  61. package/dist/components/auto-release.d.ts +10 -20
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability.d.ts +4 -4
  64. package/dist/components/cli-support.d.ts +20 -21
  65. package/dist/components/cli-support.d.ts.map +1 -1
  66. package/dist/components/component.d.ts +3 -3
  67. package/dist/components/component.d.ts.map +1 -1
  68. package/dist/components/driver-output.d.ts.map +1 -1
  69. package/dist/components/driver.d.ts +66 -36
  70. package/dist/components/driver.d.ts.map +1 -1
  71. package/dist/components/index.d.ts +1 -2
  72. package/dist/components/index.d.ts.map +1 -1
  73. package/dist/components/manifest-persistence.d.ts +1 -9
  74. package/dist/components/manifest-persistence.d.ts.map +1 -1
  75. package/dist/components/run-progress.d.ts +6 -6
  76. package/dist/components/run-progress.d.ts.map +1 -1
  77. package/dist/components/verbs/run-agent.d.ts +9 -15
  78. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  79. package/dist/components/verbs/verify.d.ts +2 -2
  80. package/dist/deep-observation.d.ts +17 -0
  81. package/dist/deep-observation.d.ts.map +1 -1
  82. package/dist/discovery/files.d.ts +4 -4
  83. package/dist/discovery/fold-import.d.ts.map +1 -1
  84. package/dist/discovery/param-deps.d.ts +33 -0
  85. package/dist/discovery/param-deps.d.ts.map +1 -1
  86. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  87. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  88. package/dist/fold/foldable-helpers.d.ts +5 -1
  89. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  90. package/dist/fold-provenance.d.ts +236 -0
  91. package/dist/fold-provenance.d.ts.map +1 -0
  92. package/dist/graph-ops.d.ts +1 -1
  93. package/dist/held-elsewhere.d.ts +85 -0
  94. package/dist/held-elsewhere.d.ts.map +1 -0
  95. package/dist/import/ir-utils.d.ts +1 -1
  96. package/dist/import/ir-utils.d.ts.map +1 -1
  97. package/dist/import/parser.d.ts +33 -0
  98. package/dist/import/parser.d.ts.map +1 -1
  99. package/dist/index.d.ts +3 -0
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/kubectl-context.d.ts +3 -3
  102. package/dist/lexicon-config.d.ts +4 -4
  103. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  104. package/dist/lexicon.d.ts +104 -14
  105. package/dist/lexicon.d.ts.map +1 -1
  106. package/dist/lifecycle/change-set.d.ts +13 -0
  107. package/dist/lifecycle/change-set.d.ts.map +1 -1
  108. package/dist/lifecycle/deep-diff.d.ts +133 -6
  109. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  110. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  111. package/dist/lifecycle/gate-ledger.d.ts +71 -3
  112. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  113. package/dist/lifecycle/index.d.ts +1 -0
  114. package/dist/lifecycle/index.d.ts.map +1 -1
  115. package/dist/lifecycle/release-ledger.d.ts +2 -2
  116. package/dist/lifecycle/run-ledger.d.ts +53 -0
  117. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  118. package/dist/lifecycle/symptoms.d.ts +3 -3
  119. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  120. package/dist/lint/config.d.ts +81 -2
  121. package/dist/lint/config.d.ts.map +1 -1
  122. package/dist/lint/post-synth.d.ts +55 -2
  123. package/dist/lint/post-synth.d.ts.map +1 -1
  124. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  125. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  126. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  127. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  128. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  129. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  130. package/dist/lint/rules/comp/index.d.ts +1 -1
  131. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  132. package/dist/lint/rules/op/index.d.ts +16 -0
  133. package/dist/lint/rules/op/index.d.ts.map +1 -0
  134. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  135. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  136. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  137. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  138. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  139. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  140. package/dist/lint/rules/op/support.d.ts +12 -0
  141. package/dist/lint/rules/op/support.d.ts.map +1 -0
  142. package/dist/lint/suppressions.d.ts +108 -0
  143. package/dist/lint/suppressions.d.ts.map +1 -0
  144. package/dist/live-endpoint.d.ts +1 -1
  145. package/dist/op/activities/activity-contracts.d.ts +54 -0
  146. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  147. package/dist/op/activities/apply.d.ts +262 -0
  148. package/dist/op/activities/apply.d.ts.map +1 -0
  149. package/dist/op/activities/build.d.ts +13 -0
  150. package/dist/op/activities/build.d.ts.map +1 -0
  151. package/dist/op/activities/converge.d.ts +110 -0
  152. package/dist/op/activities/converge.d.ts.map +1 -0
  153. package/dist/op/activities/env-teardown.d.ts +76 -0
  154. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  155. package/dist/op/activities/guard-validate.d.ts +64 -0
  156. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  157. package/dist/op/activities/http-check.d.ts +34 -0
  158. package/dist/op/activities/http-check.d.ts.map +1 -0
  159. package/dist/op/activities/index.d.ts +31 -0
  160. package/dist/op/activities/index.d.ts.map +1 -0
  161. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  162. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  163. package/dist/op/activities/lifecycle.d.ts +42 -0
  164. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  165. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  166. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  167. package/dist/op/activities/policy.d.ts +17 -0
  168. package/dist/op/activities/policy.d.ts.map +1 -0
  169. package/dist/op/activities/reconcile.d.ts +89 -0
  170. package/dist/op/activities/reconcile.d.ts.map +1 -0
  171. package/dist/op/activities/shell.d.ts +13 -0
  172. package/dist/op/activities/shell.d.ts.map +1 -0
  173. package/dist/op/activities/teardown.d.ts +10 -0
  174. package/dist/op/activities/teardown.d.ts.map +1 -0
  175. package/dist/op/activities/util.d.ts +7 -0
  176. package/dist/op/activities/util.d.ts.map +1 -0
  177. package/dist/op/activities/wait.d.ts +28 -0
  178. package/dist/op/activities/wait.d.ts.map +1 -0
  179. package/dist/op/activities/workflow-audit.d.ts +92 -0
  180. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  181. package/dist/op/activity-contract-registry.d.ts +76 -0
  182. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  183. package/dist/op/activity-contract.d.ts +25 -18
  184. package/dist/op/activity-contract.d.ts.map +1 -1
  185. package/dist/op/activity-failure.d.ts +28 -0
  186. package/dist/op/activity-failure.d.ts.map +1 -0
  187. package/dist/op/activity-profiles.d.ts +118 -0
  188. package/dist/op/activity-profiles.d.ts.map +1 -0
  189. package/dist/op/activity-registry.d.ts +22 -38
  190. package/dist/op/activity-registry.d.ts.map +1 -1
  191. package/dist/op/activity-runtime.d.ts +3 -14
  192. package/dist/op/activity-runtime.d.ts.map +1 -1
  193. package/dist/op/builders.d.ts +84 -29
  194. package/dist/op/builders.d.ts.map +1 -1
  195. package/dist/op/composites/apply-op.d.ts +113 -0
  196. package/dist/op/composites/apply-op.d.ts.map +1 -0
  197. package/dist/op/composites/converge-op.d.ts +120 -0
  198. package/dist/op/composites/converge-op.d.ts.map +1 -0
  199. package/dist/op/composites/index.d.ts +26 -0
  200. package/dist/op/composites/index.d.ts.map +1 -0
  201. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  202. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  203. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  204. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  205. package/dist/op/composites/reconcile-op.d.ts +57 -0
  206. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  207. package/dist/op/composites/watch-op.d.ts +60 -0
  208. package/dist/op/composites/watch-op.d.ts.map +1 -0
  209. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  210. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  211. package/dist/op/converge-rule.d.ts +12 -10
  212. package/dist/op/converge-rule.d.ts.map +1 -1
  213. package/dist/op/cron.d.ts +51 -0
  214. package/dist/op/cron.d.ts.map +1 -0
  215. package/dist/op/discover.d.ts +9 -0
  216. package/dist/op/discover.d.ts.map +1 -1
  217. package/dist/op/duration.d.ts +11 -0
  218. package/dist/op/duration.d.ts.map +1 -0
  219. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  220. package/dist/op/gate.d.ts +90 -0
  221. package/dist/op/gate.d.ts.map +1 -0
  222. package/dist/op/generate-pipeline.d.ts +9 -0
  223. package/dist/op/generate-pipeline.d.ts.map +1 -1
  224. package/dist/op/index.d.ts +23 -7
  225. package/dist/op/index.d.ts.map +1 -1
  226. package/dist/op/local-executor.d.ts +114 -28
  227. package/dist/op/local-executor.d.ts.map +1 -1
  228. package/dist/op/local-output.d.ts +11 -1
  229. package/dist/op/local-output.d.ts.map +1 -1
  230. package/dist/op/op-ir.d.ts +184 -0
  231. package/dist/op/op-ir.d.ts.map +1 -0
  232. package/dist/op/op-verb-class.d.ts +10 -2
  233. package/dist/op/op-verb-class.d.ts.map +1 -1
  234. package/dist/op/operator.d.ts +30 -5
  235. package/dist/op/operator.d.ts.map +1 -1
  236. package/dist/op/receipt-store.d.ts +1 -1
  237. package/dist/op/receipt-store.d.ts.map +1 -1
  238. package/dist/op/resource.d.ts +15 -1
  239. package/dist/op/resource.d.ts.map +1 -1
  240. package/dist/op/runtime.d.ts +200 -0
  241. package/dist/op/runtime.d.ts.map +1 -0
  242. package/dist/op/runtimes/local.d.ts +29 -0
  243. package/dist/op/runtimes/local.d.ts.map +1 -0
  244. package/dist/op/step-output-ref.d.ts +15 -13
  245. package/dist/op/step-output-ref.d.ts.map +1 -1
  246. package/dist/op/types.d.ts +79 -27
  247. package/dist/op/types.d.ts.map +1 -1
  248. package/dist/ownership.d.ts +1 -1
  249. package/dist/provenance.d.ts +21 -0
  250. package/dist/provenance.d.ts.map +1 -1
  251. package/dist/serializer-walker.d.ts.map +1 -1
  252. package/dist/stack-output.d.ts +5 -0
  253. package/dist/stack-output.d.ts.map +1 -1
  254. package/package.json +6 -1
  255. package/src/audit/catalog.test.ts +79 -3
  256. package/src/audit/catalog.ts +111 -13
  257. package/src/audit/core.test.ts +26 -0
  258. package/src/audit/core.ts +61 -17
  259. package/src/audit/discover.test.ts +39 -0
  260. package/src/audit/discover.ts +91 -15
  261. package/src/audit/lineage.ts +100 -0
  262. package/src/audit/prior-art.ts +153 -0
  263. package/src/audit/proof.test.ts +67 -0
  264. package/src/audit/proof.ts +70 -0
  265. package/src/audit/report-html.ts +9 -4
  266. package/src/audit/report-model.ts +16 -2
  267. package/src/audit/report.test.ts +33 -0
  268. package/src/audit/report.ts +5 -3
  269. package/src/audit/rules-doc.test.ts +34 -2
  270. package/src/audit/rules-doc.ts +82 -9
  271. package/src/audit/secrets.ts +15 -3
  272. package/src/audit/terraform-state.test.ts +144 -0
  273. package/src/audit/terraform-state.ts +131 -0
  274. package/src/build.ts +31 -1
  275. package/src/claimed-fields.test.ts +145 -0
  276. package/src/claimed-fields.ts +208 -0
  277. package/src/cli/build-params-cli.ts +2 -2
  278. package/src/cli/command-group.ts +14 -0
  279. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  280. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  281. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  282. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  283. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  284. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  285. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  286. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  287. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  288. package/src/cli/commands/audit.test.ts +189 -11
  289. package/src/cli/commands/audit.ts +73 -27
  290. package/src/cli/commands/build.test.ts +292 -9
  291. package/src/cli/commands/build.ts +156 -24
  292. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  293. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  294. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  295. package/src/cli/commands/import.ts +6 -0
  296. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  297. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  298. package/src/cli/commands/init-lexicon.test.ts +97 -2
  299. package/src/cli/commands/init-lexicon.ts +4 -2
  300. package/src/cli/commands/init.test.ts +35 -1
  301. package/src/cli/commands/init.ts +14 -3
  302. package/src/cli/commands/lint.test.ts +48 -0
  303. package/src/cli/commands/lint.ts +123 -0
  304. package/src/cli/commands/onboard.test.ts +75 -0
  305. package/src/cli/commands/onboard.ts +54 -23
  306. package/src/cli/handlers/build.test.ts +81 -1
  307. package/src/cli/handlers/build.ts +15 -1
  308. package/src/cli/handlers/graph.test.ts +3 -3
  309. package/src/cli/handlers/lifecycle.test.ts +195 -12
  310. package/src/cli/handlers/lifecycle.ts +123 -6
  311. package/src/cli/handlers/misc.ts +1 -1
  312. package/src/cli/handlers/operator.test.ts +183 -11
  313. package/src/cli/handlers/operator.ts +260 -55
  314. package/src/cli/handlers/run.test.ts +431 -1287
  315. package/src/cli/handlers/run.ts +365 -915
  316. package/src/cli/main.test.ts +23 -15
  317. package/src/cli/main.ts +88 -33
  318. package/src/cli/mcp/op-tools.ts +147 -88
  319. package/src/cli/mcp/resource-handlers.ts +10 -37
  320. package/src/cli/mcp/resources/context.ts +11 -12
  321. package/src/cli/mcp/server.test.ts +25 -27
  322. package/src/cli/mcp/server.ts +2 -2
  323. package/src/cli/registry.ts +26 -9
  324. package/src/codegen/docs.ts +1 -1
  325. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  326. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  327. package/src/components/README.md +3 -2
  328. package/src/components/auto-release.test.ts +4 -20
  329. package/src/components/auto-release.ts +17 -42
  330. package/src/components/capability.ts +4 -4
  331. package/src/components/cli-support.test.ts +10 -5
  332. package/src/components/cli-support.ts +52 -44
  333. package/src/components/component.schema.json +2 -2
  334. package/src/components/component.ts +3 -3
  335. package/src/components/driver-output.ts +14 -2
  336. package/src/components/driver.test.ts +92 -22
  337. package/src/components/driver.ts +193 -83
  338. package/src/components/index.ts +1 -6
  339. package/src/components/manifest-persistence.test.ts +2 -20
  340. package/src/components/manifest-persistence.ts +4 -24
  341. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  342. package/src/components/run-progress.ts +6 -6
  343. package/src/components/verbs/run-agent.ts +11 -17
  344. package/src/components/verbs/verify.ts +2 -2
  345. package/src/deep-observation.test.ts +75 -0
  346. package/src/deep-observation.ts +48 -0
  347. package/src/discovery/collect.test.ts +3 -3
  348. package/src/discovery/files.ts +4 -4
  349. package/src/discovery/fold-import.ts +105 -2
  350. package/src/discovery/param-deps.test.ts +112 -1
  351. package/src/discovery/param-deps.ts +193 -0
  352. package/src/discovery/sandbox/bundle.ts +15 -1
  353. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  354. package/src/discovery/sandbox/config-wire.ts +2 -2
  355. package/src/fold/fold.test.ts +56 -0
  356. package/src/fold/foldable-helpers.ts +81 -1
  357. package/src/fold-provenance-exclusion.test.ts +186 -0
  358. package/src/fold-provenance.test.ts +495 -0
  359. package/src/fold-provenance.ts +441 -0
  360. package/src/graph-ops.test.ts +2 -2
  361. package/src/graph-ops.ts +1 -1
  362. package/src/held-elsewhere.test.ts +102 -0
  363. package/src/held-elsewhere.ts +114 -0
  364. package/src/import/ir-utils.ts +11 -1
  365. package/src/import/parser.ts +35 -0
  366. package/src/index.ts +3 -0
  367. package/src/kubectl-context.ts +3 -3
  368. package/src/lexicon-config.test.ts +5 -5
  369. package/src/lexicon-config.ts +4 -4
  370. package/src/lexicon-plugin-helpers.ts +1 -1
  371. package/src/lexicon.ts +120 -14
  372. package/src/lifecycle/change-set.test.ts +49 -0
  373. package/src/lifecycle/change-set.ts +67 -0
  374. package/src/lifecycle/converge-ledger.ts +1 -1
  375. package/src/lifecycle/deep-diff.test.ts +267 -14
  376. package/src/lifecycle/deep-diff.ts +217 -14
  377. package/src/lifecycle/deep-observe.test.ts +3 -1
  378. package/src/lifecycle/deep-observe.ts +16 -6
  379. package/src/lifecycle/gate-ledger.test.ts +74 -2
  380. package/src/lifecycle/gate-ledger.ts +143 -36
  381. package/src/lifecycle/index.ts +1 -0
  382. package/src/lifecycle/release-ledger.ts +2 -2
  383. package/src/lifecycle/run-ledger.test.ts +268 -0
  384. package/src/lifecycle/run-ledger.ts +201 -0
  385. package/src/lifecycle/symptoms.ts +3 -3
  386. package/src/lint/config.test.ts +82 -1
  387. package/src/lint/config.ts +112 -3
  388. package/src/lint/policy.test.ts +1 -1
  389. package/src/lint/post-synth.test.ts +31 -0
  390. package/src/lint/post-synth.ts +54 -1
  391. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  392. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  393. package/src/lint/rules/comp/comp.test.ts +1 -1
  394. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
  395. package/src/lint/rules/comp/index.ts +3 -3
  396. package/src/lint/rules/op/index.ts +23 -0
  397. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  398. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  399. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  400. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  401. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  402. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  403. package/src/lint/rules/op/support.ts +11 -0
  404. package/src/lint/suppressions.test.ts +163 -0
  405. package/src/lint/suppressions.ts +204 -0
  406. package/src/live-endpoint.ts +1 -1
  407. package/src/op/activities/activity-contracts.ts +66 -0
  408. package/src/op/activities/apply.test.ts +567 -0
  409. package/src/op/activities/apply.ts +662 -0
  410. package/src/op/activities/build.ts +26 -0
  411. package/src/op/activities/converge.test.ts +330 -0
  412. package/src/op/activities/converge.ts +449 -0
  413. package/src/op/activities/env-teardown.test.ts +187 -0
  414. package/src/op/activities/env-teardown.ts +171 -0
  415. package/src/op/activities/guard-validate.test.ts +139 -0
  416. package/src/op/activities/guard-validate.ts +223 -0
  417. package/src/op/activities/http-check.test.ts +48 -0
  418. package/src/op/activities/http-check.ts +55 -0
  419. package/src/op/activities/index.ts +119 -0
  420. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  421. package/src/op/activities/lexicon-upgrade.ts +673 -0
  422. package/src/op/activities/lifecycle.ts +85 -0
  423. package/src/op/activities/pipeline-audit.test.ts +67 -0
  424. package/src/op/activities/pipeline-audit.ts +201 -0
  425. package/src/op/activities/policy.test.ts +19 -0
  426. package/src/op/activities/policy.ts +37 -0
  427. package/src/op/activities/reconcile.test.ts +81 -0
  428. package/src/op/activities/reconcile.ts +187 -0
  429. package/src/op/activities/shell.ts +26 -0
  430. package/src/op/activities/teardown.ts +22 -0
  431. package/src/op/activities/util.ts +6 -0
  432. package/src/op/activities/wait.ts +69 -0
  433. package/src/op/activities/workflow-audit.test.ts +90 -0
  434. package/src/op/activities/workflow-audit.ts +203 -0
  435. package/src/op/activity-contract-registry.test.ts +98 -0
  436. package/src/op/activity-contract-registry.ts +114 -0
  437. package/src/op/activity-contract.test.ts +1 -1
  438. package/src/op/activity-contract.ts +37 -33
  439. package/src/op/activity-failure.ts +34 -0
  440. package/src/op/activity-profiles.test.ts +56 -0
  441. package/src/op/activity-profiles.ts +116 -0
  442. package/src/op/activity-registry.test.ts +37 -28
  443. package/src/op/activity-registry.ts +27 -56
  444. package/src/op/activity-runtime.ts +3 -47
  445. package/src/op/builders-exports.test.ts +0 -49
  446. package/src/op/builders-typed.test.ts +164 -0
  447. package/src/op/builders.ts +123 -39
  448. package/src/op/composites/apply-op.ts +208 -0
  449. package/src/op/composites/composites.test.ts +366 -0
  450. package/src/op/composites/converge-op.test.ts +168 -0
  451. package/src/op/composites/converge-op.ts +214 -0
  452. package/src/op/composites/index.ts +26 -0
  453. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  454. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  455. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  456. package/src/op/composites/pipeline-audit-op.ts +78 -0
  457. package/src/op/composites/reconcile-op.test.ts +51 -0
  458. package/src/op/composites/reconcile-op.ts +107 -0
  459. package/src/op/composites/watch-op.ts +108 -0
  460. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  461. package/src/op/composites/workflow-audit-op.ts +88 -0
  462. package/src/op/converge-rule.ts +12 -10
  463. package/src/op/cron.test.ts +128 -0
  464. package/src/op/cron.ts +149 -0
  465. package/src/op/discover-root.test.ts +105 -1
  466. package/src/op/discover.test.ts +6 -2
  467. package/src/op/discover.ts +84 -16
  468. package/src/op/duration.ts +21 -0
  469. package/src/op/effect-step.test.ts +26 -11
  470. package/src/op/emulator-lifecycle.ts +1 -2
  471. package/src/op/gate.ts +155 -0
  472. package/src/op/generate-pipeline.test.ts +65 -3
  473. package/src/op/generate-pipeline.ts +19 -2
  474. package/src/op/index.ts +39 -6
  475. package/src/op/local-executor.test.ts +163 -34
  476. package/src/op/local-executor.ts +370 -102
  477. package/src/op/local-output.test.ts +95 -11
  478. package/src/op/local-output.ts +33 -4
  479. package/src/op/op-ir.test.ts +281 -0
  480. package/src/op/op-ir.ts +417 -0
  481. package/src/op/op-verb-class.ts +19 -5
  482. package/src/op/op.test.ts +26 -5
  483. package/src/op/operator.test.ts +175 -6
  484. package/src/op/operator.ts +63 -16
  485. package/src/op/receipt-store.ts +1 -1
  486. package/src/op/resource.ts +20 -2
  487. package/src/op/runtime.ts +203 -0
  488. package/src/op/runtimes/local.test.ts +181 -0
  489. package/src/op/runtimes/local.ts +212 -0
  490. package/src/op/step-output-ref.ts +15 -13
  491. package/src/op/types.ts +84 -24
  492. package/src/ownership.ts +1 -1
  493. package/src/provenance.test.ts +6 -0
  494. package/src/provenance.ts +21 -1
  495. package/src/serializer-walker.test.ts +42 -0
  496. package/src/serializer-walker.ts +21 -2
  497. package/src/stack-output.ts +6 -1
  498. package/dist/cli/handlers/op-progress.d.ts +0 -90
  499. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  500. package/dist/cli/handlers/run-client.d.ts +0 -127
  501. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  502. package/dist/cli/handlers/run-report.d.ts +0 -5
  503. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  504. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  505. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  506. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  507. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  508. package/src/cli/handlers/op-progress.test.ts +0 -268
  509. package/src/cli/handlers/op-progress.ts +0 -248
  510. package/src/cli/handlers/run-client.test.ts +0 -82
  511. package/src/cli/handlers/run-client.ts +0 -219
  512. package/src/cli/handlers/run-report.test.ts +0 -62
  513. package/src/cli/handlers/run-report.ts +0 -122
  514. package/src/components/temporal-codegen-loader.ts +0 -41
  515. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -95,7 +95,7 @@ export {
95
95
  accumulateComponentOutputs,
96
96
  runComponentDeploy,
97
97
  runInterpretDriver,
98
- DriverGateUnsupportedError,
98
+ type GateContext,
99
99
  DependencyCycleError,
100
100
  UnknownDependencyError,
101
101
  DriverRunFailure,
@@ -108,8 +108,3 @@ export {
108
108
  SingleHostComposeComponent,
109
109
  type SingleHostComposeComponentConfig,
110
110
  } from "./presets/index";
111
- export {
112
- type ComponentTemporalCodegen,
113
- type ComponentTemporalCodegenOptions,
114
- loadComponentTemporalCodegen,
115
- } from "./temporal-codegen-loader";
@@ -16,7 +16,6 @@ vi.mock("../lifecycle/git", () => ({
16
16
  const {
17
17
  maybePersistBuildManifest,
18
18
  extractRunManifest,
19
- extractRunManifestFromPhaseOutputs,
20
19
  } = await import("./manifest-persistence");
21
20
 
22
21
  function makeManifest(component: string, digest: string): BuildArchiveManifest {
@@ -67,23 +66,6 @@ describe("extractRunManifest", () => {
67
66
  });
68
67
  });
69
68
 
70
- describe("extractRunManifestFromPhaseOutputs", () => {
71
- test("finds the manifest across phase outputs (Temporal workflow result shape)", () => {
72
- const manifest = makeManifest("svc", "sha256:abc");
73
- expect(
74
- extractRunManifestFromPhaseOutputs({
75
- Build: { archivePath: "image.tar", digest: "sha256:abc", manifest },
76
- Apply: { ok: true },
77
- }),
78
- ).toEqual(manifest);
79
- });
80
-
81
- test("returns undefined for undefined/empty phaseOutputs", () => {
82
- expect(extractRunManifestFromPhaseOutputs(undefined)).toBeUndefined();
83
- expect(extractRunManifestFromPhaseOutputs({})).toBeUndefined();
84
- });
85
- });
86
-
87
69
  describe("maybePersistBuildManifest", () => {
88
70
  beforeEach(() => {
89
71
  persistBuildManifestMock.mockReset();
@@ -102,8 +84,8 @@ describe("maybePersistBuildManifest", () => {
102
84
  expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
103
85
  });
104
86
 
105
- test("a pre-resolved manifest (Temporal path) takes precedence over records", async () => {
106
- const preResolved = makeManifest("svc", "sha256:temporal");
87
+ test("a pre-resolved manifest takes precedence over records", async () => {
88
+ const preResolved = makeManifest("svc", "sha256:preresolved");
107
89
  persistBuildManifestMock.mockResolvedValue({ commit: "b".repeat(40) });
108
90
 
109
91
  const outcome = await maybePersistBuildManifest({
@@ -13,10 +13,9 @@
13
13
  * doc: a manifest write is a git commit + push, a non-idempotent side effect
14
14
  * with real-world I/O — exactly what `driver.ts` resists taking on (it is
15
15
  * exercised in tests against a bare `CapabilityRegistry` with no lifecycle
16
- * dependency at all) and what Temporal workflow code must never do directly
17
- * (replay-safety). The CLI calls this after `runComponents`/`handle.result()`
18
- * reports success, the same place `maybeRecordAutoRelease` is already
19
- * called from (../cli/handlers/run.ts).
16
+ * dependency at all). The CLI calls this after `runComponents` reports
17
+ * success, the same place `maybeRecordAutoRelease` is already called from
18
+ * (../cli/handlers/run.ts).
20
19
  *
21
20
  * **Extraction is duck-typed, not capability-specific.** `docker-build`,
22
21
  * `generate-sbom`, `extract-config-bom`, and `addArchiveTemplate` (the
@@ -68,25 +67,6 @@ export function extractRunManifest(records: DriverStepRecord[]): BuildArchiveMan
68
67
  return found;
69
68
  }
70
69
 
71
- /**
72
- * Same manifest extraction as `extractRunManifest`, but over a component
73
- * Temporal workflow's returned `phaseOutputs` (`{ [phase]: output }`) —
74
- * mirroring ./auto-release.ts's `extractRunDigestFromPhaseOutputs`, the
75
- * `--temporal` CLI path's counterpart, since that path never sees individual
76
- * step records either.
77
- */
78
- export function extractRunManifestFromPhaseOutputs(
79
- phaseOutputs: Record<string, Record<string, unknown>> | undefined,
80
- ): BuildArchiveManifest | undefined {
81
- let found: BuildArchiveManifest | undefined;
82
- for (const output of Object.values(phaseOutputs ?? {})) {
83
- if (isManifestShaped(output)) {
84
- found = output.manifest;
85
- }
86
- }
87
- return found;
88
- }
89
-
90
70
  /** Explicit reasons `maybePersistBuildManifest` declined to write — never a thrown error, mirroring ./auto-release.ts's `AutoReleaseSkipReason`. */
91
71
  export type ManifestPersistSkipReason = "opted-out" | "run-not-successful" | "no-manifest";
92
72
 
@@ -101,7 +81,7 @@ export interface ManifestPersistRunInfo {
101
81
  success: boolean;
102
82
  /** The component's step records (local executor), used to locate the accumulated manifest via `extractRunManifest`. Mutually exclusive with `manifest`. */
103
83
  records?: DriverStepRecord[];
104
- /** A manifest already resolved by the caller (e.g. a future durable/Temporal path that has its own phaseOutputs-shaped extraction). Takes precedence over `records` when both are given. */
84
+ /** A manifest the caller already resolved by its own means. Takes precedence over `records` when both are given. */
105
85
  manifest?: BuildArchiveManifest;
106
86
  }
107
87
 
@@ -52,17 +52,18 @@ describe("Real pilots lint clean under COMP* (#562 acceptance criteria)", () =>
52
52
  expect(runAll(ctx)).toEqual([]);
53
53
  });
54
54
 
55
- it("the Neo4j fan-out pilot produces zero COMP* diagnostics other than the expected COMP004 (gate requires Temporal)", () => {
55
+ it("the Neo4j fan-out pilot produces zero COMP* diagnostics other than the expected COMP004 (a gate ends the run pending approval)", () => {
56
56
  // The Neo4j pilot's Node-1 approval gate is a deliberate design choice
57
- // (see neo4j-fanout.pilot.ts's own docstring and
58
- // ../driver.ts's DriverGateUnsupportedError / docs/components/
59
- // orchestration.mdx's "Temporal is optional" aside) — it is the one real
60
- // pilot that genuinely needs the durable backend, so COMP004 firing here
61
- // is the *correct*, expected signal, not a defect. A real project would
62
- // acknowledge it with `// chant-disable-next-line COMP004 -- <reason>`
63
- // once authored as an actual `*.component.ts` file (see
64
- // ../../lint/rules/comp/comp004-gate-needs-temporal.ts and the
65
- // comp004/pass fixture demonstrating that opt-out end to end).
57
+ // (see neo4j-fanout.pilot.ts's own docstring, and ../driver.ts on
58
+ // gate-as-fact, #2119) — a run reaching it stops there pending `chant
59
+ // approve`, which is exactly the standing human wait COMP004 exists to
60
+ // surface, so COMP004 firing here is the *correct*, expected signal, not
61
+ // a defect. A real project would acknowledge it with a file-level
62
+ // `// chant-disable COMP004 -- <reason>` once authored as an actual
63
+ // `*.component.ts` file — a COMP* diagnostic is reported for the whole
64
+ // component and carries no line, so `-line`/`-next-line` do not suppress
65
+ // one (see ../../lint/rules/comp/comp004-gate-needs-durable-runtime.ts
66
+ // and the comp004/pass fixture demonstrating that opt-out end to end).
66
67
  const ctx = contextFor([neo4jCluster]);
67
68
  const diagnostics = runAll(ctx);
68
69
  expect(diagnostics.every((d) => d.checkId === "COMP004")).toBe(true);
@@ -10,17 +10,17 @@
10
10
  * single-component path, ./cli-support.ts's `runComponents`), that never
11
11
  * changes run ordering, gating, `onFailure`, rollback, or exit codes — it
12
12
  * only reports what already happened, as it happens. See ./driver.ts's
13
- * module doc for what actually executes; streaming progress on the *durable*
14
- * (Temporal) path is a separate, later concern (Temporal already exposes
15
- * durable run state via `chant run status`/`log`).
13
+ * module doc for what actually executes; streaming progress from a hosted
14
+ * runtime is a separate, later concern (`chant run status`/`log` already ask
15
+ * one for the run state it keeps).
16
16
  *
17
17
  * `RunProgressEvent` is a discriminated union on `type`, one JSON object per
18
18
  * NDJSON line (see `ndjsonProgressSink` below and
19
19
  * ../cli/handlers/run.ts's `--progress-json` wiring).
20
20
  */
21
21
 
22
- /** Terminal status for a wave/component/phase/run — mirrors DriverStepRecord's ok/fail split, collapsed to the two outcomes a consumer renders progress against. */
23
- export type RunProgressStatus = "ok" | "failed";
22
+ /** Terminal status for a wave/component/phase/run — mirrors `DriverRunResult.status`'s three outcomes (#2119): `gated` is neither, and reporting it as `failed` would have a progress consumer page someone for a decision nobody has made yet. */
23
+ export type RunProgressStatus = "ok" | "failed" | "gated";
24
24
 
25
25
  /** The run is about to start. `waves` are the parallel-safe waves the run will attempt, in order (see resolveComponentGraph) — 1-based wave numbers in every other event index into this array. */
26
26
  export interface RunStartEvent {
@@ -108,7 +108,7 @@ export type RunProgressSink = (event: RunProgressEvent) => void;
108
108
  * Build a sink that writes `JSON.stringify(event) + "\n"` to `write` (default:
109
109
  * `process.stdout.write`), one line per event, as they happen — the
110
110
  * `--progress-json` CLI wiring's sink (../cli/handlers/run.ts, for both the
111
- * `--components` driver's `RunProgressEvent`s and the Temporal Op path's
111
+ * `--components` driver's `RunProgressEvent`s and the Op path's
112
112
  * `StepRecord`s, chant #1676). Kept separate from `driver-output.ts`'s
113
113
  * end-of-run renderers: this emits *during* the run, one line at a time;
114
114
  * `renderDriverJson`/`renderDriverHuman` render the completed
@@ -86,9 +86,8 @@
86
86
  * `run(ctx, input)` was called with, plus (since #1944) the exact `output`
87
87
  * `run()` returned — `../capability.ts`'s `Capability.rollback` grew an
88
88
  * optional third parameter for precisely this, and ../driver.ts's saga
89
- * unwind (both the local in-process path and, via
90
- * `lexicons/temporal/src/component-op/{activities,serializer}.ts`, the
91
- * durable Temporal path) always threads it through. `run()` records the
89
+ * unwind (and any hosting runtime that splits `run`/`rollback` across
90
+ * process boundaries) always threads it through. `run()` records the
92
91
  * sprite id and exact pre-run checkpoint id two ways: in a private
93
92
  * `WeakMap` keyed by the exact `input` object (works only when `rollback`
94
93
  * is called with that same object — true in-process, e.g. this module's
@@ -115,18 +114,13 @@
115
114
  * commented no-op return — the same pattern
116
115
  * `../../lexicons/aws/src/components/host-delivery.ts`'s `code-deploy`
117
116
  * rollback uses (`if (!deploymentId) return;`) — rather than throwing.
118
- * **Before #1944**, the Temporal durable path (`run` and `rollback`
119
- * executing as separate Activities, each rebuilding `input` fresh via
120
- * `resolveStepInput`) never gave the `WeakMap` a hit, so a fresh sprite's
121
- * rollback there silently degraded to that no-op; passing `output` through
122
- * (this revision) closes that gap directly, without redesigning the
123
- * component-op wire format — see #1944's PR description for why this was
124
- * chosen over the "make the degrade loud" alternative. The generated
125
- * workflow's saga-unwind loop (`lexicons/temporal/src/component-op/
126
- * serializer.ts`) also no longer swallows a rollback failure silently
127
- * (any capability's, not just this one) — it now logs it and surfaces it
128
- * via a `RollbackFailed` search attribute, defense in depth for a rollback
129
- * failure unrelated to identity (e.g. the sprite backend itself erroring).
117
+ * **Before #1944**, a hosted path running `run` and `rollback` as separate
118
+ * units of work — each rebuilding `input` fresh via `resolveStepInput` —
119
+ * never gave the `WeakMap` a hit, so a fresh sprite's rollback there
120
+ * silently degraded to that no-op; passing `output` through (this revision)
121
+ * closes that gap directly, without redesigning the component-op wire
122
+ * format — see #1944's PR description for why this was chosen over the
123
+ * "make the degrade loud" alternative.
130
124
  * - **Destroy vs. leave-alive.** `run()` destroys a freshly created (not
131
125
  * `workspace.spriteName`-reused) sprite only when `turn.status ===
132
126
  * "completed"`. An ordinary failed turn leaves the sprite alive — it
@@ -526,8 +520,8 @@ export function createRunAgentCapability(
526
520
  async rollback(_ctx, input, output): Promise<void> {
527
521
  // The durable-safe channel first (#1944): `output` is the exact value
528
522
  // this step's own `run()` returned, threaded through by every current
529
- // caller (../driver.ts locally, lexicons/temporal/src/component-op/
530
- // {activities,serializer}.ts across the Activity boundary) — it
523
+ // caller (../driver.ts locally, and a hosting runtime across whatever
524
+ // process boundary it puts between the two) — it
531
525
  // survives even when `rollback()` is called with a freshly-rebuilt
532
526
  // `input` object the in-process WeakMap below has never seen. Falls
533
527
  // back to the WeakMap for a caller that predates/never threads
@@ -6,8 +6,8 @@
6
6
  * configured identity policy and **throws** on any failure, so composing it
7
7
  * before an apply phase fails the deploy the same way a thrown capability
8
8
  * error already halts `driver.ts`'s step execution — no new failure
9
- * mechanism, no gate-signal/human-approval semantics (that is `Gate`,
10
- * ../component.ts, a different, durable-runtime-only concept). `verify` is a
9
+ * mechanism, no human-approval semantics (that is `Gate`, ../component.ts, a
10
+ * different concept: a fact on the gate ledger). `verify` is a
11
11
  * synchronous, local-executor-safe capability, exactly like `health-gate`
12
12
  * (./wait-verify.ts).
13
13
  *
@@ -12,6 +12,7 @@ import {
12
12
  normalizeDeepProperties,
13
13
  type DeepNormalizationHooks,
14
14
  } from "./deep-observation";
15
+ import { HELD_ELSEWHERE_TAG, heldElsewhere, isNormalizedHeldElsewhere } from "./held-elsewhere";
15
16
 
16
17
  describe("the deep observation envelope", () => {
17
18
  test("is discriminated by its version literal", () => {
@@ -319,6 +320,80 @@ describe("deepValueEqual", () => {
319
320
  });
320
321
  });
321
322
 
323
+ // #2162 — a `heldElsewhere()` marker is declared on purpose, not authored
324
+ // data to walk into and not an unresolved intrinsic. It must survive
325
+ // normalization as one recognizable leaf, all the way through
326
+ // `flattenDeepProperties` and `deepPathSet`, or `deep-diff.ts` has nothing
327
+ // to key its held classification on.
328
+ describe("normalizeDeepProperties — heldElsewhere() markers (#2162)", () => {
329
+ test("normalizes to a JSON-safe tagged leaf rather than being walked as a two-key object", () => {
330
+ const out = normalizeDeepProperties(
331
+ { replicas: heldElsewhere<number>({ by: "hpa", reason: "the autoscaler owns replicas after the first apply" }) },
332
+ { entityType: "Deployment", side: "declared" },
333
+ );
334
+ expect(out).toEqual({
335
+ replicas: { heldElsewhere: HELD_ELSEWHERE_TAG, by: "hpa", reason: "the autoscaler owns replicas after the first apply" },
336
+ });
337
+ expect(isNormalizedHeldElsewhere(out.replicas)).toBe(true);
338
+ });
339
+
340
+ test("is not masked, unresolved, or subjected to a lexicon's own hooks", () => {
341
+ const out = normalizeDeepProperties(
342
+ { password: heldElsewhere<string>({ by: "operator", reason: "rotated out of band" }) },
343
+ {
344
+ entityType: "T",
345
+ side: "declared",
346
+ // Scoped to the one path under test — a hook that fires on every
347
+ // node (including the root) would mask/unresolve the whole tree,
348
+ // which is a hazard of the hook, not something this test is after.
349
+ hooks: { unresolved: (n) => n.path === "password", mask: (n) => n.path === "password" },
350
+ },
351
+ );
352
+ // If either hook had run ahead of the held check, this would be
353
+ // UNRESOLVED or MASKED instead — the key name looks secret-bearing
354
+ // (`isSensitiveKey`) and both hooks say yes too, and the held check
355
+ // still has to win.
356
+ expect(isNormalizedHeldElsewhere(out.password)).toBe(true);
357
+ });
358
+
359
+ test("nested inside a property-kind declarable, still normalizes to the tagged leaf", () => {
360
+ const propertyDeclarable = (entityType: string, props: Record<string, unknown>) => ({
361
+ entityType,
362
+ kind: "property",
363
+ props,
364
+ });
365
+ const out = normalizeDeepProperties(
366
+ {
367
+ Behavior: propertyDeclarable("HorizontalPodAutoscaler.Behavior", {
368
+ scaleUp: heldElsewhere<Record<string, unknown>>({ by: "hpa", reason: "the controller tunes its own policy" }),
369
+ }),
370
+ },
371
+ { entityType: "HorizontalPodAutoscaler", side: "declared" },
372
+ );
373
+ expect(isNormalizedHeldElsewhere((out.Behavior as Record<string, unknown>).scaleUp)).toBe(true);
374
+ });
375
+ });
376
+
377
+ describe("flattenDeepProperties — heldElsewhere() markers (#2162)", () => {
378
+ test("addresses the marker as one leaf path, not two", () => {
379
+ const normalized = normalizeDeepProperties(
380
+ { replicas: heldElsewhere<number>({ by: "hpa", reason: "x" }) },
381
+ { entityType: "Deployment", side: "declared" },
382
+ );
383
+ const flat = flattenDeepProperties(normalized);
384
+ expect([...flat.keys()]).toEqual(["replicas"]);
385
+ expect(isNormalizedHeldElsewhere(flat.get("replicas"))).toBe(true);
386
+ });
387
+ });
388
+
389
+ describe("deepPathSet — heldElsewhere() markers (#2162)", () => {
390
+ test("records the held property's own path, not synthetic sub-paths into by/reason", () => {
391
+ const marker = heldElsewhere<number>({ by: "hpa", reason: "x" });
392
+ const set = deepPathSet({ replicas: marker });
393
+ expect([...set].sort()).toEqual(["replicas"]);
394
+ });
395
+ });
396
+
322
397
  // #1314 — a nested property authored through a lexicon's generated constructor
323
398
  // is authored data, not an opaque class instance. Collapsing it to UNRESOLVED
324
399
  // left the declared side empty while the live side held the real value, so
@@ -44,6 +44,7 @@
44
44
  */
45
45
 
46
46
  import type { UnobservedEntity } from "./observation";
47
+ import { isHeldElsewhere, isNormalizedHeldElsewhere, normalizeHeldElsewhere } from "./held-elsewhere";
47
48
 
48
49
  /**
49
50
  * A live property tree for one declared entity, already normalized by the
@@ -67,6 +68,23 @@ export interface DeepResourceObservation {
67
68
  * very different answers to an operator.
68
69
  */
69
70
  fieldOwners?: Record<string, string>;
71
+ /**
72
+ * The paths this entity's declaration claims (#2160) — every property chant
73
+ * set, flattened into the diff's own grammar and sorted. Built by core in
74
+ * `lifecycle/deep-observe.ts` from the declaration's `props`, never by a
75
+ * reader: a lexicon has no more to say about it than the props it was handed.
76
+ *
77
+ * It rides here, on the live row, because this is the envelope a consumer
78
+ * holds. With it, a live value classifies three ways instead of two — chant
79
+ * set this and it matches, chant set this and it moved, chant never set it —
80
+ * and only the middle one is drift. Absent for a live entity nobody declared,
81
+ * which has no claim to carry.
82
+ *
83
+ * Complementary to {@link fieldOwners} rather than a replacement: the manager
84
+ * name says *who* holds a field, which is strictly more than "not chant". See
85
+ * `../claimed-fields.ts`.
86
+ */
87
+ claimedFields?: readonly string[];
70
88
  }
71
89
 
72
90
  /**
@@ -340,6 +358,11 @@ export function deepPathSet(tree: Record<string, unknown>): Set<string> {
340
358
  out.add(path);
341
359
  out.add(pattern);
342
360
  }
361
+ // A held marker (#2162) is one declared value, not a `{ by, reason }`
362
+ // object to walk into — same leaf treatment `normalizeDeepProperties`
363
+ // gives it, so this path set agrees with what the normalized tree
364
+ // actually looks like a path down.
365
+ if (isHeldElsewhere(value)) return;
343
366
  if (Array.isArray(value)) {
344
367
  value.forEach((el, i) => walk(el, joinIndex(path, i), joinPattern(pattern)));
345
368
  return;
@@ -418,6 +441,24 @@ export function normalizeDeepProperties(
418
441
  };
419
442
 
420
443
  const normalizeValue = (value: unknown, path: string, pattern: string, key: string): unknown => {
444
+ // A `heldElsewhere()` marker (#2162) — declared on purpose, not
445
+ // unresolved and not a plain object to walk into. Checked ahead of even
446
+ // the secret-masking rules below: the marker carries no value at all,
447
+ // only who holds the field and why, so there is nothing for masking to
448
+ // protect and masking it would destroy the one thing worth reporting —
449
+ // a `heldElsewhere()` on a `password`-shaped key ("an operator rotates
450
+ // this out of band") must still say so, not collapse to `[REDACTED]`.
451
+ // Normalized to a JSON-safe tagged leaf so its identity survives this
452
+ // pass and a `--json` round-trip; `deep-diff.ts` reads the tag to
453
+ // report a live difference here as held rather than as drift, on
454
+ // either side (a lexicon's own reader never produces this shape, so
455
+ // the check is safe on the live tree too, though only the declared
456
+ // side ever carries one in practice). Checked ahead of the
457
+ // array/object branches too, same reason a property-Declarable is: it
458
+ // would otherwise be walked as a two-key plain object and lose the
459
+ // very identity that makes it a marker rather than authored data.
460
+ if (isHeldElsewhere(value)) return normalizeHeldElsewhere(value);
461
+
421
462
  if (isSensitiveKey(key)) return MASKED;
422
463
  // The lexicon's structural mask — same collapse, path-shaped rather than
423
464
  // key-named (a k8s Secret's `data.*` no matter what the key is called).
@@ -426,6 +467,7 @@ export function normalizeDeepProperties(
426
467
  // expression-string reference — collapses exactly like a class-instance
427
468
  // intrinsic does below.
428
469
  if (hooks?.unresolved?.(nodeOf(path, pattern, key, value))) return UNRESOLVED;
470
+
429
471
  if (isJsonPrimitive(value)) return value;
430
472
 
431
473
  // A PROPERTY-kind Declarable is authored data wearing a class, not an
@@ -567,6 +609,12 @@ export function flattenDeepProperties(
567
609
  };
568
610
 
569
611
  const walk = (value: unknown, path: string, pattern: string): void => {
612
+ // A normalized held marker (#2162) is one value, not a two-key object to
613
+ // descend into — same reason UNRESOLVED and a JSON primitive are leaves.
614
+ if (isNormalizedHeldElsewhere(value)) {
615
+ out.set(path, value);
616
+ return;
617
+ }
570
618
  if (Array.isArray(value)) {
571
619
  if (value.length === 0) {
572
620
  out.set(path, []);
@@ -395,8 +395,8 @@ describe("collectEntities with composites", () => {
395
395
 
396
396
  describe("collectEntities — default exports (op files)", () => {
397
397
  test("two files with `export default` do not collide (keyed per file)", () => {
398
- const apply = createMockEntity("Temporal::Op");
399
- const reconcile = createMockEntity("Temporal::Op");
398
+ const apply = createMockEntity("Chant::Op");
399
+ const reconcile = createMockEntity("Chant::Op");
400
400
  const result = collectEntities([
401
401
  { file: "ops/apply.op.ts", exports: { default: apply } },
402
402
  { file: "ops/reconcile.op.ts", exports: { default: reconcile } },
@@ -409,7 +409,7 @@ describe("collectEntities — default exports (op files)", () => {
409
409
  });
410
410
 
411
411
  test("a single default export is collected (not dropped)", () => {
412
- const op = createMockEntity("Temporal::Op");
412
+ const op = createMockEntity("Chant::Op");
413
413
  const result = collectEntities([{ file: "ops/deploy.op.ts", exports: { default: op } }]);
414
414
  expect(result.get("deploy")).toBe(op);
415
415
  });
@@ -3,10 +3,10 @@ import { existsSync } from "node:fs";
3
3
  import { join, relative } from "node:path";
4
4
 
5
5
  /**
6
- * Marker chant writes at the top of files it generates (worker/workflow/activities
7
- * bootstrap for Temporal Ops, etc.). Discovery must not treat these as authored
8
- * infra source: they hold no Declarables, they self-execute on import (the worker
9
- * bootstrap calls `run()`), and they use runtime patterns the authored-source lint
6
+ * Marker chant writes at the top of files it generates (a hosting lexicon's
7
+ * worker/bootstrap output, and the like). Discovery must not treat these as
8
+ * authored infra source: they hold no Declarables, they self-execute on import,
9
+ * and they use runtime patterns the authored-source lint
10
10
  * rules forbid (dynamic `process.env[...]` access, spreads). Skipping them keeps
11
11
  * `chant lint`/`build` from importing or linting the tool's own output.
12
12
  */
@@ -38,7 +38,11 @@ import {
38
38
  SUPPORTED_UNARY_OPERATORS,
39
39
  } from "../fold/subset";
40
40
  import { importModule } from "./import";
41
- import { collectParamDependencies } from "./param-deps";
41
+ import {
42
+ collectCompositeOrigins,
43
+ collectParamDependencies,
44
+ type CompositeParamScope,
45
+ } from "./param-deps";
42
46
  import { setPathProvenance } from "../provenance";
43
47
  import { intrinsicCallFoldsEagerly, type IntrinsicDef } from "../lexicon";
44
48
  import type { BuildParamValue } from "../build-params";
@@ -1273,6 +1277,29 @@ interface ResolveCtx {
1273
1277
  * terminates it — see {@link MAX_INTERPRETATION_DEPTH}.
1274
1278
  */
1275
1279
  interpretDepth: number;
1280
+ /**
1281
+ * chant #2161 — the composite whose factory body this context is evaluating,
1282
+ * and how its props are bound there. Present ONLY inside
1283
+ * {@link interpretCompositeFactory}'s body context, so a `new Type(...)` at a
1284
+ * file's own top level records nothing and a nested composite records its own
1285
+ * innermost factory rather than the enclosing one.
1286
+ */
1287
+ compositeParams?: CompositeParamRecorder;
1288
+ }
1289
+
1290
+ /** chant #2161 — what {@link stampCompositeOrigins} needs at one `new Type(...)` inside a factory body. */
1291
+ interface CompositeParamRecorder {
1292
+ /** The composite's declared name, as `Composite(fn, "<name>")` gave it. */
1293
+ composite: string;
1294
+ /** How the factory's single parameter is bound in this body. */
1295
+ scope: CompositeParamScope;
1296
+ /**
1297
+ * The body's own `const` initializers, so a value hoisted out of a member's
1298
+ * props (`const roleName = \`${props.name}-role\``) is still attributed. The
1299
+ * defining module's top-level consts are layered underneath, exactly as
1300
+ * `fold()` sees them.
1301
+ */
1302
+ consts: Map<string, ts.Expression>;
1276
1303
  }
1277
1304
 
1278
1305
  /** `{ value }` when `node`'s shape was recognized and resolved (value may itself be `undefined`/`null` — e.g. an optional composite member that wasn't created); `undefined` when the shape isn't one the live resolver understands (a plain literal, etc.) — callers fall back to the original, unchanged handling for that shape. */
@@ -2149,6 +2176,77 @@ function isLiteralPropertyNameNode(node: ts.PropertyName): boolean {
2149
2176
  return ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node);
2150
2177
  }
2151
2178
 
2179
+ /**
2180
+ * chant #2161 — how one admissible factory's parameter is bound in its body,
2181
+ * plus the consts an attribution walk has to follow.
2182
+ *
2183
+ * Built from the SOURCE, not from the argument value: the question is which
2184
+ * expression a member's property was written as, not what it evaluated to. A
2185
+ * factory with no parameter at all still gets a recorder, so every path in its
2186
+ * members records as a literal the composite fixes, which is exactly what a
2187
+ * parameterless composite does.
2188
+ */
2189
+ function compositeParamRecorder(
2190
+ factory: InterpretableFactory,
2191
+ moduleConsts: ReadonlyMap<string, ts.Expression>,
2192
+ ): CompositeParamRecorder {
2193
+ const whole = new Set<string>();
2194
+ const destructured = new Map<string, string>();
2195
+ const param = factory.fn.parameters[0];
2196
+ if (param) {
2197
+ if (ts.isIdentifier(param.name)) {
2198
+ whole.add(param.name.text);
2199
+ } else if (ts.isObjectBindingPattern(param.name)) {
2200
+ for (const el of param.name.elements) {
2201
+ const key = bindingElementPropKey(el);
2202
+ if (key !== undefined && ts.isIdentifier(el.name)) destructured.set(el.name.text, key);
2203
+ }
2204
+ }
2205
+ }
2206
+
2207
+ // Body `const`s layered over the defining module's, so a hoisted value is
2208
+ // followed. `interpretCompositeFactory` deletes shadowed names from the
2209
+ // context's own const map as it binds values; this map is separate precisely
2210
+ // so the INITIALIZER stays available to the attribution walk.
2211
+ const consts = new Map(moduleConsts);
2212
+ const body = factory.fn.body;
2213
+ if (ts.isBlock(body)) {
2214
+ for (const statement of body.statements) {
2215
+ if (!ts.isVariableStatement(statement)) continue;
2216
+ for (const decl of statement.declarationList.declarations) {
2217
+ if (ts.isIdentifier(decl.name) && decl.initializer) consts.set(decl.name.text, decl.initializer);
2218
+ }
2219
+ }
2220
+ }
2221
+
2222
+ return { composite: factory.compositeName, scope: { whole, destructured }, consts };
2223
+ }
2224
+
2225
+ /**
2226
+ * chant #2161 — record, for one `new Type({...})` written inside an interpreted
2227
+ * factory body, which factory parameter produced each of its property paths and
2228
+ * which paths the composite fixes.
2229
+ *
2230
+ * Best-effort and additive, exactly like {@link stampParamDependencies}: a
2231
+ * constructor called with no object literal records nothing, and
2232
+ * `setPathProvenance` keeps the first (innermost) writer.
2233
+ */
2234
+ function stampCompositeOrigins(entity: unknown, node: ts.NewExpression, ctx: ResolveCtx): void {
2235
+ const recorder = ctx.compositeParams;
2236
+ if (!recorder) return;
2237
+ if (typeof entity !== "object" || entity === null) return;
2238
+ let propsArg: ts.ObjectLiteralExpression | undefined;
2239
+ for (const argument of node.arguments ?? []) {
2240
+ if (ts.isObjectLiteralExpression(argument)) {
2241
+ propsArg = argument;
2242
+ break;
2243
+ }
2244
+ }
2245
+ if (!propsArg) return;
2246
+ const origins = collectCompositeOrigins(propsArg, recorder.consts, recorder.scope, recorder.composite);
2247
+ for (const [path, origin] of Object.entries(origins)) setPathProvenance(entity, path, origin);
2248
+ }
2249
+
2152
2250
  /**
2153
2251
  * Interpret an admissible factory's body against `args`, and assemble the
2154
2252
  * result through chant's own {@link Composite}.
@@ -2196,6 +2294,9 @@ async function interpretCompositeFactory(
2196
2294
  sandbox: ctx.sandbox,
2197
2295
  session: ctx.session,
2198
2296
  interpretDepth: ctx.interpretDepth + 1,
2297
+ // chant #2161 — set unconditionally, and NOT inherited from `ctx`: a nested
2298
+ // composite records its own parameters, never the enclosing one's.
2299
+ compositeParams: compositeParamRecorder(factory, scope.consts),
2199
2300
  };
2200
2301
 
2201
2302
  const bind = (name: string, value: unknown): void => {
@@ -2392,7 +2493,9 @@ async function interpretNewExpression(node: ts.NewExpression, ctx: ResolveCtx):
2392
2493
 
2393
2494
  const ctorArgs: unknown[] = [];
2394
2495
  for (const arg of node.arguments ?? []) ctorArgs.push(await interpretExpression(arg, ctx));
2395
- return new (Ctor as new (...ctorArguments: unknown[]) => unknown)(...ctorArgs);
2496
+ const instance = new (Ctor as new (...ctorArguments: unknown[]) => unknown)(...ctorArgs);
2497
+ stampCompositeOrigins(instance, node, ctx);
2498
+ return instance;
2396
2499
  }
2397
2500
 
2398
2501
  /**