@intentius/chant 0.101.0 → 0.104.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 (739) hide show
  1. package/dist/agents/checks.d.ts.map +1 -1
  2. package/dist/attrref.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +2 -0
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts.map +1 -1
  6. package/dist/audit/nginx.d.ts.map +1 -1
  7. package/dist/audit/prior-art.d.ts +48 -0
  8. package/dist/audit/prior-art.d.ts.map +1 -1
  9. package/dist/behaviour-kinds.d.ts.map +1 -1
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/change-set.d.ts +232 -0
  12. package/dist/change-set.d.ts.map +1 -0
  13. package/dist/cli/commands/audit.d.ts +7 -0
  14. package/dist/cli/commands/audit.d.ts.map +1 -1
  15. package/dist/cli/commands/build.d.ts.map +1 -1
  16. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  17. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  18. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  19. package/dist/cli/commands/import.d.ts +8 -0
  20. package/dist/cli/commands/import.d.ts.map +1 -1
  21. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  22. package/dist/cli/commands/init.d.ts +19 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -1
  24. package/dist/cli/commands/onboard.d.ts +9 -0
  25. package/dist/cli/commands/onboard.d.ts.map +1 -1
  26. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  27. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  28. package/dist/cli/handlers/build.d.ts.map +1 -1
  29. package/dist/cli/handlers/change-set.d.ts +11 -0
  30. package/dist/cli/handlers/change-set.d.ts.map +1 -0
  31. package/dist/cli/handlers/dev.d.ts.map +1 -1
  32. package/dist/cli/handlers/fan-out.d.ts +33 -0
  33. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  34. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  35. package/dist/cli/handlers/misc.d.ts.map +1 -1
  36. package/dist/cli/handlers/operator.d.ts +16 -0
  37. package/dist/cli/handlers/operator.d.ts.map +1 -1
  38. package/dist/cli/handlers/pr.d.ts +31 -0
  39. package/dist/cli/handlers/pr.d.ts.map +1 -0
  40. package/dist/cli/handlers/run.d.ts.map +1 -1
  41. package/dist/cli/lsp/server.d.ts.map +1 -1
  42. package/dist/cli/main.d.ts.map +1 -1
  43. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  44. package/dist/cli/mcp/server.d.ts.map +1 -1
  45. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  46. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  47. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  48. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  49. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  50. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  51. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  52. package/dist/cli/mcp/workspace-tools.d.ts +4 -3
  53. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  54. package/dist/cli/registry.d.ts +74 -3
  55. package/dist/cli/registry.d.ts.map +1 -1
  56. package/dist/codegen/fetch.d.ts.map +1 -1
  57. package/dist/codegen/naming.d.ts.map +1 -1
  58. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  59. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  60. package/dist/codegen/registry.d.ts.map +1 -1
  61. package/dist/components/auto-release.d.ts +16 -0
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  64. package/dist/components/capability.d.ts +53 -0
  65. package/dist/components/capability.d.ts.map +1 -1
  66. package/dist/components/changed-files.d.ts +31 -0
  67. package/dist/components/changed-files.d.ts.map +1 -0
  68. package/dist/components/cli-support.d.ts +9 -1
  69. package/dist/components/cli-support.d.ts.map +1 -1
  70. package/dist/components/component.d.ts +24 -0
  71. package/dist/components/component.d.ts.map +1 -1
  72. package/dist/components/deploy-units.d.ts.map +1 -1
  73. package/dist/components/driver.d.ts +13 -0
  74. package/dist/components/driver.d.ts.map +1 -1
  75. package/dist/components/fan-out-output.d.ts +6 -0
  76. package/dist/components/fan-out-output.d.ts.map +1 -1
  77. package/dist/components/fan-out-record.d.ts +41 -0
  78. package/dist/components/fan-out-record.d.ts.map +1 -0
  79. package/dist/components/fan-out-run.d.ts +65 -0
  80. package/dist/components/fan-out-run.d.ts.map +1 -1
  81. package/dist/components/fan-out-support.d.ts +2 -0
  82. package/dist/components/fan-out-support.d.ts.map +1 -1
  83. package/dist/components/fan-out.d.ts +6 -0
  84. package/dist/components/fan-out.d.ts.map +1 -1
  85. package/dist/components/gated-wave-pipeline.d.ts +50 -0
  86. package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
  87. package/dist/components/index.d.ts +1 -1
  88. package/dist/components/index.d.ts.map +1 -1
  89. package/dist/components/layers.d.ts +25 -0
  90. package/dist/components/layers.d.ts.map +1 -0
  91. package/dist/components/pr-pipeline.d.ts +61 -0
  92. package/dist/components/pr-pipeline.d.ts.map +1 -0
  93. package/dist/components/pr-run.d.ts +119 -0
  94. package/dist/components/pr-run.d.ts.map +1 -0
  95. package/dist/components/promote.d.ts.map +1 -1
  96. package/dist/components/starter-plugin.d.ts.map +1 -1
  97. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  98. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  99. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  100. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  101. package/dist/components/verbs/shell.d.ts.map +1 -1
  102. package/dist/components/verbs/sign.d.ts.map +1 -1
  103. package/dist/components/verbs/verify.d.ts.map +1 -1
  104. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  105. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  106. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  107. package/dist/components/wave-plan.d.ts +49 -0
  108. package/dist/components/wave-plan.d.ts.map +1 -0
  109. package/dist/composite.d.ts.map +1 -1
  110. package/dist/config.d.ts +19 -7
  111. package/dist/config.d.ts.map +1 -1
  112. package/dist/declarable.d.ts +16 -0
  113. package/dist/declarable.d.ts.map +1 -1
  114. package/dist/discovery/cache.d.ts.map +1 -1
  115. package/dist/discovery/fold-import.d.ts +15 -5
  116. package/dist/discovery/fold-import.d.ts.map +1 -1
  117. package/dist/discovery/param-deps.d.ts +16 -0
  118. package/dist/discovery/param-deps.d.ts.map +1 -1
  119. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  120. package/dist/discovery/specifier-resolve.d.ts +37 -0
  121. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  122. package/dist/errors.d.ts.map +1 -1
  123. package/dist/fold/fold.d.ts +3 -1
  124. package/dist/fold/fold.d.ts.map +1 -1
  125. package/dist/gated-waves.d.ts +147 -0
  126. package/dist/gated-waves.d.ts.map +1 -0
  127. package/dist/graph-detail.d.ts.map +1 -1
  128. package/dist/graph-ir.d.ts.map +1 -1
  129. package/dist/graph-layout.d.ts.map +1 -1
  130. package/dist/import/base-parser.d.ts.map +1 -1
  131. package/dist/import/embedded.d.ts +7 -0
  132. package/dist/import/embedded.d.ts.map +1 -1
  133. package/dist/import/parser-options.d.ts +14 -0
  134. package/dist/import/parser-options.d.ts.map +1 -0
  135. package/dist/import/parser.d.ts +17 -0
  136. package/dist/import/parser.d.ts.map +1 -1
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/kubectl-context.d.ts.map +1 -1
  140. package/dist/lexicon-output.d.ts.map +1 -1
  141. package/dist/lexicon-schema.d.ts +3 -3
  142. package/dist/lexicon.d.ts +103 -3
  143. package/dist/lexicon.d.ts.map +1 -1
  144. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  145. package/dist/lifecycle/gate-ledger.d.ts +22 -0
  146. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  147. package/dist/lifecycle/git.d.ts +46 -1
  148. package/dist/lifecycle/git.d.ts.map +1 -1
  149. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  150. package/dist/lifecycle/observe.d.ts.map +1 -1
  151. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  152. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  153. package/dist/lifecycle/scenario.d.ts.map +1 -1
  154. package/dist/lifecycle/status.d.ts.map +1 -1
  155. package/dist/lifecycle/work-lease.d.ts +61 -2
  156. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  157. package/dist/lint/config.d.ts +8 -8
  158. package/dist/lint/engine.d.ts +6 -0
  159. package/dist/lint/engine.d.ts.map +1 -1
  160. package/dist/lint/post-synth.d.ts +18 -0
  161. package/dist/lint/post-synth.d.ts.map +1 -1
  162. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  163. package/dist/op/activities/activity-contracts.d.ts +137 -11
  164. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  165. package/dist/op/activities/apply.d.ts +79 -9
  166. package/dist/op/activities/apply.d.ts.map +1 -1
  167. package/dist/op/activities/change-set.d.ts +62 -0
  168. package/dist/op/activities/change-set.d.ts.map +1 -0
  169. package/dist/op/activities/decide.d.ts +2 -0
  170. package/dist/op/activities/decide.d.ts.map +1 -1
  171. package/dist/op/activities/factory.d.ts +137 -0
  172. package/dist/op/activities/factory.d.ts.map +1 -0
  173. package/dist/op/activities/index.d.ts +5 -1
  174. package/dist/op/activities/index.d.ts.map +1 -1
  175. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  176. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  177. package/dist/op/activity-contract.d.ts +1 -1
  178. package/dist/op/activity-contract.d.ts.map +1 -1
  179. package/dist/op/activity-failure.d.ts.map +1 -1
  180. package/dist/op/activity-profiles.d.ts.map +1 -1
  181. package/dist/op/builders.d.ts +11 -0
  182. package/dist/op/builders.d.ts.map +1 -1
  183. package/dist/op/composites/apply-op.d.ts +12 -5
  184. package/dist/op/composites/apply-op.d.ts.map +1 -1
  185. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  186. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  187. package/dist/op/decide-backend.d.ts +5 -1
  188. package/dist/op/decide-backend.d.ts.map +1 -1
  189. package/dist/op/decide-read-inputs.d.ts +4 -2
  190. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  191. package/dist/op/emulator-lifecycle.d.ts +21 -2
  192. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  193. package/dist/op/factory.d.ts +83 -0
  194. package/dist/op/factory.d.ts.map +1 -0
  195. package/dist/op/gate-approval.d.ts +5 -1
  196. package/dist/op/gate-approval.d.ts.map +1 -1
  197. package/dist/op/gate-wait.d.ts.map +1 -1
  198. package/dist/op/gate.d.ts +19 -3
  199. package/dist/op/gate.d.ts.map +1 -1
  200. package/dist/op/index.d.ts +6 -1
  201. package/dist/op/index.d.ts.map +1 -1
  202. package/dist/op/local-executor.d.ts +6 -0
  203. package/dist/op/local-executor.d.ts.map +1 -1
  204. package/dist/op/op-ir.d.ts +2 -0
  205. package/dist/op/op-ir.d.ts.map +1 -1
  206. package/dist/op/op-verb-class.d.ts.map +1 -1
  207. package/dist/op/operator.d.ts.map +1 -1
  208. package/dist/op/run-context.d.ts +39 -0
  209. package/dist/op/run-context.d.ts.map +1 -0
  210. package/dist/op/run-live.d.ts.map +1 -1
  211. package/dist/op/runtimes/local.d.ts.map +1 -1
  212. package/dist/op/source-archive.d.ts.map +1 -1
  213. package/dist/op/steward-beside.d.ts.map +1 -1
  214. package/dist/op/steward-points.d.ts.map +1 -1
  215. package/dist/op/steward.d.ts.map +1 -1
  216. package/dist/op/types.d.ts +16 -3
  217. package/dist/op/types.d.ts.map +1 -1
  218. package/dist/op/work-lease-run.d.ts +24 -4
  219. package/dist/op/work-lease-run.d.ts.map +1 -1
  220. package/dist/plan-summary.d.ts +207 -0
  221. package/dist/plan-summary.d.ts.map +1 -0
  222. package/dist/pr-forge.d.ts +105 -0
  223. package/dist/pr-forge.d.ts.map +1 -0
  224. package/dist/pr-loop.d.ts +178 -0
  225. package/dist/pr-loop.d.ts.map +1 -0
  226. package/dist/project-root.d.ts.map +1 -1
  227. package/dist/provenance.d.ts +21 -0
  228. package/dist/provenance.d.ts.map +1 -1
  229. package/dist/pseudo-parameter.d.ts.map +1 -1
  230. package/dist/reconcile.d.ts.map +1 -1
  231. package/dist/secret-materialization.d.ts.map +1 -1
  232. package/dist/telemetry-attribution.d.ts +31 -0
  233. package/dist/telemetry-attribution.d.ts.map +1 -1
  234. package/dist/terraform/emit-source.d.ts.map +1 -1
  235. package/dist/terraform/hcl2json.d.ts +45 -0
  236. package/dist/terraform/hcl2json.d.ts.map +1 -0
  237. package/dist/terraform/parse.d.ts +4 -40
  238. package/dist/terraform/parse.d.ts.map +1 -1
  239. package/dist/testing.d.ts.map +1 -1
  240. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  241. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  242. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  243. package/dist/workspace/agent-cli.d.ts +5 -0
  244. package/dist/workspace/agent-cli.d.ts.map +1 -1
  245. package/dist/workspace/box-cli.d.ts +12 -0
  246. package/dist/workspace/box-cli.d.ts.map +1 -0
  247. package/dist/workspace/box-factory.d.ts +97 -0
  248. package/dist/workspace/box-factory.d.ts.map +1 -0
  249. package/dist/workspace/box-listing.d.ts +85 -0
  250. package/dist/workspace/box-listing.d.ts.map +1 -0
  251. package/dist/workspace/box-publish.d.ts +147 -0
  252. package/dist/workspace/box-publish.d.ts.map +1 -0
  253. package/dist/workspace/broker-protocol.d.ts +190 -0
  254. package/dist/workspace/broker-protocol.d.ts.map +1 -0
  255. package/dist/workspace/changes.d.ts.map +1 -1
  256. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  257. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  258. package/dist/workspace/checks.d.ts +5 -0
  259. package/dist/workspace/checks.d.ts.map +1 -1
  260. package/dist/workspace/compose-graph.d.ts +10 -0
  261. package/dist/workspace/compose-graph.d.ts.map +1 -1
  262. package/dist/workspace/composites.d.ts +2 -2
  263. package/dist/workspace/composites.d.ts.map +1 -1
  264. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
  265. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
  266. package/dist/workspace/conformance/broker.d.ts +202 -0
  267. package/dist/workspace/conformance/broker.d.ts.map +1 -0
  268. package/dist/workspace/conformance/index.d.ts +68 -6
  269. package/dist/workspace/conformance/index.d.ts.map +1 -1
  270. package/dist/workspace/conformance/vitest.d.ts +19 -3
  271. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  272. package/dist/workspace/conformance/writer.d.ts +462 -0
  273. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  274. package/dist/workspace/decide.d.ts +126 -12
  275. package/dist/workspace/decide.d.ts.map +1 -1
  276. package/dist/workspace/decision-points.schema.json +11 -4
  277. package/dist/workspace/declaration.d.ts +156 -4
  278. package/dist/workspace/declaration.d.ts.map +1 -1
  279. package/dist/workspace/declaration.schema.json +383 -5
  280. package/dist/workspace/environments.d.ts +36 -10
  281. package/dist/workspace/environments.d.ts.map +1 -1
  282. package/dist/workspace/factory-rules.d.ts +180 -0
  283. package/dist/workspace/factory-rules.d.ts.map +1 -0
  284. package/dist/workspace/generated-files.d.ts.map +1 -1
  285. package/dist/workspace/graph-cache.d.ts.map +1 -1
  286. package/dist/workspace/graph-cli.d.ts +2 -0
  287. package/dist/workspace/graph-cli.d.ts.map +1 -1
  288. package/dist/workspace/identity.d.ts +111 -0
  289. package/dist/workspace/identity.d.ts.map +1 -0
  290. package/dist/workspace/init.d.ts +21 -0
  291. package/dist/workspace/init.d.ts.map +1 -1
  292. package/dist/workspace/intent-cli.d.ts +7 -4
  293. package/dist/workspace/intent-cli.d.ts.map +1 -1
  294. package/dist/workspace/intent-record.d.ts +36 -2
  295. package/dist/workspace/intent-record.d.ts.map +1 -1
  296. package/dist/workspace/intent.d.ts +249 -8
  297. package/dist/workspace/intent.d.ts.map +1 -1
  298. package/dist/workspace/json-edit.d.ts +24 -0
  299. package/dist/workspace/json-edit.d.ts.map +1 -0
  300. package/dist/workspace/jsonc.d.ts +11 -0
  301. package/dist/workspace/jsonc.d.ts.map +1 -1
  302. package/dist/workspace/kinds.d.ts +66 -4
  303. package/dist/workspace/kinds.d.ts.map +1 -1
  304. package/dist/workspace/lexicon-symbols.d.ts +29 -0
  305. package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
  306. package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
  307. package/dist/workspace/lineage-lock.d.ts +2 -2
  308. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  309. package/dist/workspace/lineage-upgrade.d.ts +31 -2
  310. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  311. package/dist/workspace/links.d.ts.map +1 -1
  312. package/dist/workspace/point-answer.schema.json +42 -2
  313. package/dist/workspace/points-cli.d.ts +10 -3
  314. package/dist/workspace/points-cli.d.ts.map +1 -1
  315. package/dist/workspace/points.d.ts +66 -5
  316. package/dist/workspace/points.d.ts.map +1 -1
  317. package/dist/workspace/principal-classes.d.ts +114 -0
  318. package/dist/workspace/principal-classes.d.ts.map +1 -0
  319. package/dist/workspace/reason-codes.d.ts +53 -4
  320. package/dist/workspace/reason-codes.d.ts.map +1 -1
  321. package/dist/workspace/record-assets.d.ts.map +1 -1
  322. package/dist/workspace/record-sessions.d.ts +5 -7
  323. package/dist/workspace/record-sessions.d.ts.map +1 -1
  324. package/dist/workspace/records-checkout.d.ts +54 -0
  325. package/dist/workspace/records-checkout.d.ts.map +1 -0
  326. package/dist/workspace/records-cli.d.ts +34 -1
  327. package/dist/workspace/records-cli.d.ts.map +1 -1
  328. package/dist/workspace/records-close.d.ts +7 -3
  329. package/dist/workspace/records-close.d.ts.map +1 -1
  330. package/dist/workspace/records-since.d.ts.map +1 -1
  331. package/dist/workspace/records-write.d.ts +68 -7
  332. package/dist/workspace/records-write.d.ts.map +1 -1
  333. package/dist/workspace/records.d.ts +43 -9
  334. package/dist/workspace/records.d.ts.map +1 -1
  335. package/dist/workspace/runs-cli.d.ts +296 -0
  336. package/dist/workspace/runs-cli.d.ts.map +1 -0
  337. package/dist/workspace/runs.d.ts +544 -0
  338. package/dist/workspace/runs.d.ts.map +1 -0
  339. package/dist/workspace/session-kinds.d.ts +1 -1
  340. package/dist/workspace/session-kinds.d.ts.map +1 -1
  341. package/dist/workspace/source-block.d.ts +1 -1
  342. package/dist/workspace/source-block.d.ts.map +1 -1
  343. package/dist/workspace/squash.d.ts +80 -0
  344. package/dist/workspace/squash.d.ts.map +1 -0
  345. package/dist/workspace/status-gates.d.ts +17 -3
  346. package/dist/workspace/status-gates.d.ts.map +1 -1
  347. package/dist/workspace/status.d.ts +64 -0
  348. package/dist/workspace/status.d.ts.map +1 -1
  349. package/dist/workspace/symbols.d.ts +63 -0
  350. package/dist/workspace/symbols.d.ts.map +1 -0
  351. package/dist/workspace/trailer-joins.d.ts +46 -0
  352. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  353. package/dist/workspace/trailers.d.ts +89 -0
  354. package/dist/workspace/trailers.d.ts.map +1 -0
  355. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  356. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  357. package/dist/workspace/trust/run-commits.d.ts +46 -0
  358. package/dist/workspace/trust/run-commits.d.ts.map +1 -0
  359. package/dist/workspace/trust/run-statement.d.ts +128 -0
  360. package/dist/workspace/trust/run-statement.d.ts.map +1 -0
  361. package/dist/workspace/trust/seal.d.ts +38 -0
  362. package/dist/workspace/trust/seal.d.ts.map +1 -1
  363. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  364. package/dist/workspace/trust/verify-cli.d.ts +1 -1
  365. package/dist/workspace/trust/verify.d.ts +16 -2
  366. package/dist/workspace/trust/verify.d.ts.map +1 -1
  367. package/dist/workspace/wip-cli.d.ts +21 -0
  368. package/dist/workspace/wip-cli.d.ts.map +1 -0
  369. package/dist/workspace/wip.d.ts +268 -0
  370. package/dist/workspace/wip.d.ts.map +1 -0
  371. package/dist/workspace/work-cli.d.ts +39 -3
  372. package/dist/workspace/work-cli.d.ts.map +1 -1
  373. package/dist/workspace/work-evidence.d.ts +1 -1
  374. package/dist/workspace/work-evidence.d.ts.map +1 -1
  375. package/dist/workspace/work-size.d.ts +55 -0
  376. package/dist/workspace/work-size.d.ts.map +1 -0
  377. package/dist/workspace/work.d.ts +26 -1
  378. package/dist/workspace/work.d.ts.map +1 -1
  379. package/dist/workspace/workspace-kinds.schema.json +122 -0
  380. package/dist/workspace/workspace-principals.schema.json +60 -0
  381. package/dist/workspace/write-lock-cli.d.ts +60 -0
  382. package/dist/workspace/write-lock-cli.d.ts.map +1 -0
  383. package/dist/workspace/write-lock.d.ts +152 -0
  384. package/dist/workspace/write-lock.d.ts.map +1 -0
  385. package/dist/workspace/write-scope.d.ts +83 -19
  386. package/dist/workspace/write-scope.d.ts.map +1 -1
  387. package/dist/yaml.d.ts +21 -39
  388. package/dist/yaml.d.ts.map +1 -1
  389. package/package.json +7 -2
  390. package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
  391. package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
  392. package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
  393. package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
  394. package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
  395. package/src/__fixtures__/change-set/warden.plan.json +44 -0
  396. package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
  397. package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
  398. package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
  399. package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
  400. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
  401. package/src/audit/core.test.ts +15 -0
  402. package/src/audit/core.ts +8 -2
  403. package/src/audit/discover.test.ts +11 -0
  404. package/src/audit/discover.ts +7 -2
  405. package/src/audit/prior-art.ts +15 -0
  406. package/src/change-set-bundle.test.ts +57 -0
  407. package/src/change-set.test.ts +215 -0
  408. package/src/change-set.ts +445 -0
  409. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  410. package/src/cli/commands/audit-opt-in.test.ts +54 -0
  411. package/src/cli/commands/audit.ts +29 -2
  412. package/src/cli/commands/build.test.ts +19 -0
  413. package/src/cli/commands/build.ts +3 -2
  414. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  415. package/src/cli/commands/carve-emit.ts +5 -19
  416. package/src/cli/commands/check-lexicon.test.ts +62 -1
  417. package/src/cli/commands/check-lexicon.ts +36 -6
  418. package/src/cli/commands/import-live.test.ts +18 -0
  419. package/src/cli/commands/import-parser-options.test.ts +133 -0
  420. package/src/cli/commands/import.ts +21 -3
  421. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  422. package/src/cli/commands/init.test.ts +8 -1
  423. package/src/cli/commands/init.ts +23 -8
  424. package/src/cli/commands/lint.test.ts +37 -0
  425. package/src/cli/commands/onboard.test.ts +53 -3
  426. package/src/cli/commands/onboard.ts +52 -4
  427. package/src/cli/commands/pinned-upgrade.ts +73 -33
  428. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  429. package/src/cli/handlers/build.ts +13 -1
  430. package/src/cli/handlers/change-set.test.ts +56 -0
  431. package/src/cli/handlers/change-set.ts +44 -0
  432. package/src/cli/handlers/components.ts +2 -2
  433. package/src/cli/handlers/dev.ts +8 -6
  434. package/src/cli/handlers/fan-out.test.ts +221 -2
  435. package/src/cli/handlers/fan-out.ts +165 -75
  436. package/src/cli/handlers/graph.ts +3 -0
  437. package/src/cli/handlers/lifecycle.test.ts +67 -0
  438. package/src/cli/handlers/lifecycle.ts +6 -5
  439. package/src/cli/handlers/misc.ts +2 -0
  440. package/src/cli/handlers/operator.test.ts +21 -0
  441. package/src/cli/handlers/operator.ts +121 -6
  442. package/src/cli/handlers/pr.ts +373 -0
  443. package/src/cli/handlers/run.test.ts +111 -0
  444. package/src/cli/handlers/run.ts +86 -24
  445. package/src/cli/handlers/scenario.ts +2 -2
  446. package/src/cli/main.test.ts +21 -0
  447. package/src/cli/main.ts +246 -30
  448. package/src/cli/mcp/never-over-mcp.test.ts +101 -0
  449. package/src/cli/mcp/op-tools.ts +24 -2
  450. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  451. package/src/cli/mcp/workspace-tools.ts +62 -7
  452. package/src/cli/registry.ts +74 -3
  453. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  454. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  455. package/src/codegen/pinned-upgrade.test.ts +104 -0
  456. package/src/codegen/pinned-upgrade.ts +250 -56
  457. package/src/codegen/testdata/postgres-tags.json +242 -0
  458. package/src/components/auto-release.ts +1 -1
  459. package/src/components/capability.ts +55 -0
  460. package/src/components/changed-files.ts +66 -0
  461. package/src/components/cli-support.ts +28 -5
  462. package/src/components/component.schema.json +17 -0
  463. package/src/components/component.ts +25 -0
  464. package/src/components/deploy-units.ts +3 -0
  465. package/src/components/driver.test.ts +52 -0
  466. package/src/components/driver.ts +31 -13
  467. package/src/components/fan-out-output.ts +42 -1
  468. package/src/components/fan-out-record.ts +69 -0
  469. package/src/components/fan-out-run.test.ts +17 -0
  470. package/src/components/fan-out-run.ts +304 -1
  471. package/src/components/fan-out-support.ts +3 -0
  472. package/src/components/fan-out-waves.test.ts +375 -0
  473. package/src/components/fan-out.ts +18 -17
  474. package/src/components/gated-wave-pipeline.ts +82 -0
  475. package/src/components/index.ts +1 -0
  476. package/src/components/layers.ts +30 -0
  477. package/src/components/pr-pipeline.ts +91 -0
  478. package/src/components/pr-run.test.ts +205 -0
  479. package/src/components/pr-run.ts +280 -0
  480. package/src/components/promote.ts +5 -0
  481. package/src/components/verbs/shell.test.ts +11 -0
  482. package/src/components/verbs/shell.ts +7 -3
  483. package/src/components/wave-plan.ts +124 -0
  484. package/src/config.test.ts +21 -0
  485. package/src/config.ts +15 -0
  486. package/src/declarable.test.ts +21 -0
  487. package/src/declarable.ts +19 -0
  488. package/src/discovery/fold-composite.test.ts +41 -5
  489. package/src/discovery/fold-import.test.ts +129 -0
  490. package/src/discovery/fold-import.ts +643 -131
  491. package/src/discovery/fold-package-composite.test.ts +264 -0
  492. package/src/discovery/fold-specifiers.test.ts +191 -0
  493. package/src/discovery/param-deps.test.ts +66 -1
  494. package/src/discovery/param-deps.ts +45 -0
  495. package/src/discovery/sandbox/bundle.ts +1 -1
  496. package/src/discovery/specifier-resolve.ts +344 -0
  497. package/src/fold/fold.test.ts +39 -1
  498. package/src/fold/fold.ts +83 -9
  499. package/src/fold-provenance.test.ts +140 -0
  500. package/src/gated-waves-bundle.test.ts +62 -0
  501. package/src/gated-waves.test.ts +118 -0
  502. package/src/gated-waves.ts +240 -0
  503. package/src/graph-ir.test.ts +83 -0
  504. package/src/graph-ir.ts +29 -0
  505. package/src/import/embedded.test.ts +20 -0
  506. package/src/import/embedded.ts +13 -0
  507. package/src/import/parser-options.ts +46 -0
  508. package/src/import/parser.ts +20 -0
  509. package/src/index.ts +1 -0
  510. package/src/lexicon.ts +106 -3
  511. package/src/lifecycle/gate-ledger.ts +23 -0
  512. package/src/lifecycle/git.ts +102 -16
  513. package/src/lifecycle/observe.test.ts +18 -0
  514. package/src/lifecycle/observe.ts +6 -4
  515. package/src/lifecycle/snapshot.ts +2 -2
  516. package/src/lifecycle/work-lease.test.ts +1 -1
  517. package/src/lifecycle/work-lease.ts +93 -2
  518. package/src/lint/engine.test.ts +55 -0
  519. package/src/lint/engine.ts +30 -4
  520. package/src/lint/output-docs.test.ts +59 -56
  521. package/src/lint/post-synth.test.ts +19 -0
  522. package/src/lint/post-synth.ts +19 -1
  523. package/src/meta/declared-imports.test.ts +1 -1
  524. package/src/op/activities/activity-contracts.ts +84 -0
  525. package/src/op/activities/apply.test.ts +189 -5
  526. package/src/op/activities/apply.ts +230 -8
  527. package/src/op/activities/change-set.ts +114 -0
  528. package/src/op/activities/decide.ts +3 -0
  529. package/src/op/activities/factory.ts +675 -0
  530. package/src/op/activities/index.ts +9 -0
  531. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  532. package/src/op/activities/lexicon-upgrade.ts +154 -51
  533. package/src/op/activity-contract.test.ts +21 -1
  534. package/src/op/activity-contract.ts +19 -9
  535. package/src/op/builders.ts +23 -0
  536. package/src/op/composites/apply-op.ts +12 -5
  537. package/src/op/composites/composites.test.ts +30 -3
  538. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  539. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  540. package/src/op/decide-backend.ts +5 -1
  541. package/src/op/decide-read-inputs.ts +33 -5
  542. package/src/op/emulator-lifecycle.test.ts +23 -0
  543. package/src/op/emulator-lifecycle.ts +52 -14
  544. package/src/op/factory.e2e.test.ts +232 -0
  545. package/src/op/factory.ts +118 -0
  546. package/src/op/gate-approval.test.ts +74 -0
  547. package/src/op/gate-approval.ts +5 -1
  548. package/src/op/gate.ts +31 -5
  549. package/src/op/index.ts +11 -1
  550. package/src/op/local-executor.test.ts +15 -0
  551. package/src/op/local-executor.ts +40 -12
  552. package/src/op/local-output.ts +1 -1
  553. package/src/op/op-ir.test.ts +9 -0
  554. package/src/op/op-ir.ts +4 -0
  555. package/src/op/op-verb-class.ts +3 -0
  556. package/src/op/operator.ts +4 -0
  557. package/src/op/run-context.test.ts +141 -0
  558. package/src/op/run-context.ts +51 -0
  559. package/src/op/runtimes/local.test.ts +14 -0
  560. package/src/op/runtimes/local.ts +2 -0
  561. package/src/op/steward-beside.ts +2 -0
  562. package/src/op/types.ts +16 -3
  563. package/src/op/work-lease-run.test.ts +47 -0
  564. package/src/op/work-lease-run.ts +76 -11
  565. package/src/plan-summary.test.ts +263 -0
  566. package/src/plan-summary.ts +845 -0
  567. package/src/pr-forge.test.ts +237 -0
  568. package/src/pr-forge.ts +332 -0
  569. package/src/pr-loop-bundle.test.ts +46 -0
  570. package/src/pr-loop.test.ts +171 -0
  571. package/src/pr-loop.ts +324 -0
  572. package/src/provenance.ts +35 -0
  573. package/src/telemetry-attribution.test.ts +23 -1
  574. package/src/telemetry-attribution.ts +51 -0
  575. package/src/terraform/hcl2json.test.ts +21 -0
  576. package/src/terraform/hcl2json.ts +81 -0
  577. package/src/terraform/parse.ts +11 -74
  578. package/src/workspace/agent-cli.ts +7 -3
  579. package/src/workspace/agent.schema.json +22 -0
  580. package/src/workspace/app-kind.test.ts +196 -0
  581. package/src/workspace/box-cli.ts +113 -0
  582. package/src/workspace/box-factory.test.ts +323 -0
  583. package/src/workspace/box-factory.ts +136 -0
  584. package/src/workspace/box-listing-write.schema.json +204 -0
  585. package/src/workspace/box-listing.test.ts +234 -0
  586. package/src/workspace/box-listing.ts +324 -0
  587. package/src/workspace/box-publish.schema.json +498 -0
  588. package/src/workspace/box-publish.test.ts +204 -0
  589. package/src/workspace/box-publish.ts +420 -0
  590. package/src/workspace/box-ship.test.ts +96 -0
  591. package/src/workspace/broker-protocol.schema.json +186 -0
  592. package/src/workspace/broker-protocol.test.ts +122 -0
  593. package/src/workspace/broker-protocol.ts +317 -0
  594. package/src/workspace/builder-tiers.test.ts +146 -0
  595. package/src/workspace/change-set.schema.json +460 -0
  596. package/src/workspace/changes.schema.json +12 -20
  597. package/src/workspace/changes.ts +4 -1
  598. package/src/workspace/chant-migrations.e2e.test.ts +17 -5
  599. package/src/workspace/checks/boxes.test.ts +5 -0
  600. package/src/workspace/checks.ts +39 -8
  601. package/src/workspace/component-environments.test.ts +105 -0
  602. package/src/workspace/compose-graph.ts +7 -0
  603. package/src/workspace/composites.schema.json +23 -4
  604. package/src/workspace/composites.test.ts +8 -8
  605. package/src/workspace/composites.ts +13 -2
  606. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
  607. package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
  608. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  609. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  610. package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  611. package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  612. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  613. package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  614. package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  615. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  616. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  617. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  618. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  619. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  620. package/src/workspace/conformance/broker.test.ts +122 -0
  621. package/src/workspace/conformance/broker.ts +792 -0
  622. package/src/workspace/conformance/conformance.e2e.test.ts +36 -3
  623. package/src/workspace/conformance/index.mjs +51 -3
  624. package/src/workspace/conformance/index.ts +107 -15
  625. package/src/workspace/conformance/vitest.ts +76 -2
  626. package/src/workspace/conformance/writer-conformance.e2e.test.ts +177 -0
  627. package/src/workspace/conformance/writer.test.ts +186 -0
  628. package/src/workspace/conformance/writer.ts +1191 -0
  629. package/src/workspace/decide.test.ts +208 -4
  630. package/src/workspace/decide.ts +433 -73
  631. package/src/workspace/decision-points.schema.json +11 -4
  632. package/src/workspace/declaration.schema.json +383 -5
  633. package/src/workspace/declaration.ts +315 -10
  634. package/src/workspace/environments.ts +66 -14
  635. package/src/workspace/factory-rules.test.ts +62 -0
  636. package/src/workspace/factory-rules.ts +218 -0
  637. package/src/workspace/graph-cli.ts +6 -3
  638. package/src/workspace/graph.schema.json +314 -0
  639. package/src/workspace/identity.test.ts +219 -0
  640. package/src/workspace/identity.ts +186 -0
  641. package/src/workspace/init.ts +82 -2
  642. package/src/workspace/intent-cli.ts +84 -13
  643. package/src/workspace/intent-patch-id.test.ts +162 -0
  644. package/src/workspace/intent-record.schema.json +336 -1
  645. package/src/workspace/intent-record.ts +96 -16
  646. package/src/workspace/intent-reviews.test.ts +76 -0
  647. package/src/workspace/intent-squash.test.ts +213 -0
  648. package/src/workspace/intent-why.test.ts +274 -0
  649. package/src/workspace/intent.schema.json +950 -9
  650. package/src/workspace/intent.test.ts +11 -2
  651. package/src/workspace/intent.ts +722 -65
  652. package/src/workspace/json-edit.test.ts +121 -0
  653. package/src/workspace/json-edit.ts +142 -0
  654. package/src/workspace/jsonc.ts +20 -0
  655. package/src/workspace/kinds.ts +201 -39
  656. package/src/workspace/lexicon-symbols.test.ts +148 -0
  657. package/src/workspace/lexicon-symbols.ts +125 -0
  658. package/src/workspace/lineage-upgrade.test.ts +63 -0
  659. package/src/workspace/lineage-upgrade.ts +146 -5
  660. package/src/workspace/plan-summary.schema.json +155 -0
  661. package/src/workspace/point-answer.schema.json +42 -2
  662. package/src/workspace/points-cli.ts +42 -16
  663. package/src/workspace/points-write.schema.json +163 -4
  664. package/src/workspace/points.schema.json +157 -2
  665. package/src/workspace/points.test.ts +13 -1
  666. package/src/workspace/points.ts +118 -12
  667. package/src/workspace/pr-report.schema.json +95 -0
  668. package/src/workspace/principal-classes.test.ts +175 -0
  669. package/src/workspace/principal-classes.ts +307 -0
  670. package/src/workspace/profiles.test.ts +159 -0
  671. package/src/workspace/read-contract.test.ts +2 -2
  672. package/src/workspace/reason-codes.test.ts +23 -3
  673. package/src/workspace/reason-codes.ts +61 -4
  674. package/src/workspace/record-sessions.ts +9 -8
  675. package/src/workspace/records-amend.schema.json +80 -0
  676. package/src/workspace/records-checkout.ts +106 -0
  677. package/src/workspace/records-cli.ts +123 -17
  678. package/src/workspace/records-close.schema.json +79 -0
  679. package/src/workspace/records-close.ts +31 -7
  680. package/src/workspace/records-concurrent.e2e.test.ts +135 -0
  681. package/src/workspace/records-concurrent.test.ts +145 -0
  682. package/src/workspace/records-formats.test.ts +46 -10
  683. package/src/workspace/records-new.schema.json +9 -0
  684. package/src/workspace/records-review.schema.json +80 -0
  685. package/src/workspace/records-sessions-write.test.ts +69 -0
  686. package/src/workspace/records-sessions.test.ts +22 -0
  687. package/src/workspace/records-uncommitted.test.ts +171 -0
  688. package/src/workspace/records-write.ts +219 -30
  689. package/src/workspace/records.schema.json +88 -1
  690. package/src/workspace/records.ts +76 -8
  691. package/src/workspace/reference-kinds/app/package.json +10 -0
  692. package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  693. package/src/workspace/run-statement.schema.json +622 -0
  694. package/src/workspace/runs-cli.ts +710 -0
  695. package/src/workspace/runs-statement.test.ts +239 -0
  696. package/src/workspace/runs-write.schema.json +994 -0
  697. package/src/workspace/runs.schema.json +1257 -0
  698. package/src/workspace/runs.test.ts +281 -0
  699. package/src/workspace/runs.ts +970 -0
  700. package/src/workspace/session-kinds.ts +3 -3
  701. package/src/workspace/squash.ts +198 -0
  702. package/src/workspace/status-contract.test.ts +10 -2
  703. package/src/workspace/status-gates.ts +25 -9
  704. package/src/workspace/status.schema.json +252 -4
  705. package/src/workspace/status.ts +110 -1
  706. package/src/workspace/symbols.ts +191 -0
  707. package/src/workspace/trailer-joins.test.ts +171 -0
  708. package/src/workspace/trailer-joins.ts +82 -0
  709. package/src/workspace/trailers.ts +148 -0
  710. package/src/workspace/trust/run-commits.ts +115 -0
  711. package/src/workspace/trust/run-statement.ts +226 -0
  712. package/src/workspace/trust/seal.ts +58 -1
  713. package/src/workspace/trust/verify-cli.ts +6 -5
  714. package/src/workspace/trust/verify.ts +39 -6
  715. package/src/workspace/wip-cli.ts +97 -0
  716. package/src/workspace/wip-write.schema.json +504 -0
  717. package/src/workspace/wip.schema.json +334 -0
  718. package/src/workspace/wip.test.ts +294 -0
  719. package/src/workspace/wip.ts +753 -0
  720. package/src/workspace/work-cli.e2e.test.ts +28 -1
  721. package/src/workspace/work-cli.ts +136 -8
  722. package/src/workspace/work-evidence.schema.json +5 -0
  723. package/src/workspace/work-history.schema.json +73 -1
  724. package/src/workspace/work-history.test.ts +48 -5
  725. package/src/workspace/work-kind-fields.test.ts +154 -0
  726. package/src/workspace/work-lease.schema.json +14 -1
  727. package/src/workspace/work-size.test.ts +77 -0
  728. package/src/workspace/work-size.ts +93 -0
  729. package/src/workspace/work.ts +82 -0
  730. package/src/workspace/workspace-kinds.schema.json +122 -0
  731. package/src/workspace/workspace-principals.schema.json +60 -0
  732. package/src/workspace/write-lock-cli.ts +131 -0
  733. package/src/workspace/write-lock.schema.json +172 -0
  734. package/src/workspace/write-lock.test.ts +189 -0
  735. package/src/workspace/write-lock.ts +474 -0
  736. package/src/workspace/write-scope.test.ts +144 -3
  737. package/src/workspace/write-scope.ts +192 -45
  738. package/src/yaml.test.ts +111 -1
  739. package/src/yaml.ts +141 -549
@@ -150,14 +150,22 @@ function isStepOutputRefValue(value: unknown): boolean {
150
150
  return typeof value === "object" && value !== null && (value as Record<symbol, unknown>)[STEP_OUTPUT_REF_BRAND] === true;
151
151
  }
152
152
 
153
- /** The value at `path` (a zod issue's `.path`) inside `obj`, or `undefined` if any segment doesn't resolve. */
154
- function valueAtPath(obj: unknown, path: ReadonlyArray<PropertyKey>): unknown {
153
+ /**
154
+ * Does any prefix of `path` (a zod issue's `.path`) inside `obj` land on a
155
+ * step-output reference? A reference stands in for the whole value at its
156
+ * position, so an issue at or below it describes the placeholder, not the
157
+ * value it resolves to. "Below" matters for a whole-value reference in a
158
+ * record-typed arg (`inputs: step.out.json`, #3299): zod walks the
159
+ * reference's own keys, brand symbol included, and reports issues inside it.
160
+ */
161
+ function pathCrossesStepOutputRef(obj: unknown, path: ReadonlyArray<PropertyKey>): boolean {
155
162
  let current = obj;
156
163
  for (const segment of path) {
157
- if (current === null || typeof current !== "object") return undefined;
164
+ if (current === null || typeof current !== "object") return false;
158
165
  current = (current as Record<PropertyKey, unknown>)[segment];
166
+ if (isStepOutputRefValue(current)) return true;
159
167
  }
160
- return current;
168
+ return false;
161
169
  }
162
170
 
163
171
  /** Unwrap `ZodOptional`/`ZodNullable`/`ZodDefault` (and similar) down to the schema they wrap. */
@@ -270,16 +278,18 @@ export function validateActivitySteps(
270
278
  const parsed = contract.args.safeParse(step.args ?? {});
271
279
  if (!parsed.success) {
272
280
  for (const issue of parsed.error.issues) {
273
- // A step-output reference (#1290) sitting at this path is a
274
- // placeholder object at build time, not the value it will
275
- // resolve to — so an args-schema type mismatch here is a false
281
+ // A step-output reference (#1290) sitting at this path, or above
282
+ // it, is a placeholder object at build time, not the value it
283
+ // will resolve to — so an args-schema issue there is a false
276
284
  // positive; OPS013 (`validateStepOutputRefs`) is what validates
277
285
  // a reference, against the *producer's* declared return schema.
278
286
  // An unrecognized-key issue's path is the parent object (`[]`
279
287
  // for a top-level extra key), which is never itself a reference,
280
288
  // so a genuinely misspelled key is still caught either way.
281
- if (isStepOutputRefValue(valueAtPath(step.args, issue.path))) continue;
282
- const path = issue.path.length > 0 ? issue.path.join(".") : "(args)";
289
+ if (pathCrossesStepOutputRef(step.args, issue.path)) continue;
290
+ // String(), not join(): a zod path can hold a symbol key, and
291
+ // join() throws converting one (#3299).
292
+ const path = issue.path.length > 0 ? issue.path.map((segment) => String(segment)).join(".") : "(args)";
283
293
  issues.push({ opName: config.name, phase: phase.name, fn: step.fn, message: `args.${path}: ${issue.message}` });
284
294
  }
285
295
  }
@@ -18,6 +18,7 @@ import type { PolicyGateArgs } from "./activities/policy";
18
18
  import type { GuardValidateArgs } from "./activities/guard-validate";
19
19
  import type { WorkEvidenceArgs } from "./activities/work-evidence";
20
20
  import type { DecideArgs } from "./activities/decide";
21
+ import type { ComposeChangeSetArgs, LifecyclePlanChangeSetArgs, ReadChangeSetPartArgs } from "./activities/change-set";
21
22
  import { isValidCronExpression, cronSyntaxMessage } from "./cron";
22
23
 
23
24
  /** An `activity()` result — the plain `ActivityStep` shape plus the `.out` reference sugar (#1290). */
@@ -398,6 +399,28 @@ export const releasePlan = (args: WithStepRefs<ReleasePlanArgs> & StepOpts): Nam
398
399
  return activity("releasePlan", rest, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
399
400
  };
400
401
 
402
+ /**
403
+ * Join members' change-set parts into one document (#3181). Its `digest` is
404
+ * what a combined run's gate binds: `gate("approve", { plan:
405
+ * changeSet.out.digest })`. Defaults to the `fastIdempotent` profile.
406
+ */
407
+ export const composeChangeSet = (args: WithStepRefs<ComposeChangeSetArgs> & StepOpts): NamedActivityStep => {
408
+ const { args: rest, profile, id } = takeProfileAndId(args as Record<string, unknown>);
409
+ return activity("composeChangeSet", rest, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
410
+ };
411
+
412
+ /** A chant member's change-set part, from `chant lifecycle plan <env> --json` (#3181). Its `part` feeds {@link composeChangeSet}. */
413
+ export const lifecyclePlanChangeSet = (args: WithStepRefs<LifecyclePlanChangeSetArgs> & StepOpts): NamedActivityStep => {
414
+ const { args: rest, profile, id } = takeProfileAndId(args as Record<string, unknown>);
415
+ return activity("lifecyclePlanChangeSet", rest, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
416
+ };
417
+
418
+ /** A member's change-set part from a plan file a chant or warden run wrote (#3181). Its `part` feeds {@link composeChangeSet}. */
419
+ export const readChangeSetPart = (args: WithStepRefs<ReadChangeSetPartArgs> & StepOpts): NamedActivityStep => {
420
+ const { args: rest, profile, id } = takeProfileAndId(args as Record<string, unknown>);
421
+ return activity("readChangeSetPart", rest, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
422
+ };
423
+
401
424
  /**
402
425
  * Record a release in the release ledger with its plan (#2782, ws-055), once:
403
426
  * a retry whose release the ledger already names records nothing. Defaults to
@@ -10,8 +10,11 @@
10
10
  * the ownership tag on `arm` (chant #1448 — previously `--mode Complete`, which
11
11
  * removed resources chant never applied), the ownership label on `gcp`
12
12
  * (chant #1449), the metadata marker (machines) and managed app
13
- * (volumes/ips/certs/secrets) on `fly` (chant #1449), and the stack itself on
14
- * `cloudformation`, which a resource CFN did not create is not in. All of
13
+ * (volumes/ips/certs/secrets) on `fly` (chant #1449), the ownership labels on
14
+ * `grafana` (chant #3011), the comment marker on `clickhouse` (chant #3208)
15
+ * and `postgres` (chant #3280),
16
+ * and the stack itself on `cloudformation`, which a
17
+ * resource CFN did not create is not in. All of
15
18
  * them are owned-only. See {@link DeleteMode}.
16
19
  *
17
20
  * A gate is a fact, not a wait (#2119): the local executor reads the gate
@@ -52,14 +55,18 @@ import { defaultOutput, hasNativeRollback, type ApplyTarget, type DeleteMode } f
52
55
  export interface ApplyOpConfig {
53
56
  /** Op name (kebab-case). */
54
57
  name: string;
55
- /** Environment — CFN stack name / ARM resource group / kube context env;
56
- * a log label on `gcp` and `fly`. */
58
+ /** Environment — CFN stack name / ARM resource group / kube context env /
59
+ * the `grafana.profiles.<env>` entry on `grafana` / the `sql.profiles.<env>`
60
+ * entry on `clickhouse` and `postgres`; a log label on `gcp` and
61
+ * `fly`. */
57
62
  env: string;
58
63
  /** Native apply mechanism. Default: "kubectl". */
59
64
  target?: ApplyTarget;
60
65
  /** Built manifest/template path. Default per target: `dist` (dir) for kubectl,
61
66
  * `template.json` (file) for CloudFormation/ARM, `dist/gcp.yaml` for gcp,
62
- * `dist/fly.json` for fly. Must match your build output. */
67
+ * `dist/fly.json` for fly, `dist/grafana.json` (the build index) for
68
+ * grafana, `dist/schema.json` for clickhouse and postgres. Must match your
69
+ * build output. */
63
70
  output?: string;
64
71
  /** Project directory to build. Default: ".". */
65
72
  path?: string;
@@ -157,6 +157,33 @@ describe("ApplyOp: shape", () => {
157
157
  expect(applyStep.fn).toBe("nativeApply");
158
158
  expect(applyStep.args).toEqual({ target: "kubectl", env: "prod", output: "dist", deleteMode: "never" });
159
159
  });
160
+
161
+ test("target clickhouse applies the sql build output, dist/schema.json by default (#3208)", () => {
162
+ const { op } = ApplyOp({ name: "p", env: "prod", target: "clickhouse", delete: "owned-only" });
163
+ const phases = getProps(op).phases as Array<Record<string, unknown>>;
164
+ const applyStep = (phases[2].steps as Array<Record<string, unknown>>)[0];
165
+ expect(applyStep.fn).toBe("nativeApply");
166
+ expect(applyStep.args).toEqual({ target: "clickhouse", env: "prod", output: "dist/schema.json", deleteMode: "owned-only" });
167
+ expect(getProps(op).onFailure).toBeUndefined();
168
+ });
169
+
170
+ test("target postgres applies the sql build output, dist/schema.json by default (#3280)", () => {
171
+ const { op } = ApplyOp({ name: "p", env: "prod", target: "postgres", delete: "owned-only" });
172
+ const phases = getProps(op).phases as Array<Record<string, unknown>>;
173
+ const applyStep = (phases[2].steps as Array<Record<string, unknown>>)[0];
174
+ expect(applyStep.fn).toBe("nativeApply");
175
+ expect(applyStep.args).toEqual({ target: "postgres", env: "prod", output: "dist/schema.json", deleteMode: "owned-only" });
176
+ expect(getProps(op).onFailure).toBeUndefined();
177
+ });
178
+
179
+ test("target grafana applies the build index, dist/grafana.json by default (#3011)", () => {
180
+ const { op } = ApplyOp({ name: "p", env: "prod", target: "grafana", delete: "owned-only" });
181
+ const phases = getProps(op).phases as Array<Record<string, unknown>>;
182
+ const applyStep = (phases[2].steps as Array<Record<string, unknown>>)[0];
183
+ expect(applyStep.fn).toBe("nativeApply");
184
+ expect(applyStep.args).toEqual({ target: "grafana", env: "prod", output: "dist/grafana.json", deleteMode: "owned-only" });
185
+ expect(getProps(op).onFailure).toBeUndefined();
186
+ });
160
187
  });
161
188
 
162
189
  describe("ApplyOp: gating + deletes", () => {
@@ -274,7 +301,7 @@ describe("ApplyOp: compensation (#125, total-or-refused in #1449)", () => {
274
301
  });
275
302
 
276
303
  test("compensate: true is refused at build time for every rollback-less target (#1449)", () => {
277
- for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly"] as const) {
304
+ for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres"] as const) {
278
305
  expect(() => ApplyOp({ name: "p", env: "prod", target, compensate: true })).toThrow(
279
306
  new RegExp(`ApplyOp "p": compensate is enabled, but target "${target}" has no automatic rollback`),
280
307
  );
@@ -296,7 +323,7 @@ describe("ApplyOp: compensation (#125, total-or-refused in #1449)", () => {
296
323
  });
297
324
 
298
325
  test("an object without a command is refused the same way as true", () => {
299
- for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly"] as const) {
326
+ for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres"] as const) {
300
327
  expect(() => ApplyOp({ name: "p", env: "prod", target, compensate: {} })).toThrow(
301
328
  /has no automatic rollback/,
302
329
  );
@@ -304,7 +331,7 @@ describe("ApplyOp: compensation (#125, total-or-refused in #1449)", () => {
304
331
  });
305
332
 
306
333
  test("a command lifts the refusal on every target", () => {
307
- for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "cloudformation"] as const) {
334
+ for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres", "cloudformation"] as const) {
308
335
  const { op } = ApplyOp({
309
336
  name: "p",
310
337
  env: "prod",
@@ -49,17 +49,22 @@ describe("LexiconUpgradeOp composite (#527)", () => {
49
49
  expect(phases[0].steps[0].outcomeAttribute).toEqual({ name: "HasUpgrade", from: "hasUpgrade" });
50
50
  });
51
51
 
52
- test("in-scope set is exactly the 9 lexicons (helm/forgejo excluded)", () => {
52
+ test("known set is exactly the 11 lexicons (helm/forgejo excluded)", () => {
53
53
  // cedar joined with #1650: it pins `CEDAR_WASM_VERSION`, a dependency
54
54
  // rather than a downloaded spec, but the pinned-constant machinery the Op
55
55
  // drives is identical. helm/forgejo still have no upstream at all.
56
56
  expect([...IN_SCOPE_LEXICONS].sort()).toEqual(
57
- ["aws", "azure", "cedar", "docker", "fly", "gcp", "github", "gitlab", "k8s"].sort(),
57
+ ["aws", "azure", "cedar", "docker", "fly", "gcp", "github", "gitlab", "k3s", "k8s", "sql"].sort(),
58
58
  );
59
59
  expect(IN_SCOPE_LEXICONS).not.toContain("helm");
60
60
  expect(IN_SCOPE_LEXICONS).not.toContain("forgejo");
61
61
  });
62
62
 
63
+ test("accepts a pinned lexicon by name, discovered at run time", () => {
64
+ expect(() => LexiconUpgradeOp({ lexicon: "sql" })).not.toThrow();
65
+ expect(() => LexiconUpgradeOp({ lexicon: "k3s" })).not.toThrow();
66
+ });
67
+
63
68
  test("rejects out-of-scope lexicons at construction", () => {
64
69
  for (const l of ["helm", "forgejo"]) {
65
70
  expect(() => LexiconUpgradeOp({ lexicon: l as never })).toThrow(/not in scope/);
@@ -13,9 +13,13 @@
13
13
  * lands on the Op itself (#2120).
14
14
  *
15
15
  * Lexicon classification (which check the activity dispatches to):
16
- * PINNED {k8s, gcp, docker, gitlab} → checkPinnedUpgrade
17
- * ROLLING {aws, azure, github} → checkRollingUpgrade
18
- * helm / forgejo are excluded — no upstream spec.
16
+ * ROLLING {aws, azure, github, fly} → checkRollingUpgrade
17
+ * PINNED any other lexicon whose plugin declares `upstreamPin`
18
+ * (k8s, k3s, gcp, docker, gitlab, cedar, sql, ...) → checkPinnedUpgrade
19
+ * The pinned set is discovered from the plugin at run time, the way `chant dev
20
+ * pinned-upgrade` does. A pin that moves with other constants (`alsoMoves`, as
21
+ * sql's version plus digest) is report-only. helm / forgejo are excluded: no
22
+ * upstream spec.
19
23
  *
20
24
  * Finding-modes mirror ReconcileOp: `report` (default, no external services)
21
25
  * | `issue` | `pull-request`. For the epic goal, `pull-request` opens/updates a
@@ -43,9 +47,15 @@ import { Op, phase } from "../builders";
43
47
  import type { OpResource } from "../resource";
44
48
  import type { LexiconUpgradeMode, SupportedLexicon } from "../activities/lexicon-upgrade";
45
49
 
46
- /** The in-scope lexicons. helm / forgejo are excluded (no upstream spec). */
50
+ /**
51
+ * The lexicons known to be in scope. This is not a gate: a lexicon that declares
52
+ * `upstreamPin` is dispatched without being listed. helm / forgejo are excluded
53
+ * (no upstream spec).
54
+ */
47
55
  export const IN_SCOPE_LEXICONS: readonly SupportedLexicon[] = [
48
56
  "k8s",
57
+ "k3s",
58
+ "sql",
49
59
  "gcp",
50
60
  "docker",
51
61
  "gitlab",
@@ -74,6 +84,12 @@ export interface LexiconUpgradeOpConfig {
74
84
  * `<cwd>/lexicons/<lexicon>` at run time.
75
85
  */
76
86
  lexiconDir?: string;
87
+ /**
88
+ * Label of one pin to check, for a lexicon whose plugin declares several
89
+ * (`upstreamPins`; sql has `clickhouse` and `postgres-14` to `postgres-18`).
90
+ * Omit to check every pin.
91
+ */
92
+ pin?: string;
77
93
  /**
78
94
  * What to produce on findings. Default: "report".
79
95
  * @default "report"
@@ -86,15 +102,19 @@ export interface LexiconUpgradeOpResources {
86
102
  op: InstanceType<typeof OpResource>;
87
103
  }
88
104
 
105
+ const EXCLUDED_LEXICONS: ReadonlySet<string> = new Set(["helm", "forgejo"]);
106
+
89
107
  /**
90
- * Build a LexiconUpgradeOp for one lexicon. Rejects out-of-scope lexicons at
91
- * construction time so a typo never silently produces a no-op Op.
108
+ * Build a LexiconUpgradeOp for one lexicon. Rejects the lexicons with no
109
+ * upstream spec at construction time. Whether any other name declares a pin is
110
+ * only known by loading its plugin, so the activity checks that at run time and
111
+ * fails with a clear message for a name that has none.
92
112
  */
93
113
  export function LexiconUpgradeOp(config: LexiconUpgradeOpConfig): LexiconUpgradeOpResources {
94
- if (!IN_SCOPE_LEXICONS.includes(config.lexicon)) {
114
+ if (EXCLUDED_LEXICONS.has(config.lexicon)) {
95
115
  throw new Error(
96
116
  `LexiconUpgradeOp: "${config.lexicon}" is not in scope. ` +
97
- `In-scope lexicons: ${IN_SCOPE_LEXICONS.join(", ")} ` +
117
+ `Known lexicons: ${IN_SCOPE_LEXICONS.join(", ")}, and any lexicon declaring upstreamPin ` +
98
118
  `(helm, forgejo have no upstream spec).`,
99
119
  );
100
120
  }
@@ -119,6 +139,7 @@ export function LexiconUpgradeOp(config: LexiconUpgradeOpConfig): LexiconUpgrade
119
139
  args: {
120
140
  lexicon: config.lexicon,
121
141
  ...(config.lexiconDir ? { lexiconDir: config.lexiconDir } : {}),
142
+ ...(config.pin ? { pin: config.pin } : {}),
122
143
  mode: onFinding,
123
144
  },
124
145
  // Surface whether a PR-worthy upgrade was found as the run's
@@ -6,9 +6,13 @@
6
6
  * POST <url>/v1/systemone Authorization: Bearer <key>
7
7
  * { "model": "jev-1.13.0", "state": {...}, "questions": { "<name>": { "type": "noul" | "choice" | "score", "instructions": ..., "criteria": ... } } }
8
8
  *
9
- * { "model": "jev-1.13.0", "answers": { "<name>": { "type": "noul", "noul": 0.22 } | { "type": "choice", "choice": ..., "probabilities": {...}, "confidence": ... } | { "type": "score", ... } } }
9
+ * { "model": "jev-1.13.0", "answers": { "<name>": { "type": "noul", "noul": 0.22, "reason"?: ... } | { "type": "choice", "choice": ..., "probabilities": {...}, "confidence": ..., "reason"?: ... } | { "type": "score", ..., "reason"?: ... } } }
10
10
  * ```
11
11
  *
12
+ * `reason` is optional: the model's own explanation of its answer (#3345).
13
+ * Core keeps it in the answer record beside a proposal, or as `model_reason`
14
+ * in the escalation entry of an answer below the threshold.
15
+ *
12
16
  * {@link backendAsk} turns a set of backends into core's `ModelAsk`, the
13
17
  * model call `askPoint` takes (`../workspace/points.ts`). This file
14
18
  * only speaks the wire format: whether an answer is observed, proposed or
@@ -10,10 +10,12 @@
10
10
  *
11
11
  * Read by id or name here:
12
12
  *
13
- * record, decision, work-item a record, by id, from the declared record kinds (`records --json`)
13
+ * record, decision, work-item a record, by id, from the declared record kinds (`records --json`);
14
+ * a work item also has its size, `criteria`, `files`, `words` and
15
+ * `fits_<tier>`, for the slice-tier point (`../workspace/work-size.ts`, #3150)
14
16
  * member a member, by name (`ls --json`)
15
17
  *
16
- * The other outputs a point may name (finding, region, commit, gate, release,
18
+ * The other outputs a point may name (finding, region, commit, node, gate, release,
17
19
  * environment, component) are passed in `inputs`, as the output printed them.
18
20
  * These reads never call a model, and never write. The module loads code
19
21
  * under `workspace/`, so the `decide` activity imports it on first call.
@@ -22,6 +24,11 @@
22
24
  import { declaredKindFiles, queryDeclaredRecords } from "../workspace/records-cli";
23
25
  import { listWorkspace } from "../workspace/ls";
24
26
  import { inputOutput } from "../workspace/points";
27
+ import { readFileSync } from "node:fs";
28
+ import { join } from "node:path";
29
+ import { bodyText, loadRecordKind } from "../workspace/records";
30
+ import { locateWorkspace } from "../workspace/which-chant";
31
+ import { DEFAULT_TIER_LIMITS, measureWorkItem, sizeFields } from "../workspace/work-size";
25
32
 
26
33
  /** The outputs {@link readInputs} reads by id or name. */
27
34
  export const READABLE_OUTPUTS = ["record", "decision", "work-item", "member"] as const;
@@ -45,19 +52,40 @@ export function fieldOf(value: unknown, path: string): unknown {
45
52
  }
46
53
 
47
54
  async function readRecord(id: string, cwd: string, output: string): Promise<Record<string, unknown>> {
48
- const set = await queryDeclaredRecords(declaredKindFiles(cwd), { cwd });
55
+ const files = declaredKindFiles(cwd);
56
+ const set = await queryDeclaredRecords(files, { cwd });
49
57
  const unread: string[] = [];
50
- for (const doc of set.kinds) {
58
+ for (const [i, doc] of set.kinds.entries()) {
51
59
  if ("error" in doc) {
52
60
  unread.push(`${doc.declared.path}: ${doc.error.code}`);
53
61
  continue;
54
62
  }
55
63
  const found = doc.records.find((r) => r.id === id);
56
- if (found) return found as unknown as Record<string, unknown>;
64
+ if (found) {
65
+ const record = found as unknown as Record<string, unknown>;
66
+ // A work item's size, for the slice-tier point (#3150): criteria, files, words and fits_<tier>.
67
+ return output === "work-item" ? { ...record, ...(await workItemSizeFields(files[i].file, found.path, found.data, cwd)) } : record;
68
+ }
57
69
  }
58
70
  throw new InputReadError(`no declared record kind holds a record with id ${id} (read for ${output})${unread.length ? `; not read: ${unread.join(", ")}` : ""}`);
59
71
  }
60
72
 
73
+ /** The size fields of a work item of the kind at `kindFile`, measured from its record file. Empty for a kind with no work block. */
74
+ async function workItemSizeFields(kindFile: string, path: string, data: Record<string, unknown> | null, cwd: string): Promise<Record<string, unknown>> {
75
+ const loaded = await loadRecordKind(kindFile, cwd);
76
+ const work = loaded.kind.work;
77
+ if (!work) return {};
78
+ const located = locateWorkspace(cwd);
79
+ let body = "";
80
+ try {
81
+ body = bodyText(readFileSync(join(located.top ?? located.rootOnDisk, ...path.split("/")), "utf-8"));
82
+ } catch {
83
+ // A record that can't be read again is measured from its front matter alone.
84
+ }
85
+ const size = measureWorkItem(data, body, work.acceptance?.field ?? "acceptance");
86
+ return sizeFields(size, work.tier?.limits ?? DEFAULT_TIER_LIMITS);
87
+ }
88
+
61
89
  function readMember(name: string, cwd: string): Record<string, unknown> {
62
90
  const doc = listWorkspace({ cwd });
63
91
  if ("error" in doc) throw new InputReadError(`the workspace can't be listed: ${doc.error.code}: ${doc.error.message}`);
@@ -39,3 +39,26 @@ describe("emulatorLifecycle command builders", () => {
39
39
  expect(emu.endpoint(4599)).toBe("http://localhost:4599");
40
40
  });
41
41
  });
42
+
43
+ describe("an emulator reached by its own client, not over HTTP", () => {
44
+ const pg = emulatorLifecycle({
45
+ name: "chant-postgres",
46
+ image: "postgres:18",
47
+ containerPort: 5432,
48
+ readyCommand: ["pg_isready", "-h", "127.0.0.1"],
49
+ endpoint: (port) => `postgres://postgres@localhost:${port}/postgres`,
50
+ });
51
+
52
+ test("readiness is a command run in the container", () => {
53
+ expect(pg.readyExecCommand("chant-postgres")).toBe("docker exec chant-postgres pg_isready -h 127.0.0.1");
54
+ expect(emulatorLifecycle({ name: "x", image: "x:1", containerPort: 1, healthPath: "/h" }).readyExecCommand("x")).toBeUndefined();
55
+ });
56
+
57
+ test("the endpoint is the declared one, not an http URL", () => {
58
+ expect(pg.endpoint(55432)).toBe("postgres://postgres@localhost:55432/postgres");
59
+ });
60
+
61
+ test("a spec with neither a health path nor a ready command is refused", () => {
62
+ expect(() => emulatorLifecycle({ name: "x", image: "x:1", containerPort: 1 })).toThrow(/neither a healthPath nor a readyCommand/);
63
+ });
64
+ });
@@ -16,8 +16,25 @@ export interface EmulatorSpec {
16
16
  image: string;
17
17
  /** Port the emulator listens on inside the container (e.g. 4566, 4280). */
18
18
  containerPort: number;
19
- /** Health path on the host port (e.g. `/_localstack/health`, `/_mudflaps/health`). */
20
- healthPath: string;
19
+ /**
20
+ * Health path on the host port (e.g. `/_localstack/health`, `/_mudflaps/health`).
21
+ * Required unless {@link readyCommand} is set: an emulator is reached over
22
+ * HTTP or checks itself inside its container, one or the other.
23
+ */
24
+ healthPath?: string;
25
+ /**
26
+ * A command run inside the container (`docker exec <name> ...`) whose exit
27
+ * status 0 means ready, for an emulator with no HTTP health endpoint: a
28
+ * database server answers its own client (`pg_isready`), not a URL. When
29
+ * set, it replaces the HTTP poll of {@link healthPath}.
30
+ */
31
+ readyCommand?: readonly string[];
32
+ /**
33
+ * The endpoint a tool connects to, for an emulator that is not reached over
34
+ * HTTP, e.g. a `postgres://` URL for a database server.
35
+ * Default: `http://localhost:<port>`.
36
+ */
37
+ endpoint?: (port: number) => string;
21
38
  /** Readiness predicate over the health body. Default: any 200 response is ready. */
22
39
  ready?: (healthBody: string) => boolean;
23
40
  /** Extra `docker run` args inserted before the image (e.g. a socket mount). */
@@ -102,6 +119,8 @@ export interface EmulatorLifecycle {
102
119
  existsCommand(name: string): string;
103
120
  rmCommand(name: string): string;
104
121
  healthUrl(port: number): string;
122
+ /** `docker exec <name> <readyCommand...>`, or undefined for an emulator polled over HTTP. */
123
+ readyExecCommand(name: string): string | undefined;
105
124
  endpoint(port: number): string;
106
125
  up(args?: EmulatorUpArgs, signal?: AbortSignal): Promise<{ endpoint: string }>;
107
126
  down(args?: { name?: string }, signal?: AbortSignal): Promise<void>;
@@ -116,6 +135,9 @@ export interface EmulatorLifecycle {
116
135
  */
117
136
  export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
118
137
  const ready = spec.ready ?? (() => true);
138
+ if (spec.healthPath === undefined && !spec.readyCommand?.length) {
139
+ throw new Error(`emulator "${spec.name}" declares neither a healthPath nor a readyCommand, so nothing can tell when it is ready`);
140
+ }
119
141
 
120
142
  const runCommand = (args: EmulatorUpArgs = {}): string => {
121
143
  const name = args.name ?? spec.name;
@@ -128,8 +150,30 @@ export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
128
150
  };
129
151
  const existsCommand = (name: string): string => `docker ps -q -f name=${name}`;
130
152
  const rmCommand = (name: string): string => `docker rm -f ${name}`;
131
- const healthUrl = (port: number): string => `http://localhost:${port}${spec.healthPath}`;
132
- const endpoint = (port: number): string => `http://localhost:${port}`;
153
+ const healthUrl = (port: number): string => `http://localhost:${port}${spec.healthPath ?? ""}`;
154
+ const endpoint = (port: number): string => (spec.endpoint ? spec.endpoint(port) : `http://localhost:${port}`);
155
+ const readyExecCommand = (name: string): string | undefined =>
156
+ spec.readyCommand?.length ? ["docker", "exec", name, ...spec.readyCommand].join(" ") : undefined;
157
+
158
+ /** One readiness probe: the in-container command when declared, else the HTTP health path. */
159
+ async function probe(name: string, port: number, signal?: AbortSignal): Promise<boolean> {
160
+ const command = readyExecCommand(name);
161
+ if (command) {
162
+ try {
163
+ await execAsync(command, { signal });
164
+ return true;
165
+ } catch {
166
+ return false;
167
+ }
168
+ }
169
+ try {
170
+ const res = await fetch(healthUrl(port), { signal });
171
+ return res.ok && ready(await res.text());
172
+ } catch {
173
+ // Not up yet (connection refused / non-2xx) — retry.
174
+ return false;
175
+ }
176
+ }
133
177
 
134
178
  async function up(args: EmulatorUpArgs = {}, signal?: AbortSignal): Promise<{ endpoint: string }> {
135
179
  const name = args.name ?? spec.name;
@@ -153,19 +197,13 @@ export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
153
197
  await execAsync(runCommand({ ...args, name, port }), { signal });
154
198
  }
155
199
 
156
- const url = healthUrl(port);
157
200
  const deadline = Date.now() + timeoutMs;
158
201
  let ok = false;
159
202
  while (Date.now() < deadline) {
160
203
  if (signal?.aborted) throw new Error(`emulator "${name}" wait aborted`);
161
- try {
162
- const res = await fetch(url, { signal });
163
- if (res.ok && ready(await res.text())) {
164
- ok = true;
165
- break;
166
- }
167
- } catch {
168
- // Not up yet (connection refused / non-2xx) — retry.
204
+ if (await probe(name, port, signal)) {
205
+ ok = true;
206
+ break;
169
207
  }
170
208
  await sleep(intervalMs, signal);
171
209
  }
@@ -187,5 +225,5 @@ export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
187
225
  }
188
226
  }
189
227
 
190
- return { runCommand, existsCommand, rmCommand, healthUrl, endpoint, up, down };
228
+ return { runCommand, existsCommand, rmCommand, healthUrl, readyExecCommand, endpoint, up, down };
191
229
  }