@intentius/chant 0.57.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (558) hide show
  1. package/dist/audit/catalog.d.ts +51 -1
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +36 -1
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts +26 -9
  6. package/dist/audit/discover.d.ts.map +1 -1
  7. package/dist/audit/lineage.d.ts +10 -0
  8. package/dist/audit/lineage.d.ts.map +1 -0
  9. package/dist/audit/prior-art.d.ts +385 -0
  10. package/dist/audit/prior-art.d.ts.map +1 -0
  11. package/dist/audit/proof.d.ts +16 -0
  12. package/dist/audit/proof.d.ts.map +1 -1
  13. package/dist/audit/report-html.d.ts.map +1 -1
  14. package/dist/audit/report-model.d.ts +8 -1
  15. package/dist/audit/report-model.d.ts.map +1 -1
  16. package/dist/audit/report.d.ts.map +1 -1
  17. package/dist/audit/rules-doc.d.ts +3 -0
  18. package/dist/audit/rules-doc.d.ts.map +1 -1
  19. package/dist/audit/secrets.d.ts +15 -0
  20. package/dist/audit/secrets.d.ts.map +1 -1
  21. package/dist/audit/terraform-state.d.ts +46 -0
  22. package/dist/audit/terraform-state.d.ts.map +1 -0
  23. package/dist/build.d.ts +17 -1
  24. package/dist/build.d.ts.map +1 -1
  25. package/dist/claimed-fields.d.ts +161 -0
  26. package/dist/claimed-fields.d.ts.map +1 -0
  27. package/dist/cli/build-params-cli.d.ts +2 -2
  28. package/dist/cli/command-group.d.ts +14 -0
  29. package/dist/cli/command-group.d.ts.map +1 -1
  30. package/dist/cli/commands/audit.d.ts +17 -1
  31. package/dist/cli/commands/audit.d.ts.map +1 -1
  32. package/dist/cli/commands/build.d.ts.map +1 -1
  33. package/dist/cli/commands/carve-bridge.d.ts.map +1 -1
  34. package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
  35. package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
  36. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
  37. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
  38. package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
  39. package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
  40. package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
  41. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/lint.d.ts +13 -0
  44. package/dist/cli/commands/lint.d.ts.map +1 -1
  45. package/dist/cli/commands/onboard.d.ts +2 -0
  46. package/dist/cli/commands/onboard.d.ts.map +1 -1
  47. package/dist/cli/handlers/build.d.ts.map +1 -1
  48. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  49. package/dist/cli/handlers/operator.d.ts +82 -16
  50. package/dist/cli/handlers/operator.d.ts.map +1 -1
  51. package/dist/cli/handlers/run.d.ts +49 -42
  52. package/dist/cli/handlers/run.d.ts.map +1 -1
  53. package/dist/cli/main.d.ts +12 -1
  54. package/dist/cli/main.d.ts.map +1 -1
  55. package/dist/cli/mcp/op-tools.d.ts +16 -1
  56. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  57. package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
  58. package/dist/cli/mcp/resources/context.d.ts.map +1 -1
  59. package/dist/cli/plugins.d.ts +22 -0
  60. package/dist/cli/plugins.d.ts.map +1 -1
  61. package/dist/cli/registry.d.ts +40 -9
  62. package/dist/cli/registry.d.ts.map +1 -1
  63. package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
  64. package/dist/components/auto-release.d.ts +10 -20
  65. package/dist/components/auto-release.d.ts.map +1 -1
  66. package/dist/components/capability.d.ts +4 -4
  67. package/dist/components/cli-support.d.ts +24 -22
  68. package/dist/components/cli-support.d.ts.map +1 -1
  69. package/dist/components/component.d.ts +21 -6
  70. package/dist/components/component.d.ts.map +1 -1
  71. package/dist/components/driver-output.d.ts.map +1 -1
  72. package/dist/components/driver.d.ts +73 -37
  73. package/dist/components/driver.d.ts.map +1 -1
  74. package/dist/components/index.d.ts +1 -2
  75. package/dist/components/index.d.ts.map +1 -1
  76. package/dist/components/manifest-persistence.d.ts +1 -9
  77. package/dist/components/manifest-persistence.d.ts.map +1 -1
  78. package/dist/components/run-progress.d.ts +6 -6
  79. package/dist/components/run-progress.d.ts.map +1 -1
  80. package/dist/components/verbs/run-agent.d.ts +10 -22
  81. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  82. package/dist/components/verbs/verify.d.ts +2 -2
  83. package/dist/deep-observation.d.ts +17 -0
  84. package/dist/deep-observation.d.ts.map +1 -1
  85. package/dist/detectLexicon.d.ts +13 -0
  86. package/dist/detectLexicon.d.ts.map +1 -1
  87. package/dist/discovery/files.d.ts +4 -4
  88. package/dist/discovery/fold-import.d.ts.map +1 -1
  89. package/dist/discovery/param-deps.d.ts +33 -0
  90. package/dist/discovery/param-deps.d.ts.map +1 -1
  91. package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
  92. package/dist/discovery/sandbox/config-wire.d.ts +2 -2
  93. package/dist/fold/foldable-helpers.d.ts +5 -1
  94. package/dist/fold/foldable-helpers.d.ts.map +1 -1
  95. package/dist/fold-provenance.d.ts +236 -0
  96. package/dist/fold-provenance.d.ts.map +1 -0
  97. package/dist/graph-ops.d.ts +1 -1
  98. package/dist/held-elsewhere.d.ts +85 -0
  99. package/dist/held-elsewhere.d.ts.map +1 -0
  100. package/dist/index.d.ts +3 -0
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/kubectl-context.d.ts +3 -3
  103. package/dist/lexicon-config.d.ts +4 -4
  104. package/dist/lexicon-plugin-helpers.d.ts +1 -1
  105. package/dist/lexicon.d.ts +273 -16
  106. package/dist/lexicon.d.ts.map +1 -1
  107. package/dist/lifecycle/change-set.d.ts +13 -0
  108. package/dist/lifecycle/change-set.d.ts.map +1 -1
  109. package/dist/lifecycle/deep-diff.d.ts +133 -6
  110. package/dist/lifecycle/deep-diff.d.ts.map +1 -1
  111. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  112. package/dist/lifecycle/gate-ledger.d.ts +79 -3
  113. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  114. package/dist/lifecycle/index.d.ts +1 -0
  115. package/dist/lifecycle/index.d.ts.map +1 -1
  116. package/dist/lifecycle/release-ledger.d.ts +2 -2
  117. package/dist/lifecycle/run-ledger.d.ts +53 -0
  118. package/dist/lifecycle/run-ledger.d.ts.map +1 -0
  119. package/dist/lifecycle/symptoms.d.ts +3 -3
  120. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  121. package/dist/lint/config.d.ts +81 -2
  122. package/dist/lint/config.d.ts.map +1 -1
  123. package/dist/lint/post-synth.d.ts +55 -2
  124. package/dist/lint/post-synth.d.ts.map +1 -1
  125. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
  126. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
  127. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
  128. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
  129. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
  130. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
  131. package/dist/lint/rules/comp/index.d.ts +1 -1
  132. package/dist/lint/rules/comp/index.d.ts.map +1 -1
  133. package/dist/lint/rules/op/index.d.ts +16 -0
  134. package/dist/lint/rules/op/index.d.ts.map +1 -0
  135. package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
  136. package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
  137. package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
  138. package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
  139. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
  140. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
  141. package/dist/lint/rules/op/support.d.ts +12 -0
  142. package/dist/lint/rules/op/support.d.ts.map +1 -0
  143. package/dist/lint/suppressions.d.ts +108 -0
  144. package/dist/lint/suppressions.d.ts.map +1 -0
  145. package/dist/live-endpoint.d.ts +1 -1
  146. package/dist/op/activities/activity-contracts.d.ts +54 -0
  147. package/dist/op/activities/activity-contracts.d.ts.map +1 -0
  148. package/dist/op/activities/apply.d.ts +262 -0
  149. package/dist/op/activities/apply.d.ts.map +1 -0
  150. package/dist/op/activities/build.d.ts +13 -0
  151. package/dist/op/activities/build.d.ts.map +1 -0
  152. package/dist/op/activities/converge.d.ts +110 -0
  153. package/dist/op/activities/converge.d.ts.map +1 -0
  154. package/dist/op/activities/env-teardown.d.ts +76 -0
  155. package/dist/op/activities/env-teardown.d.ts.map +1 -0
  156. package/dist/op/activities/guard-validate.d.ts +64 -0
  157. package/dist/op/activities/guard-validate.d.ts.map +1 -0
  158. package/dist/op/activities/http-check.d.ts +34 -0
  159. package/dist/op/activities/http-check.d.ts.map +1 -0
  160. package/dist/op/activities/index.d.ts +31 -0
  161. package/dist/op/activities/index.d.ts.map +1 -0
  162. package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
  163. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
  164. package/dist/op/activities/lifecycle.d.ts +42 -0
  165. package/dist/op/activities/lifecycle.d.ts.map +1 -0
  166. package/dist/op/activities/pipeline-audit.d.ts +84 -0
  167. package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
  168. package/dist/op/activities/policy.d.ts +17 -0
  169. package/dist/op/activities/policy.d.ts.map +1 -0
  170. package/dist/op/activities/reconcile.d.ts +149 -0
  171. package/dist/op/activities/reconcile.d.ts.map +1 -0
  172. package/dist/op/activities/shell.d.ts +13 -0
  173. package/dist/op/activities/shell.d.ts.map +1 -0
  174. package/dist/op/activities/teardown.d.ts +10 -0
  175. package/dist/op/activities/teardown.d.ts.map +1 -0
  176. package/dist/op/activities/util.d.ts +7 -0
  177. package/dist/op/activities/util.d.ts.map +1 -0
  178. package/dist/op/activities/wait.d.ts +28 -0
  179. package/dist/op/activities/wait.d.ts.map +1 -0
  180. package/dist/op/activities/workflow-audit.d.ts +92 -0
  181. package/dist/op/activities/workflow-audit.d.ts.map +1 -0
  182. package/dist/op/activity-contract-registry.d.ts +76 -0
  183. package/dist/op/activity-contract-registry.d.ts.map +1 -0
  184. package/dist/op/activity-contract.d.ts +25 -18
  185. package/dist/op/activity-contract.d.ts.map +1 -1
  186. package/dist/op/activity-failure.d.ts +28 -0
  187. package/dist/op/activity-failure.d.ts.map +1 -0
  188. package/dist/op/activity-profiles.d.ts +118 -0
  189. package/dist/op/activity-profiles.d.ts.map +1 -0
  190. package/dist/op/activity-registry.d.ts +22 -38
  191. package/dist/op/activity-registry.d.ts.map +1 -1
  192. package/dist/op/activity-runtime.d.ts +3 -14
  193. package/dist/op/activity-runtime.d.ts.map +1 -1
  194. package/dist/op/builders.d.ts +85 -30
  195. package/dist/op/builders.d.ts.map +1 -1
  196. package/dist/op/change-signal.d.ts +91 -0
  197. package/dist/op/change-signal.d.ts.map +1 -0
  198. package/dist/op/composites/apply-op.d.ts +118 -0
  199. package/dist/op/composites/apply-op.d.ts.map +1 -0
  200. package/dist/op/composites/converge-op.d.ts +120 -0
  201. package/dist/op/composites/converge-op.d.ts.map +1 -0
  202. package/dist/op/composites/index.d.ts +26 -0
  203. package/dist/op/composites/index.d.ts.map +1 -0
  204. package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
  205. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
  206. package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
  207. package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
  208. package/dist/op/composites/reconcile-op.d.ts +57 -0
  209. package/dist/op/composites/reconcile-op.d.ts.map +1 -0
  210. package/dist/op/composites/watch-op.d.ts +60 -0
  211. package/dist/op/composites/watch-op.d.ts.map +1 -0
  212. package/dist/op/composites/workflow-audit-op.d.ts +57 -0
  213. package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
  214. package/dist/op/converge-rule.d.ts +12 -10
  215. package/dist/op/converge-rule.d.ts.map +1 -1
  216. package/dist/op/cron.d.ts +51 -0
  217. package/dist/op/cron.d.ts.map +1 -0
  218. package/dist/op/discover.d.ts +9 -0
  219. package/dist/op/discover.d.ts.map +1 -1
  220. package/dist/op/duration.d.ts +11 -0
  221. package/dist/op/duration.d.ts.map +1 -0
  222. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  223. package/dist/op/gate-name.d.ts +40 -0
  224. package/dist/op/gate-name.d.ts.map +1 -0
  225. package/dist/op/gate-summary.d.ts +43 -0
  226. package/dist/op/gate-summary.d.ts.map +1 -0
  227. package/dist/op/gate.d.ts +90 -0
  228. package/dist/op/gate.d.ts.map +1 -0
  229. package/dist/op/generate-pipeline.d.ts +9 -0
  230. package/dist/op/generate-pipeline.d.ts.map +1 -1
  231. package/dist/op/index.d.ts +29 -9
  232. package/dist/op/index.d.ts.map +1 -1
  233. package/dist/op/local-executor.d.ts +114 -28
  234. package/dist/op/local-executor.d.ts.map +1 -1
  235. package/dist/op/local-output.d.ts +11 -1
  236. package/dist/op/local-output.d.ts.map +1 -1
  237. package/dist/op/op-ir.d.ts +185 -0
  238. package/dist/op/op-ir.d.ts.map +1 -0
  239. package/dist/op/op-verb-class.d.ts +10 -2
  240. package/dist/op/op-verb-class.d.ts.map +1 -1
  241. package/dist/op/operator.d.ts +93 -5
  242. package/dist/op/operator.d.ts.map +1 -1
  243. package/dist/op/receipt-store.d.ts +1 -1
  244. package/dist/op/receipt-store.d.ts.map +1 -1
  245. package/dist/op/resource.d.ts +15 -1
  246. package/dist/op/resource.d.ts.map +1 -1
  247. package/dist/op/runtime.d.ts +200 -0
  248. package/dist/op/runtime.d.ts.map +1 -0
  249. package/dist/op/runtimes/local.d.ts +29 -0
  250. package/dist/op/runtimes/local.d.ts.map +1 -0
  251. package/dist/op/step-output-ref.d.ts +15 -13
  252. package/dist/op/step-output-ref.d.ts.map +1 -1
  253. package/dist/op/types.d.ts +96 -29
  254. package/dist/op/types.d.ts.map +1 -1
  255. package/dist/ownership.d.ts +1 -1
  256. package/dist/provenance.d.ts +21 -0
  257. package/dist/provenance.d.ts.map +1 -1
  258. package/dist/serializer-walker.d.ts.map +1 -1
  259. package/dist/terraform/bridge.d.ts +26 -7
  260. package/dist/terraform/bridge.d.ts.map +1 -1
  261. package/dist/terraform/carve-provider.d.ts +28 -2
  262. package/dist/terraform/carve-provider.d.ts.map +1 -1
  263. package/dist/terraform/data-source-shape.d.ts +77 -0
  264. package/dist/terraform/data-source-shape.d.ts.map +1 -0
  265. package/dist/terraform/graph.d.ts.map +1 -1
  266. package/dist/terraform/providers/kubernetes.d.ts +5 -0
  267. package/dist/terraform/providers/kubernetes.d.ts.map +1 -1
  268. package/dist/terraform/tier-map.d.ts +16 -4
  269. package/dist/terraform/tier-map.d.ts.map +1 -1
  270. package/dist/terraform/types.d.ts +8 -0
  271. package/dist/terraform/types.d.ts.map +1 -1
  272. package/package.json +6 -1
  273. package/src/audit/catalog.test.ts +79 -3
  274. package/src/audit/catalog.ts +111 -13
  275. package/src/audit/core.test.ts +26 -0
  276. package/src/audit/core.ts +84 -18
  277. package/src/audit/discover.test.ts +39 -0
  278. package/src/audit/discover.ts +202 -18
  279. package/src/audit/lineage.ts +100 -0
  280. package/src/audit/prior-art.ts +153 -0
  281. package/src/audit/proof.test.ts +67 -0
  282. package/src/audit/proof.ts +70 -0
  283. package/src/audit/report-html.ts +9 -4
  284. package/src/audit/report-model.ts +16 -2
  285. package/src/audit/report.test.ts +33 -0
  286. package/src/audit/report.ts +5 -3
  287. package/src/audit/rules-doc.test.ts +34 -2
  288. package/src/audit/rules-doc.ts +82 -9
  289. package/src/audit/secrets.ts +15 -3
  290. package/src/audit/terraform-state.test.ts +144 -0
  291. package/src/audit/terraform-state.ts +131 -0
  292. package/src/build.ts +31 -1
  293. package/src/claimed-fields.test.ts +145 -0
  294. package/src/claimed-fields.ts +208 -0
  295. package/src/cli/build-params-cli.ts +2 -2
  296. package/src/cli/command-group.ts +14 -0
  297. package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
  298. package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
  299. package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
  300. package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
  301. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
  302. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
  303. package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
  304. package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
  305. package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
  306. package/src/cli/commands/audit.test.ts +191 -11
  307. package/src/cli/commands/audit.ts +78 -28
  308. package/src/cli/commands/build.test.ts +330 -9
  309. package/src/cli/commands/build.ts +170 -24
  310. package/src/cli/commands/carve-bridge.test.ts +237 -14
  311. package/src/cli/commands/carve-bridge.ts +21 -17
  312. package/src/cli/commands/carve-emit-k8s.test.ts +17 -10
  313. package/src/cli/commands/check-lexicon-docs.ts +1 -1
  314. package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
  315. package/src/cli/commands/check-lexicon-examples.ts +42 -10
  316. package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
  317. package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
  318. package/src/cli/commands/init-lexicon.test.ts +97 -2
  319. package/src/cli/commands/init-lexicon.ts +4 -2
  320. package/src/cli/commands/init.test.ts +35 -1
  321. package/src/cli/commands/init.ts +14 -3
  322. package/src/cli/commands/lint.test.ts +194 -1
  323. package/src/cli/commands/lint.ts +205 -7
  324. package/src/cli/commands/onboard.test.ts +75 -0
  325. package/src/cli/commands/onboard.ts +54 -23
  326. package/src/cli/handlers/build.test.ts +81 -1
  327. package/src/cli/handlers/build.ts +15 -1
  328. package/src/cli/handlers/graph.test.ts +3 -3
  329. package/src/cli/handlers/lifecycle.test.ts +195 -12
  330. package/src/cli/handlers/lifecycle.ts +123 -6
  331. package/src/cli/handlers/misc.ts +1 -1
  332. package/src/cli/handlers/operator.test.ts +183 -11
  333. package/src/cli/handlers/operator.ts +341 -55
  334. package/src/cli/handlers/run.test.ts +568 -1295
  335. package/src/cli/handlers/run.ts +446 -912
  336. package/src/cli/main.test.ts +22 -16
  337. package/src/cli/main.ts +66 -33
  338. package/src/cli/mcp/op-tools.ts +147 -88
  339. package/src/cli/mcp/resource-handlers.ts +10 -37
  340. package/src/cli/mcp/resources/context.ts +11 -12
  341. package/src/cli/mcp/server.test.ts +25 -27
  342. package/src/cli/mcp/server.ts +2 -2
  343. package/src/cli/plugins.test.ts +68 -2
  344. package/src/cli/plugins.ts +39 -0
  345. package/src/cli/registry.ts +40 -9
  346. package/src/codegen/docs.ts +1 -1
  347. package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
  348. package/src/codegen/generate-post-synth-barrel.ts +1 -1
  349. package/src/components/README.md +4 -3
  350. package/src/components/__fixtures__/neo4j-fanout.json +1 -1
  351. package/src/components/auto-release.test.ts +4 -20
  352. package/src/components/auto-release.ts +17 -42
  353. package/src/components/capability.ts +4 -4
  354. package/src/components/cli-support.test.ts +28 -12
  355. package/src/components/cli-support.ts +60 -47
  356. package/src/components/component-schema.test.ts +18 -2
  357. package/src/components/component.schema.json +18 -5
  358. package/src/components/component.test.ts +2 -2
  359. package/src/components/component.ts +27 -7
  360. package/src/components/config-defaults.test.ts +2 -2
  361. package/src/components/driver-output.ts +14 -2
  362. package/src/components/driver.test.ts +109 -20
  363. package/src/components/driver.ts +201 -84
  364. package/src/components/index.ts +1 -6
  365. package/src/components/manifest-persistence.test.ts +2 -20
  366. package/src/components/manifest-persistence.ts +4 -24
  367. package/src/components/pilots/neo4j-fanout.pilot.ts +3 -3
  368. package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
  369. package/src/components/run-progress.ts +6 -6
  370. package/src/components/verbs/run-agent.test.ts +19 -0
  371. package/src/components/verbs/run-agent.ts +12 -24
  372. package/src/components/verbs/verify.ts +2 -2
  373. package/src/deep-observation.test.ts +75 -0
  374. package/src/deep-observation.ts +48 -0
  375. package/src/detectLexicon.ts +18 -1
  376. package/src/discovery/collect.test.ts +3 -3
  377. package/src/discovery/files.ts +4 -4
  378. package/src/discovery/fold-import.test.ts +1 -1
  379. package/src/discovery/fold-import.ts +105 -2
  380. package/src/discovery/param-deps.test.ts +112 -1
  381. package/src/discovery/param-deps.ts +193 -0
  382. package/src/discovery/sandbox/bundle.ts +15 -1
  383. package/src/discovery/sandbox/config-wire.test.ts +2 -2
  384. package/src/discovery/sandbox/config-wire.ts +2 -2
  385. package/src/fold/fold.test.ts +56 -0
  386. package/src/fold/foldable-helpers.ts +82 -2
  387. package/src/fold-provenance-exclusion.test.ts +186 -0
  388. package/src/fold-provenance.test.ts +495 -0
  389. package/src/fold-provenance.ts +441 -0
  390. package/src/graph-ops.test.ts +3 -3
  391. package/src/graph-ops.ts +1 -1
  392. package/src/held-elsewhere.test.ts +102 -0
  393. package/src/held-elsewhere.ts +114 -0
  394. package/src/index.ts +3 -0
  395. package/src/kubectl-context.ts +3 -3
  396. package/src/lexicon-config.test.ts +5 -5
  397. package/src/lexicon-config.ts +4 -4
  398. package/src/lexicon-plugin-helpers.ts +1 -1
  399. package/src/lexicon.ts +296 -16
  400. package/src/lifecycle/change-set.test.ts +49 -0
  401. package/src/lifecycle/change-set.ts +67 -0
  402. package/src/lifecycle/converge-ledger.ts +1 -1
  403. package/src/lifecycle/deep-diff.test.ts +267 -14
  404. package/src/lifecycle/deep-diff.ts +217 -14
  405. package/src/lifecycle/deep-observe.test.ts +3 -1
  406. package/src/lifecycle/deep-observe.ts +16 -6
  407. package/src/lifecycle/gate-ledger.test.ts +74 -2
  408. package/src/lifecycle/gate-ledger.ts +154 -36
  409. package/src/lifecycle/index.ts +1 -0
  410. package/src/lifecycle/release-ledger.ts +2 -2
  411. package/src/lifecycle/run-ledger.test.ts +268 -0
  412. package/src/lifecycle/run-ledger.ts +201 -0
  413. package/src/lifecycle/symptoms.ts +3 -3
  414. package/src/lint/config.test.ts +82 -1
  415. package/src/lint/config.ts +112 -3
  416. package/src/lint/pipeline-change-gate.test.ts +2 -2
  417. package/src/lint/policy.test.ts +1 -1
  418. package/src/lint/post-synth.test.ts +31 -0
  419. package/src/lint/post-synth.ts +54 -1
  420. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
  421. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
  422. package/src/lint/rules/comp/comp.test.ts +27 -1
  423. package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +76 -0
  424. package/src/lint/rules/comp/index.ts +3 -3
  425. package/src/lint/rules/op/index.ts +23 -0
  426. package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
  427. package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
  428. package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
  429. package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
  430. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
  431. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
  432. package/src/lint/rules/op/support.ts +11 -0
  433. package/src/lint/suppressions.test.ts +163 -0
  434. package/src/lint/suppressions.ts +204 -0
  435. package/src/live-endpoint.ts +1 -1
  436. package/src/op/activities/activity-contracts.ts +66 -0
  437. package/src/op/activities/apply.test.ts +567 -0
  438. package/src/op/activities/apply.ts +662 -0
  439. package/src/op/activities/build.ts +26 -0
  440. package/src/op/activities/converge.test.ts +330 -0
  441. package/src/op/activities/converge.ts +449 -0
  442. package/src/op/activities/env-teardown.test.ts +187 -0
  443. package/src/op/activities/env-teardown.ts +171 -0
  444. package/src/op/activities/guard-validate.test.ts +139 -0
  445. package/src/op/activities/guard-validate.ts +223 -0
  446. package/src/op/activities/http-check.test.ts +48 -0
  447. package/src/op/activities/http-check.ts +55 -0
  448. package/src/op/activities/index.ts +119 -0
  449. package/src/op/activities/lexicon-upgrade.test.ts +492 -0
  450. package/src/op/activities/lexicon-upgrade.ts +673 -0
  451. package/src/op/activities/lifecycle.ts +85 -0
  452. package/src/op/activities/pipeline-audit.test.ts +67 -0
  453. package/src/op/activities/pipeline-audit.ts +201 -0
  454. package/src/op/activities/policy.test.ts +19 -0
  455. package/src/op/activities/policy.ts +37 -0
  456. package/src/op/activities/reconcile.test.ts +161 -0
  457. package/src/op/activities/reconcile.ts +354 -0
  458. package/src/op/activities/shell.ts +26 -0
  459. package/src/op/activities/teardown.ts +22 -0
  460. package/src/op/activities/util.ts +6 -0
  461. package/src/op/activities/wait.ts +69 -0
  462. package/src/op/activities/workflow-audit.test.ts +90 -0
  463. package/src/op/activities/workflow-audit.ts +203 -0
  464. package/src/op/activity-contract-registry.test.ts +98 -0
  465. package/src/op/activity-contract-registry.ts +114 -0
  466. package/src/op/activity-contract.test.ts +1 -1
  467. package/src/op/activity-contract.ts +37 -33
  468. package/src/op/activity-failure.ts +34 -0
  469. package/src/op/activity-profiles.test.ts +56 -0
  470. package/src/op/activity-profiles.ts +116 -0
  471. package/src/op/activity-registry.test.ts +37 -28
  472. package/src/op/activity-registry.ts +27 -56
  473. package/src/op/activity-runtime.ts +3 -47
  474. package/src/op/builders-exports.test.ts +0 -49
  475. package/src/op/builders-typed.test.ts +164 -0
  476. package/src/op/builders.ts +125 -41
  477. package/src/op/change-signal.test.ts +117 -0
  478. package/src/op/change-signal.ts +169 -0
  479. package/src/op/composites/apply-op.ts +218 -0
  480. package/src/op/composites/composites.test.ts +379 -0
  481. package/src/op/composites/converge-op.test.ts +168 -0
  482. package/src/op/composites/converge-op.ts +214 -0
  483. package/src/op/composites/index.ts +26 -0
  484. package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
  485. package/src/op/composites/lexicon-upgrade-op.ts +134 -0
  486. package/src/op/composites/pipeline-audit-op.test.ts +25 -0
  487. package/src/op/composites/pipeline-audit-op.ts +78 -0
  488. package/src/op/composites/reconcile-op.test.ts +51 -0
  489. package/src/op/composites/reconcile-op.ts +110 -0
  490. package/src/op/composites/watch-op.ts +108 -0
  491. package/src/op/composites/workflow-audit-op.test.ts +25 -0
  492. package/src/op/composites/workflow-audit-op.ts +88 -0
  493. package/src/op/converge-rule.ts +12 -10
  494. package/src/op/cron.test.ts +128 -0
  495. package/src/op/cron.ts +149 -0
  496. package/src/op/discover-root.test.ts +105 -1
  497. package/src/op/discover.test.ts +6 -2
  498. package/src/op/discover.ts +84 -16
  499. package/src/op/duration.ts +21 -0
  500. package/src/op/effect-step.test.ts +29 -14
  501. package/src/op/emulator-lifecycle.ts +1 -2
  502. package/src/op/gate-name.test.ts +65 -0
  503. package/src/op/gate-name.ts +60 -0
  504. package/src/op/gate-summary.ts +84 -0
  505. package/src/op/gate.ts +155 -0
  506. package/src/op/generate-pipeline.test.ts +65 -3
  507. package/src/op/generate-pipeline.ts +19 -2
  508. package/src/op/index.ts +48 -8
  509. package/src/op/local-executor.test.ts +178 -34
  510. package/src/op/local-executor.ts +371 -102
  511. package/src/op/local-output.test.ts +95 -11
  512. package/src/op/local-output.ts +33 -4
  513. package/src/op/op-ir.test.ts +292 -0
  514. package/src/op/op-ir.ts +419 -0
  515. package/src/op/op-verb-class.test.ts +2 -2
  516. package/src/op/op-verb-class.ts +19 -5
  517. package/src/op/op.test.ts +28 -7
  518. package/src/op/operator.test.ts +543 -6
  519. package/src/op/operator.ts +203 -20
  520. package/src/op/receipt-store.ts +1 -1
  521. package/src/op/resource.ts +20 -2
  522. package/src/op/runtime.ts +203 -0
  523. package/src/op/runtimes/local.test.ts +181 -0
  524. package/src/op/runtimes/local.ts +212 -0
  525. package/src/op/step-output-ref.ts +15 -13
  526. package/src/op/types.ts +106 -26
  527. package/src/ownership.ts +1 -1
  528. package/src/provenance.test.ts +6 -0
  529. package/src/provenance.ts +21 -1
  530. package/src/serializer-walker.test.ts +42 -0
  531. package/src/serializer-walker.ts +21 -2
  532. package/src/terraform/aws-resources.test.ts +13 -4
  533. package/src/terraform/bridge.test.ts +22 -9
  534. package/src/terraform/bridge.ts +89 -28
  535. package/src/terraform/carve-provider.ts +38 -2
  536. package/src/terraform/data-source-shape.ts +95 -0
  537. package/src/terraform/graph.ts +35 -7
  538. package/src/terraform/providers/kubernetes.ts +48 -2
  539. package/src/terraform/tier-map.ts +21 -6
  540. package/src/terraform/types.ts +8 -0
  541. package/dist/cli/handlers/op-progress.d.ts +0 -90
  542. package/dist/cli/handlers/op-progress.d.ts.map +0 -1
  543. package/dist/cli/handlers/run-client.d.ts +0 -127
  544. package/dist/cli/handlers/run-client.d.ts.map +0 -1
  545. package/dist/cli/handlers/run-report.d.ts +0 -5
  546. package/dist/cli/handlers/run-report.d.ts.map +0 -1
  547. package/dist/components/temporal-codegen-loader.d.ts +0 -27
  548. package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
  549. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
  550. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
  551. package/src/cli/handlers/op-progress.test.ts +0 -268
  552. package/src/cli/handlers/op-progress.ts +0 -248
  553. package/src/cli/handlers/run-client.test.ts +0 -82
  554. package/src/cli/handlers/run-client.ts +0 -219
  555. package/src/cli/handlers/run-report.test.ts +0 -62
  556. package/src/cli/handlers/run-report.ts +0 -122
  557. package/src/components/temporal-codegen-loader.ts +0 -41
  558. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
@@ -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
@@ -287,6 +287,25 @@ describe("run() — failed turn: non-zero exit surfaces as status \"failed\", ne
287
287
  });
288
288
  });
289
289
 
290
+ describe("RunAgentTurn[\"status\"] is exactly the two states run() produces (#2072)", () => {
291
+ it("has no third member: a switch handling only \"completed\" and \"failed\" compiles with no default needed", () => {
292
+ // Compile-time exhaustiveness check, not a runtime assertion: if a third
293
+ // member were ever added back to the union (e.g. "interrupted"), this
294
+ // switch would stop being exhaustive and `tsc` would reject the missing
295
+ // case, since `identity`'s return type has no branch left to satisfy it.
296
+ const identity = (status: RunAgentOutput["turn"]["status"]): "completed" | "failed" => {
297
+ switch (status) {
298
+ case "completed":
299
+ return "completed";
300
+ case "failed":
301
+ return "failed";
302
+ }
303
+ };
304
+ expect(identity("completed")).toBe("completed");
305
+ expect(identity("failed")).toBe("failed");
306
+ });
307
+ });
308
+
290
309
  describe("collectArtifacts — only a \"not found\" read means \"no artifact\"; a genuine infra failure propagates (#1942 review finding 2)", () => {
291
310
  it("branch A: readFile rejecting with the sprite-fs \"not found\" shape resolves to empty artifacts.files, not a run() rejection", async () => {
292
311
  const { sprites } = makeFakeSprites(succeed); // never writes /work/output — readFile hits the fake's "not found" branch
@@ -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
@@ -155,12 +149,6 @@
155
149
  * snapshot folded into a `BuildArchiveManifest` entry (./build-archive.ts)
156
150
  * remains an open question, as does `artifacts.diff`, which `run()` never
157
151
  * populates (the real Sprites API has no built-in diff endpoint).
158
- * - Interrupted turns — `turn.status: "interrupted"` stays in the type but
159
- * is unreachable from this implementation: any `sprites.exec` rejection
160
- * (including one caused by an aborted signal) propagates as a genuine
161
- * `run()` failure rather than being classified as an interrupted turn.
162
- * Distinguishing "deadline hit mid-run" from "the sprite backend errored"
163
- * well enough to surface `"interrupted"` safely is left for #1944.
164
152
  *
165
153
  * **#1943 (this revision) resolved the transcript-hash basis and
166
154
  * sign/verify-gate interop, closing #1941's open "transcript hash basis"
@@ -291,7 +279,7 @@ export interface RunAgentInput {
291
279
 
292
280
  /** Mirrors fountain's `Turn` shape (`status`/`exit_code`/`started_at`/`ended_at`), even though the turn itself runs on a chant-owned sprite rather than a fountain-managed `Sandbox`. */
293
281
  export interface RunAgentTurn {
294
- status: "completed" | "failed" | "interrupted";
282
+ status: "completed" | "failed";
295
283
  exitCode: number | null;
296
284
  startedAt: string;
297
285
  endedAt: string | null;
@@ -526,8 +514,8 @@ export function createRunAgentCapability(
526
514
  async rollback(_ctx, input, output): Promise<void> {
527
515
  // The durable-safe channel first (#1944): `output` is the exact value
528
516
  // 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
517
+ // caller (../driver.ts locally, and a hosting runtime across whatever
518
+ // process boundary it puts between the two) — it
531
519
  // survives even when `rollback()` is called with a freshly-rebuilt
532
520
  // `input` object the in-process WeakMap below has never seen. Falls
533
521
  // 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, []);
@@ -1,5 +1,22 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
 
3
+ /**
4
+ * The message {@link detectLexicons} throws when a scan of the project's
5
+ * source files turns up no `@intentius/chant-lexicon-*` import at all.
6
+ *
7
+ * Named (chant #2222) because one caller has to tell this failure apart from
8
+ * every other one: `chant lint` reports a lexicon it cannot resolve as an
9
+ * error diagnostic, but "this directory declares no lexicon and imports none"
10
+ * is not that. It is a project that lints under the core rules alone, and it
11
+ * has always been allowed to. See {@link isNoLexiconDetected}.
12
+ */
13
+ export const NO_LEXICON_DETECTED_MESSAGE = "No lexicon detected in infrastructure files";
14
+
15
+ /** Whether `error` is the {@link NO_LEXICON_DETECTED_MESSAGE} failure. */
16
+ export function isNoLexiconDetected(error: unknown): boolean {
17
+ return error instanceof Error && error.message === NO_LEXICON_DETECTED_MESSAGE;
18
+ }
19
+
3
20
  /**
4
21
  * Detects which lexicons are being used by analyzing import statements
5
22
  * in the provided infrastructure files. Matches any `@intentius/chant-lexicon-*` package.
@@ -32,7 +49,7 @@ export async function detectLexicons(files: string[]): Promise<string[]> {
32
49
 
33
50
  // Validate results
34
51
  if (detectedLexicons.size === 0) {
35
- throw new Error("No lexicon detected in infrastructure files");
52
+ throw new Error(NO_LEXICON_DETECTED_MESSAGE);
36
53
  }
37
54
 
38
55
  return Array.from(detectedLexicons);
@@ -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
  */
@@ -1276,7 +1276,7 @@ describe("tryFoldFile — registered authoring helpers (#1082)", () => {
1276
1276
  stack: "web",
1277
1277
  inputs: { pVpcId: { stackOutput: { stack: "shared-foundation", name: "oVpcId" } } },
1278
1278
  },
1279
- { kind: "gate", signalName: "approve", timeout: "24h" },
1279
+ { kind: "gate", gate: "approve", timeout: "24h" },
1280
1280
  ],
1281
1281
  },
1282
1282
  ],
@@ -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
  /**