@intentius/chant 0.124.13 → 0.124.14

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 (907) hide show
  1. package/bin/chant +11 -0
  2. package/dist/agents/checks.js +326 -0
  3. package/dist/agents/discover.js +885 -0
  4. package/dist/agents/importer.js +17 -0
  5. package/dist/agents/index.js +12 -0
  6. package/dist/agents/types.js +19 -0
  7. package/dist/apply.js +151 -0
  8. package/dist/attrref.js +70 -0
  9. package/dist/audit/catalog.js +350 -0
  10. package/dist/audit/core.js +252 -0
  11. package/dist/audit/discover.js +633 -0
  12. package/dist/audit/fetch.js +666 -0
  13. package/dist/audit/lineage.js +91 -0
  14. package/dist/audit/nginx.js +366 -0
  15. package/dist/audit/prior-art.js +132 -0
  16. package/dist/audit/proof.js +321 -0
  17. package/dist/audit/report-html.js +194 -0
  18. package/dist/audit/report-model.js +198 -0
  19. package/dist/audit/report.js +102 -0
  20. package/dist/audit/rules-doc.js +144 -0
  21. package/dist/audit/secrets.js +405 -0
  22. package/dist/audit/terraform-state.js +140 -0
  23. package/dist/audit/wrangler.js +262 -0
  24. package/dist/behaviour-delta.js +401 -0
  25. package/dist/behaviour-engine.js +357 -0
  26. package/dist/behaviour-graph.js +83 -0
  27. package/dist/behaviour-http.js +188 -0
  28. package/dist/behaviour-kinds.js +172 -0
  29. package/dist/behaviour-overlay.js +50 -0
  30. package/dist/behaviour-predict.js +188 -0
  31. package/dist/behaviour-request.js +194 -0
  32. package/dist/behaviour.js +1325 -0
  33. package/dist/build-params.js +108 -0
  34. package/dist/build.js +668 -0
  35. package/dist/builder.js +44 -0
  36. package/dist/cdk/advise.js +30 -0
  37. package/dist/cdk/assembly.js +122 -0
  38. package/dist/cdk/graph.js +444 -0
  39. package/dist/cdk/tier-map.js +64 -0
  40. package/dist/cdk/types.js +24 -0
  41. package/dist/change-set.js +312 -0
  42. package/dist/child-project.js +21 -0
  43. package/dist/claimed-fields.js +135 -0
  44. package/dist/cli/build-options.js +70 -0
  45. package/dist/cli/build-params-cli.js +139 -0
  46. package/dist/cli/command-group.js +123 -0
  47. package/dist/cli/commands/audit-agents.js +326 -0
  48. package/dist/cli/commands/audit.js +571 -0
  49. package/dist/cli/commands/build.js +920 -0
  50. package/dist/cli/commands/carve-apply.js +153 -0
  51. package/dist/cli/commands/carve-bridge.js +201 -0
  52. package/dist/cli/commands/carve-emit.js +332 -0
  53. package/dist/cli/commands/carve-status.js +119 -0
  54. package/dist/cli/commands/carve.js +204 -0
  55. package/dist/cli/commands/check-lexicon-docs.js +79 -0
  56. package/dist/cli/commands/check-lexicon-examples.js +177 -0
  57. package/dist/cli/commands/check-lexicon-intrinsics.js +291 -0
  58. package/dist/cli/commands/check-lexicon-mcp.js +82 -0
  59. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  60. package/dist/cli/commands/check-lexicon-plugin.js +104 -0
  61. package/dist/cli/commands/check-lexicon.js +766 -0
  62. package/dist/cli/commands/describe.js +85 -0
  63. package/dist/cli/commands/diff.js +175 -0
  64. package/dist/cli/commands/doctor.js +350 -0
  65. package/dist/cli/commands/import-agents.js +155 -0
  66. package/dist/cli/commands/import.js +670 -0
  67. package/dist/cli/commands/init-lexicon/templates/codegen.js +194 -0
  68. package/dist/cli/commands/init-lexicon/templates/docs.js +100 -0
  69. package/dist/cli/commands/init-lexicon/templates/examples.js +29 -0
  70. package/dist/cli/commands/init-lexicon/templates/lint.js +34 -0
  71. package/dist/cli/commands/init-lexicon/templates/lsp.js +37 -0
  72. package/dist/cli/commands/init-lexicon/templates/plugin.js +108 -0
  73. package/dist/cli/commands/init-lexicon/templates/project.js +240 -0
  74. package/dist/cli/commands/init-lexicon/templates/spec.js +56 -0
  75. package/dist/cli/commands/init-lexicon/templates/tests.js +66 -0
  76. package/dist/cli/commands/init-lexicon.js +172 -0
  77. package/dist/cli/commands/init.js +381 -0
  78. package/dist/cli/commands/lexicon-rolling-upgrade.js +145 -0
  79. package/dist/cli/commands/lexicon-surface-diff.js +145 -0
  80. package/dist/cli/commands/licenses.js +125 -0
  81. package/dist/cli/commands/lint.d.ts.map +1 -1
  82. package/dist/cli/commands/lint.js +948 -0
  83. package/dist/cli/commands/list.js +63 -0
  84. package/dist/cli/commands/migrate.d.ts.map +1 -1
  85. package/dist/cli/commands/migrate.js +423 -0
  86. package/dist/cli/commands/onboard.js +403 -0
  87. package/dist/cli/commands/pinned-upgrade.js +191 -0
  88. package/dist/cli/commands/update.js +194 -0
  89. package/dist/cli/commands/vendor.js +217 -0
  90. package/dist/cli/conflict-check.js +104 -0
  91. package/dist/cli/debug.js +8 -0
  92. package/dist/cli/format.js +104 -0
  93. package/dist/cli/handlers/build.js +267 -0
  94. package/dist/cli/handlers/carve-apply.js +30 -0
  95. package/dist/cli/handlers/carve-bridge.js +28 -0
  96. package/dist/cli/handlers/carve-emit.js +50 -0
  97. package/dist/cli/handlers/carve-status.js +26 -0
  98. package/dist/cli/handlers/carve.js +40 -0
  99. package/dist/cli/handlers/change-set.js +46 -0
  100. package/dist/cli/handlers/components.js +730 -0
  101. package/dist/cli/handlers/dev.js +113 -0
  102. package/dist/cli/handlers/emulator.js +233 -0
  103. package/dist/cli/handlers/explain.js +54 -0
  104. package/dist/cli/handlers/fan-out.js +422 -0
  105. package/dist/cli/handlers/gate-resume.js +275 -0
  106. package/dist/cli/handlers/generate.js +84 -0
  107. package/dist/cli/handlers/graph.js +969 -0
  108. package/dist/cli/handlers/init.js +102 -0
  109. package/dist/cli/handlers/lifecycle.js +1727 -0
  110. package/dist/cli/handlers/lint.js +62 -0
  111. package/dist/cli/handlers/migrate.js +48 -0
  112. package/dist/cli/handlers/misc.js +391 -0
  113. package/dist/cli/handlers/operator.js +1162 -0
  114. package/dist/cli/handlers/override-approve.js +102 -0
  115. package/dist/cli/handlers/pr.js +503 -0
  116. package/dist/cli/handlers/promote.js +342 -0
  117. package/dist/cli/handlers/run-generate.js +206 -0
  118. package/dist/cli/handlers/run-wave.js +66 -0
  119. package/dist/cli/handlers/run.js +1191 -0
  120. package/dist/cli/handlers/scenario.js +325 -0
  121. package/dist/cli/handlers/search.js +924 -0
  122. package/dist/cli/handlers/serve.js +32 -0
  123. package/dist/cli/handlers/vendor.js +154 -0
  124. package/dist/cli/index.js +3 -0
  125. package/dist/cli/is-entry-point.js +23 -0
  126. package/dist/cli/lsp/capabilities.js +28 -0
  127. package/dist/cli/lsp/diagnostics.js +34 -0
  128. package/dist/cli/lsp/server.js +329 -0
  129. package/dist/cli/main.d.ts.map +1 -1
  130. package/dist/cli/main.js +2540 -0
  131. package/dist/cli/mcp/lifecycle-tools.js +80 -0
  132. package/dist/cli/mcp/op-tools.js +306 -0
  133. package/dist/cli/mcp/resource-handlers.js +258 -0
  134. package/dist/cli/mcp/resources/context.js +85 -0
  135. package/dist/cli/mcp/server.js +353 -0
  136. package/dist/cli/mcp/tools/build.js +111 -0
  137. package/dist/cli/mcp/tools/composites.js +95 -0
  138. package/dist/cli/mcp/tools/explain.js +166 -0
  139. package/dist/cli/mcp/tools/import.js +49 -0
  140. package/dist/cli/mcp/tools/lint.js +41 -0
  141. package/dist/cli/mcp/tools/scaffold.js +111 -0
  142. package/dist/cli/mcp/tools/search.js +112 -0
  143. package/dist/cli/mcp/types.js +1 -0
  144. package/dist/cli/mcp/workspace-plugins.js +91 -0
  145. package/dist/cli/mcp/workspace-tools.d.ts +1 -1
  146. package/dist/cli/mcp/workspace-tools.js +564 -0
  147. package/dist/cli/mcp-config.js +70 -0
  148. package/dist/cli/plugins.js +313 -0
  149. package/dist/cli/registry.js +23 -0
  150. package/dist/cli/reporters/stylish.js +329 -0
  151. package/dist/cli/version.js +15 -0
  152. package/dist/cli/watch.js +79 -0
  153. package/dist/codegen/bound-property-types.js +82 -0
  154. package/dist/codegen/coverage.js +119 -0
  155. package/dist/codegen/docs-file-markers.js +60 -0
  156. package/dist/codegen/docs-pages.js +115 -0
  157. package/dist/codegen/docs-rule-scanning.js +164 -0
  158. package/dist/codegen/docs-rules.js +76 -0
  159. package/dist/codegen/docs-sections.js +117 -0
  160. package/dist/codegen/docs-sidebar.js +65 -0
  161. package/dist/codegen/docs-types.js +4 -0
  162. package/dist/codegen/docs.js +356 -0
  163. package/dist/codegen/fetch.js +340 -0
  164. package/dist/codegen/generate-post-synth-barrel.js +63 -0
  165. package/dist/codegen/generate-registry.js +71 -0
  166. package/dist/codegen/generate-runtime-index.js +56 -0
  167. package/dist/codegen/generate-typescript.js +119 -0
  168. package/dist/codegen/generate.js +115 -0
  169. package/dist/codegen/json-patch.js +141 -0
  170. package/dist/codegen/json-schema-to-ts.js +344 -0
  171. package/dist/codegen/json-schema.js +246 -0
  172. package/dist/codegen/lexicon-regen.js +412 -0
  173. package/dist/codegen/naming.js +217 -0
  174. package/dist/codegen/okf-lexicon.js +245 -0
  175. package/dist/codegen/package.js +150 -0
  176. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  177. package/dist/codegen/pinned-upgrade.js +494 -0
  178. package/dist/codegen/registry.js +60 -0
  179. package/dist/codegen/rehype-base-url.mjs +68 -0
  180. package/dist/codegen/rolling-upgrade.js +217 -0
  181. package/dist/codegen/surface-snapshot.js +537 -0
  182. package/dist/codegen/testdata/postgres-tags.json +242 -0
  183. package/dist/codegen/topo-sort.js +36 -0
  184. package/dist/codegen/typecheck.js +115 -0
  185. package/dist/codegen/validate.js +200 -0
  186. package/dist/codegen/version-bump.js +35 -0
  187. package/dist/components/auto-release.js +143 -0
  188. package/dist/components/builders.js +47 -0
  189. package/dist/components/capability-plugin-loader.js +175 -0
  190. package/dist/components/capability-plugin-schema.js +46 -0
  191. package/dist/components/capability-plugin.js +99 -0
  192. package/dist/components/capability.js +60 -0
  193. package/dist/components/changed-files.js +72 -0
  194. package/dist/components/cli-support.js +427 -0
  195. package/dist/components/component.js +120 -0
  196. package/dist/components/component.schema.json +271 -0
  197. package/dist/components/config-defaults.js +130 -0
  198. package/dist/components/deploy-units.js +60 -0
  199. package/dist/components/discover.d.ts.map +1 -1
  200. package/dist/components/discover.js +189 -0
  201. package/dist/components/driver-output.js +86 -0
  202. package/dist/components/driver.js +728 -0
  203. package/dist/components/fan-out-output.js +165 -0
  204. package/dist/components/fan-out-record.js +94 -0
  205. package/dist/components/fan-out-run.js +373 -0
  206. package/dist/components/fan-out-support.js +60 -0
  207. package/dist/components/fan-out.js +273 -0
  208. package/dist/components/gate-plan.js +41 -0
  209. package/dist/components/gated-wave-pipeline.js +46 -0
  210. package/dist/components/index.js +24 -0
  211. package/dist/components/layers.js +28 -0
  212. package/dist/components/manifest-persistence.js +108 -0
  213. package/dist/components/pilots/alb-ecs.pilot.js +59 -0
  214. package/dist/components/pilots/dynamodb.pilot.js +51 -0
  215. package/dist/components/pilots/jar-emr.pilot.js +65 -0
  216. package/dist/components/pilots/lambda.pilot.js +52 -0
  217. package/dist/components/pilots/neo4j-fanout.pilot.js +68 -0
  218. package/dist/components/pilots/project.js +12 -0
  219. package/dist/components/pr-pipeline.js +134 -0
  220. package/dist/components/pr-run.js +363 -0
  221. package/dist/components/presets/ecs-fargate.js +72 -0
  222. package/dist/components/presets/index.js +28 -0
  223. package/dist/components/presets/lambda.js +34 -0
  224. package/dist/components/presets/single-host-compose.js +41 -0
  225. package/dist/components/promote.js +549 -0
  226. package/dist/components/registry.js +34 -0
  227. package/dist/components/run-progress.js +33 -0
  228. package/dist/components/sandbox/driver.d.ts.map +1 -1
  229. package/dist/components/sandbox/driver.js +93 -0
  230. package/dist/components/sandbox/run.js +115 -0
  231. package/dist/components/starter-plugin.js +104 -0
  232. package/dist/components/verbs/__tests__/mock-cloud-executor.js +68 -0
  233. package/dist/components/verbs/__tests__/mock-process-runner.js +45 -0
  234. package/dist/components/verbs/__tests__/mock-sbom-generator.js +56 -0
  235. package/dist/components/verbs/bom-writer.js +287 -0
  236. package/dist/components/verbs/build-archive.js +188 -0
  237. package/dist/components/verbs/build.js +142 -0
  238. package/dist/components/verbs/cloud-executor.js +110 -0
  239. package/dist/components/verbs/component-bom.js +125 -0
  240. package/dist/components/verbs/ensure-secret.js +50 -0
  241. package/dist/components/verbs/index.js +61 -0
  242. package/dist/components/verbs/license-policy.js +75 -0
  243. package/dist/components/verbs/lockfile-sbom-generator.js +191 -0
  244. package/dist/components/verbs/process-runner.js +78 -0
  245. package/dist/components/verbs/r2-sync.js +93 -0
  246. package/dist/components/verbs/reproducibility.js +62 -0
  247. package/dist/components/verbs/run-agent.js +577 -0
  248. package/dist/components/verbs/sbom-generator.js +119 -0
  249. package/dist/components/verbs/sbom.js +97 -0
  250. package/dist/components/verbs/shell.js +32 -0
  251. package/dist/components/verbs/sign.js +221 -0
  252. package/dist/components/verbs/stub.js +28 -0
  253. package/dist/components/verbs/tool-sbom-generator.js +154 -0
  254. package/dist/components/verbs/verify.js +112 -0
  255. package/dist/components/verbs/vex.js +131 -0
  256. package/dist/components/verbs/vuln-gate.js +152 -0
  257. package/dist/components/verbs/vuln-scan.js +288 -0
  258. package/dist/components/verbs/wait-verify.js +106 -0
  259. package/dist/components/verbs/wrangler.js +179 -0
  260. package/dist/components/wave-plan.js +102 -0
  261. package/dist/composite.js +305 -0
  262. package/dist/config-import.d.ts.map +1 -1
  263. package/dist/config-import.js +22 -0
  264. package/dist/config-sandbox.js +122 -0
  265. package/dist/config-static.js +206 -0
  266. package/dist/config.js +605 -0
  267. package/dist/content-digest.js +23 -0
  268. package/dist/declarable.js +114 -0
  269. package/dist/deep-observation.js +437 -0
  270. package/dist/detectLexicon.js +54 -0
  271. package/dist/discovery/cache.js +70 -0
  272. package/dist/discovery/collect.js +208 -0
  273. package/dist/discovery/cycles.js +95 -0
  274. package/dist/discovery/entity-wire-codec.js +391 -0
  275. package/dist/discovery/entity-wire.js +42 -0
  276. package/dist/discovery/files.js +121 -0
  277. package/dist/discovery/fold-import.d.ts.map +1 -1
  278. package/dist/discovery/fold-import.js +4178 -0
  279. package/dist/discovery/fold-rank.js +292 -0
  280. package/dist/discovery/graph.js +115 -0
  281. package/dist/discovery/import.d.ts.map +1 -1
  282. package/dist/discovery/import.js +65 -0
  283. package/dist/discovery/index.js +333 -0
  284. package/dist/discovery/param-deps.js +487 -0
  285. package/dist/discovery/resolve.js +39 -0
  286. package/dist/discovery/sandbox/bundle.js +214 -0
  287. package/dist/discovery/sandbox/child-errors.js +26 -0
  288. package/dist/discovery/sandbox/config-run.js +100 -0
  289. package/dist/discovery/sandbox/config-wire.js +183 -0
  290. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  291. package/dist/discovery/sandbox/driver.js +333 -0
  292. package/dist/discovery/sandbox/fork.js +229 -0
  293. package/dist/discovery/sandbox/policy-run.js +142 -0
  294. package/dist/discovery/sandbox/policy-wire.js +152 -0
  295. package/dist/discovery/sandbox/run.js +77 -0
  296. package/dist/discovery/specifier-resolve.js +320 -0
  297. package/dist/discovery/walk.js +284 -0
  298. package/dist/effect-receipt.js +340 -0
  299. package/dist/env.js +55 -0
  300. package/dist/errors.js +62 -0
  301. package/dist/fold/fold.js +1434 -0
  302. package/dist/fold/foldable-helpers.js +229 -0
  303. package/dist/fold/subset.js +696 -0
  304. package/dist/fold-provenance.js +414 -0
  305. package/dist/gate-decision.js +260 -0
  306. package/dist/gate-resume-run.js +154 -0
  307. package/dist/gated-waves.js +165 -0
  308. package/dist/governance.js +43 -0
  309. package/dist/graph-declared.js +45 -0
  310. package/dist/graph-detail.js +207 -0
  311. package/dist/graph-dot.js +54 -0
  312. package/dist/graph-effective.js +107 -0
  313. package/dist/graph-ir.js +623 -0
  314. package/dist/graph-layout.js +184 -0
  315. package/dist/graph-lens.js +105 -0
  316. package/dist/graph-mermaid.js +83 -0
  317. package/dist/graph-ops.js +39 -0
  318. package/dist/graph-refs.js +156 -0
  319. package/dist/held-elsewhere.js +87 -0
  320. package/dist/identity.js +251 -0
  321. package/dist/import/base-parser.js +34 -0
  322. package/dist/import/embedded.js +255 -0
  323. package/dist/import/generator.js +1 -0
  324. package/dist/import/ir-utils.js +85 -0
  325. package/dist/import/parser-options.js +45 -0
  326. package/dist/import/parser.js +1 -0
  327. package/dist/index.js +118 -0
  328. package/dist/intrinsic-interpolation.js +73 -0
  329. package/dist/intrinsic.js +31 -0
  330. package/dist/join-key.js +35 -0
  331. package/dist/kubectl-context.js +150 -0
  332. package/dist/lexicon-config.js +58 -0
  333. package/dist/lexicon-integrity.js +47 -0
  334. package/dist/lexicon-manifest.js +70 -0
  335. package/dist/lexicon-module.d.ts.map +1 -1
  336. package/dist/lexicon-module.js +241 -0
  337. package/dist/lexicon-output.js +218 -0
  338. package/dist/lexicon-plugin-helpers.js +104 -0
  339. package/dist/lexicon-schema.js +136 -0
  340. package/dist/lexicon.js +130 -0
  341. package/dist/lifecycle/affected.js +224 -0
  342. package/dist/lifecycle/assert-live.js +110 -0
  343. package/dist/lifecycle/build-ledger-store.js +160 -0
  344. package/dist/lifecycle/build-ledger.js +155 -0
  345. package/dist/lifecycle/change-set.js +356 -0
  346. package/dist/lifecycle/converge-ledger.js +161 -0
  347. package/dist/lifecycle/deep-diff.js +233 -0
  348. package/dist/lifecycle/deep-observe.js +147 -0
  349. package/dist/lifecycle/digest.js +143 -0
  350. package/dist/lifecycle/disruption.js +135 -0
  351. package/dist/lifecycle/gate-applied.js +113 -0
  352. package/dist/lifecycle/gate-audit.js +341 -0
  353. package/dist/lifecycle/gate-ledger-select.js +89 -0
  354. package/dist/lifecycle/gate-ledger.js +193 -0
  355. package/dist/lifecycle/gate-origin.js +117 -0
  356. package/dist/lifecycle/gate-pending.js +58 -0
  357. package/dist/lifecycle/git.js +1182 -0
  358. package/dist/lifecycle/identity.js +58 -0
  359. package/dist/lifecycle/index.js +26 -0
  360. package/dist/lifecycle/lease.js +283 -0
  361. package/dist/lifecycle/ledger-port.js +1 -0
  362. package/dist/lifecycle/legacy-digest.js +91 -0
  363. package/dist/lifecycle/live-diff.js +274 -0
  364. package/dist/lifecycle/local-note.js +15 -0
  365. package/dist/lifecycle/member-ledger.js +122 -0
  366. package/dist/lifecycle/observation-baseline.js +155 -0
  367. package/dist/lifecycle/observe.js +375 -0
  368. package/dist/lifecycle/oras-referrer-lookup.js +82 -0
  369. package/dist/lifecycle/override-ledger.js +54 -0
  370. package/dist/lifecycle/plan-digest.js +110 -0
  371. package/dist/lifecycle/plan-ledger.js +129 -0
  372. package/dist/lifecycle/receipt-plan.js +192 -0
  373. package/dist/lifecycle/release-ledger.js +155 -0
  374. package/dist/lifecycle/release-read.js +64 -0
  375. package/dist/lifecycle/replay.js +193 -0
  376. package/dist/lifecycle/rollback.js +102 -0
  377. package/dist/lifecycle/run-ledger.js +183 -0
  378. package/dist/lifecycle/scenario-eval.js +204 -0
  379. package/dist/lifecycle/scenario.js +214 -0
  380. package/dist/lifecycle/snapshot.js +239 -0
  381. package/dist/lifecycle/status.js +447 -0
  382. package/dist/lifecycle/symptoms.js +117 -0
  383. package/dist/lifecycle/teardown.js +255 -0
  384. package/dist/lifecycle/types.js +1 -0
  385. package/dist/lifecycle/unobserved-gate.js +33 -0
  386. package/dist/lifecycle/wave-plans.js +68 -0
  387. package/dist/lifecycle/work-item-id.js +36 -0
  388. package/dist/lifecycle/work-lease.js +393 -0
  389. package/dist/lint/component-checks.js +87 -0
  390. package/dist/lint/config.js +483 -0
  391. package/dist/lint/declarative.js +122 -0
  392. package/dist/lint/discover.d.ts.map +1 -1
  393. package/dist/lint/discover.js +138 -0
  394. package/dist/lint/engine.js +246 -0
  395. package/dist/lint/knowledge-checks.js +64 -0
  396. package/dist/lint/named-checks.js +22 -0
  397. package/dist/lint/output-checks.js +87 -0
  398. package/dist/lint/output-docs.js +163 -0
  399. package/dist/lint/parser.js +33 -0
  400. package/dist/lint/pipeline-change-gate.js +70 -0
  401. package/dist/lint/policy-import.d.ts +1 -1
  402. package/dist/lint/policy-import.d.ts.map +1 -1
  403. package/dist/lint/policy-import.js +62 -0
  404. package/dist/lint/policy-sandbox.js +86 -0
  405. package/dist/lint/policy.js +122 -0
  406. package/dist/lint/post-synth.js +87 -0
  407. package/dist/lint/presets/relaxed.json +26 -0
  408. package/dist/lint/presets/strict.json +24 -24
  409. package/dist/lint/receipt-checks.js +83 -0
  410. package/dist/lint/rule-loader.d.ts.map +1 -1
  411. package/dist/lint/rule-loader.js +89 -0
  412. package/dist/lint/rule-registry.js +86 -0
  413. package/dist/lint/rule.js +1 -0
  414. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.js +7 -0
  415. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.js +7 -0
  416. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.js +9 -0
  417. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.js +11 -0
  418. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.js +9 -0
  419. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.js +25 -0
  420. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.js +8 -0
  421. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.js +21 -0
  422. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.js +8 -0
  423. package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.js +24 -0
  424. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.js +17 -0
  425. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.js +8 -0
  426. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.js +18 -0
  427. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.js +20 -0
  428. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.js +8 -0
  429. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.js +12 -0
  430. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.js +16 -0
  431. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.js +8 -0
  432. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.js +12 -0
  433. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.js +11 -0
  434. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.js +11 -0
  435. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.js +10 -0
  436. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.js +16 -0
  437. package/dist/lint/rules/comp/comp001-publishes-never-applies.js +69 -0
  438. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.js +84 -0
  439. package/dist/lint/rules/comp/comp003-mutating-no-rollback.js +103 -0
  440. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.js +70 -0
  441. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.js +109 -0
  442. package/dist/lint/rules/comp/comp006-shell-needs-reason.js +49 -0
  443. package/dist/lint/rules/comp/comp007-composition-sprawl.js +64 -0
  444. package/dist/lint/rules/comp/index.js +33 -0
  445. package/dist/lint/rules/comp/support.js +129 -0
  446. package/dist/lint/rules/composite-scope.js +51 -0
  447. package/dist/lint/rules/cor017-composite-name-match.js +93 -0
  448. package/dist/lint/rules/cor018-composite-prefer-lexicon-type.js +136 -0
  449. package/dist/lint/rules/cor021-env-literal-name.js +100 -0
  450. package/dist/lint/rules/cor022-receipt-leaf.js +118 -0
  451. package/dist/lint/rules/cor024-receipt-secret-pointer.js +199 -0
  452. package/dist/lint/rules/declarable-naming-convention.js +62 -0
  453. package/dist/lint/rules/evl001-non-literal-expression.js +66 -0
  454. package/dist/lint/rules/evl002-control-flow-resource.js +69 -0
  455. package/dist/lint/rules/evl003-dynamic-property-access.js +44 -0
  456. package/dist/lint/rules/evl004-spread-non-const.js +94 -0
  457. package/dist/lint/rules/evl005-resource-block-body.js +41 -0
  458. package/dist/lint/rules/evl007-invalid-siblings.js +105 -0
  459. package/dist/lint/rules/evl009-composite-no-constant.js +158 -0
  460. package/dist/lint/rules/evl010-composite-no-transform.js +59 -0
  461. package/dist/lint/rules/evl011-symbolic-in-template.js +106 -0
  462. package/dist/lint/rules/export-required.js +115 -0
  463. package/dist/lint/rules/file-declarable-limit.js +88 -0
  464. package/dist/lint/rules/flat-declarations.js +62 -0
  465. package/dist/lint/rules/index.js +90 -0
  466. package/dist/lint/rules/no-cyclic-declarable-ref.js +138 -0
  467. package/dist/lint/rules/no-redundant-type-import.js +76 -0
  468. package/dist/lint/rules/no-redundant-value-cast.js +41 -0
  469. package/dist/lint/rules/no-string-ref.js +59 -0
  470. package/dist/lint/rules/no-unused-declarable-import.js +75 -0
  471. package/dist/lint/rules/no-unused-declarable.js +142 -0
  472. package/dist/lint/rules/op/index.js +28 -0
  473. package/dist/lint/rules/op/ops012-activity-contract.js +54 -0
  474. package/dist/lint/rules/op/ops013-step-output-ref.js +88 -0
  475. package/dist/lint/rules/op/ops014-converge-rule-refusals.js +114 -0
  476. package/dist/lint/rules/op/ops015-gate-approval.js +45 -0
  477. package/dist/lint/rules/op/support.js +11 -0
  478. package/dist/lint/rules/op/sys010-key-over-plain-http.js +100 -0
  479. package/dist/lint/rules/property-kind.js +56 -0
  480. package/dist/lint/rules/single-concern-file.js +71 -0
  481. package/dist/lint/rules/sys001-no-literal-key.js +60 -0
  482. package/dist/lint/selectors.js +168 -0
  483. package/dist/lint/suppressions.js +129 -0
  484. package/dist/lint/typescript.js +17 -0
  485. package/dist/live-endpoint.js +113 -0
  486. package/dist/live-read-session.js +76 -0
  487. package/dist/lsp/lexicon-providers.js +163 -0
  488. package/dist/lsp/types.js +5 -0
  489. package/dist/managed-fields.js +293 -0
  490. package/dist/mcp/types.js +4 -0
  491. package/dist/notify-verify.js +0 -1
  492. package/dist/notify.js +0 -1
  493. package/dist/notify.schema.json +72 -0
  494. package/dist/observation.js +266 -0
  495. package/dist/okf-read.js +134 -0
  496. package/dist/okf.js +275 -0
  497. package/dist/op/__fixtures__/decide-stub-backend.js +125 -0
  498. package/dist/op/activities/activity-contracts.js +313 -0
  499. package/dist/op/activities/apply.js +582 -0
  500. package/dist/op/activities/build.js +18 -0
  501. package/dist/op/activities/change-coverage.js +40 -0
  502. package/dist/op/activities/change-set.js +64 -0
  503. package/dist/op/activities/converge.js +492 -0
  504. package/dist/op/activities/decide.js +211 -0
  505. package/dist/op/activities/env-teardown.js +110 -0
  506. package/dist/op/activities/factory.js +591 -0
  507. package/dist/op/activities/forge-pull-request.js +82 -0
  508. package/dist/op/activities/gh-host.js +78 -0
  509. package/dist/op/activities/guard-validate.js +165 -0
  510. package/dist/op/activities/http-check.js +40 -0
  511. package/dist/op/activities/index.js +59 -0
  512. package/dist/op/activities/lexicon-upgrade.js +629 -0
  513. package/dist/op/activities/lifecycle.js +109 -0
  514. package/dist/op/activities/pipeline-audit.js +147 -0
  515. package/dist/op/activities/policy.js +26 -0
  516. package/dist/op/activities/predict-behaviour.js +341 -0
  517. package/dist/op/activities/propose-upgrade.js +165 -0
  518. package/dist/op/activities/reconcile.js +997 -0
  519. package/dist/op/activities/shell.js +118 -0
  520. package/dist/op/activities/source-release.js +97 -0
  521. package/dist/op/activities/source-rollback.js +165 -0
  522. package/dist/op/activities/teardown.js +17 -0
  523. package/dist/op/activities/util.js +6 -0
  524. package/dist/op/activities/wait.js +51 -0
  525. package/dist/op/activities/work-evidence.js +35 -0
  526. package/dist/op/activities/workflow-audit.js +133 -0
  527. package/dist/op/activity-contract-registry.js +106 -0
  528. package/dist/op/activity-contract.js +232 -0
  529. package/dist/op/activity-failure.js +31 -0
  530. package/dist/op/activity-profiles.js +129 -0
  531. package/dist/op/activity-registry.js +105 -0
  532. package/dist/op/activity-runtime.js +28 -0
  533. package/dist/op/builders.js +801 -0
  534. package/dist/op/change-signal.js +118 -0
  535. package/dist/op/composites/apply-op.js +151 -0
  536. package/dist/op/composites/behaviour-op.js +65 -0
  537. package/dist/op/composites/converge-op.js +141 -0
  538. package/dist/op/composites/index.js +19 -0
  539. package/dist/op/composites/lexicon-upgrade-op.js +107 -0
  540. package/dist/op/composites/pipeline-audit-op.js +50 -0
  541. package/dist/op/composites/reconcile-op.js +84 -0
  542. package/dist/op/composites/watch-op.js +69 -0
  543. package/dist/op/composites/workflow-audit-op.js +57 -0
  544. package/dist/op/converge-rule.js +205 -0
  545. package/dist/op/cron.js +146 -0
  546. package/dist/op/decide-backend.js +181 -0
  547. package/dist/op/decide-config.js +68 -0
  548. package/dist/op/decide-read-inputs.js +141 -0
  549. package/dist/op/discover.d.ts.map +1 -1
  550. package/dist/op/discover.js +213 -0
  551. package/dist/op/duration.js +21 -0
  552. package/dist/op/emulator-freshness.js +80 -0
  553. package/dist/op/emulator-lifecycle.js +269 -0
  554. package/dist/op/factory.js +83 -0
  555. package/dist/op/gate-approval.js +172 -0
  556. package/dist/op/gate-name.js +86 -0
  557. package/dist/op/gate-plan-context.js +167 -0
  558. package/dist/op/gate-point-run.js +67 -0
  559. package/dist/op/gate-point.js +111 -0
  560. package/dist/op/gate-resume-plan.js +155 -0
  561. package/dist/op/gate-resume.js +31 -0
  562. package/dist/op/gate-review.js +290 -0
  563. package/dist/op/gate-run-locator.js +85 -0
  564. package/dist/op/gate-summary.js +100 -0
  565. package/dist/op/gate-wait.js +56 -0
  566. package/dist/op/gate.js +449 -0
  567. package/dist/op/generate-pipeline.js +124 -0
  568. package/dist/op/index.js +51 -0
  569. package/dist/op/lifecycle-receipt-store.js +45 -0
  570. package/dist/op/local-executor.js +1164 -0
  571. package/dist/op/local-output.js +140 -0
  572. package/dist/op/op-ir.js +317 -0
  573. package/dist/op/op-verb-class.js +131 -0
  574. package/dist/op/op-waves-notify.js +136 -0
  575. package/dist/op/op-waves-run.js +1657 -0
  576. package/dist/op/op-waves.js +409 -0
  577. package/dist/op/operator.js +743 -0
  578. package/dist/op/receipt-store.js +94 -0
  579. package/dist/op/resource.js +23 -0
  580. package/dist/op/run-context.js +28 -0
  581. package/dist/op/run-live.js +256 -0
  582. package/dist/op/runtime.js +21 -0
  583. package/dist/op/runtimes/local.js +195 -0
  584. package/dist/op/source-archive.js +131 -0
  585. package/dist/op/step-output-ref.js +397 -0
  586. package/dist/op/steward-beside.js +169 -0
  587. package/dist/op/steward-points.js +138 -0
  588. package/dist/op/steward-turn.js +59 -0
  589. package/dist/op/steward.js +317 -0
  590. package/dist/op/types.js +25 -0
  591. package/dist/op/work-lease-decl.js +81 -0
  592. package/dist/op/work-lease-run.js +393 -0
  593. package/dist/override-gate.js +284 -0
  594. package/dist/owner-chain.js +74 -0
  595. package/dist/ownership.js +92 -0
  596. package/dist/params.js +61 -0
  597. package/dist/plan-summary.js +711 -0
  598. package/dist/point-decision.js +211 -0
  599. package/dist/pr-forge.js +810 -0
  600. package/dist/pr-loop.js +203 -0
  601. package/dist/project-codegen.js +191 -0
  602. package/dist/project-root.js +74 -0
  603. package/dist/project-validation.js +50 -0
  604. package/dist/provenance.js +157 -0
  605. package/dist/pseudo-parameter.js +40 -0
  606. package/dist/reconcile.js +450 -0
  607. package/dist/resource-attributes.js +33 -0
  608. package/dist/runtime-adapter.js +77 -0
  609. package/dist/runtime.js +66 -0
  610. package/dist/secret-materialization.js +153 -0
  611. package/dist/secret-provenance.js +250 -0
  612. package/dist/serializer-walker.js +112 -0
  613. package/dist/serializer.js +1 -0
  614. package/dist/sort.js +45 -0
  615. package/dist/stack-output.js +115 -0
  616. package/dist/telemetry-attribution.js +149 -0
  617. package/dist/terraform/__fixtures__/build-graph.js +63 -0
  618. package/dist/terraform/adopt-state.js +40 -0
  619. package/dist/terraform/aws-resources.js +384 -0
  620. package/dist/terraform/bridge.js +204 -0
  621. package/dist/terraform/carve-provider.js +155 -0
  622. package/dist/terraform/carve.js +138 -0
  623. package/dist/terraform/data-source-shape.js +57 -0
  624. package/dist/terraform/emit-source.js +36 -0
  625. package/dist/terraform/excise.js +123 -0
  626. package/dist/terraform/graduate.js +128 -0
  627. package/dist/terraform/graph.js +435 -0
  628. package/dist/terraform/hcl2json.js +60 -0
  629. package/dist/terraform/manifest.js +149 -0
  630. package/dist/terraform/parse.js +81 -0
  631. package/dist/terraform/providers/aws.js +146 -0
  632. package/dist/terraform/providers/gcp.js +294 -0
  633. package/dist/terraform/providers/index.js +17 -0
  634. package/dist/terraform/providers/kubernetes.js +253 -0
  635. package/dist/terraform/score.js +151 -0
  636. package/dist/terraform/state.js +67 -0
  637. package/dist/terraform/tier-map.js +74 -0
  638. package/dist/terraform/types.js +13 -0
  639. package/dist/terraform/unified-diff.js +132 -0
  640. package/dist/testing.js +295 -0
  641. package/dist/toml-emit.js +153 -0
  642. package/dist/toml-parse.js +355 -0
  643. package/dist/toml-utils.js +60 -0
  644. package/dist/toml.js +428 -0
  645. package/dist/ts-loader.d.ts +46 -0
  646. package/dist/ts-loader.d.ts.map +1 -0
  647. package/dist/ts-loader.js +103 -0
  648. package/dist/types.js +1 -0
  649. package/dist/utils.js +61 -0
  650. package/dist/validation.js +20 -0
  651. package/dist/vendor/js-yaml-load.js +1662 -0
  652. package/dist/workspace/__fixtures__/contract-repo.js +103 -0
  653. package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
  654. package/dist/workspace/__fixtures__/sessions.js +91 -0
  655. package/dist/workspace/__fixtures__/two-member-workspace.js +34 -0
  656. package/dist/workspace/agent-cli.js +99 -0
  657. package/dist/workspace/agent.schema.json +390 -0
  658. package/dist/workspace/answers-ledger.js +89 -0
  659. package/dist/workspace/box-cli.js +142 -0
  660. package/dist/workspace/box-factory-write.js +196 -0
  661. package/dist/workspace/box-factory-write.schema.json +342 -0
  662. package/dist/workspace/box-factory.js +88 -0
  663. package/dist/workspace/box-intent.js +126 -0
  664. package/dist/workspace/box-isolation.js +169 -0
  665. package/dist/workspace/box-listing-write.schema.json +204 -0
  666. package/dist/workspace/box-listing.js +298 -0
  667. package/dist/workspace/box-publish.js +352 -0
  668. package/dist/workspace/box-publish.schema.json +498 -0
  669. package/dist/workspace/box-services.js +39 -0
  670. package/dist/workspace/broker-protocol.js +359 -0
  671. package/dist/workspace/broker-protocol.schema.json +228 -0
  672. package/dist/workspace/change-set.schema.json +460 -0
  673. package/dist/workspace/changes-cli.js +56 -0
  674. package/dist/workspace/changes.js +446 -0
  675. package/dist/workspace/changes.schema.json +642 -0
  676. package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.js +198 -0
  677. package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.js +155 -0
  678. package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.js +214 -0
  679. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.js +180 -0
  680. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.js +99 -0
  681. package/dist/workspace/chant-migrations/chud-lexicon-exit.js +847 -0
  682. package/dist/workspace/chant-migrations.js +113 -0
  683. package/dist/workspace/check.schema.json +433 -0
  684. package/dist/workspace/checks/box-isolation.js +62 -0
  685. package/dist/workspace/checks/boxes.js +491 -0
  686. package/dist/workspace/checks/diagrams.js +104 -0
  687. package/dist/workspace/checks/generated.js +419 -0
  688. package/dist/workspace/checks/ledgers.js +212 -0
  689. package/dist/workspace/checks/links.js +191 -0
  690. package/dist/workspace/checks/live.js +100 -0
  691. package/dist/workspace/checks/pipelines.js +188 -0
  692. package/dist/workspace/checks/records.js +169 -0
  693. package/dist/workspace/checks.js +426 -0
  694. package/dist/workspace/ci-green-cli.js +125 -0
  695. package/dist/workspace/ci-green-forge.js +83 -0
  696. package/dist/workspace/ci-green-workflow.js +199 -0
  697. package/dist/workspace/ci-green.js +325 -0
  698. package/dist/workspace/ci-last-green.schema.json +158 -0
  699. package/dist/workspace/compose-graph.js +235 -0
  700. package/dist/workspace/compose-reports.js +146 -0
  701. package/dist/workspace/composites.js +264 -0
  702. package/dist/workspace/composites.schema.json +617 -0
  703. package/dist/workspace/conformance/__fixture__/app/package.json +7 -0
  704. package/dist/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
  705. package/dist/workspace/conformance/__fixture__/decisions/decision.kind.mjs +54 -0
  706. package/dist/workspace/conformance/__fixture__/decisions/decision.schema.json +512 -0
  707. package/dist/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
  708. package/dist/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
  709. package/dist/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
  710. package/dist/workspace/conformance/__fixture__/delivery/package.json +7 -0
  711. package/dist/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
  712. package/dist/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
  713. package/dist/workspace/conformance/__fixtures__/reference-broker.js +205 -0
  714. package/dist/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  715. package/dist/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  716. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  717. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  718. package/dist/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  719. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  720. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  721. package/dist/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  722. package/dist/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  723. package/dist/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  724. package/dist/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  725. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  726. package/dist/workspace/conformance/broker.js +736 -0
  727. package/dist/workspace/conformance/index.js +673 -0
  728. package/dist/workspace/conformance/vitest.js +108 -0
  729. package/dist/workspace/conformance/writer.js +1080 -0
  730. package/dist/workspace/decide.js +879 -0
  731. package/dist/workspace/decision-points.schema.json +135 -135
  732. package/dist/workspace/declaration-write-cli.js +74 -0
  733. package/dist/workspace/declaration-write.js +238 -0
  734. package/dist/workspace/declaration.js +938 -0
  735. package/dist/workspace/declaration.schema.json +1413 -1413
  736. package/dist/workspace/declared-kinds.js +106 -0
  737. package/dist/workspace/environments.js +164 -0
  738. package/dist/workspace/evidence.schema.json +279 -0
  739. package/dist/workspace/export-cli.js +185 -0
  740. package/dist/workspace/export.js +499 -0
  741. package/dist/workspace/factory-rules.js +175 -0
  742. package/dist/workspace/generated-files.js +92 -0
  743. package/dist/workspace/glob.js +45 -0
  744. package/dist/workspace/graph-cache.js +352 -0
  745. package/dist/workspace/graph-cli.js +348 -0
  746. package/dist/workspace/graph.schema.json +1338 -0
  747. package/dist/workspace/identity-gate-rule.js +75 -0
  748. package/dist/workspace/identity.js +126 -0
  749. package/dist/workspace/import.js +283 -0
  750. package/dist/workspace/init.js +620 -0
  751. package/dist/workspace/intent-cli.js +263 -0
  752. package/dist/workspace/intent-joins.js +201 -0
  753. package/dist/workspace/intent-record.js +352 -0
  754. package/dist/workspace/intent-record.schema.json +864 -0
  755. package/dist/workspace/intent.js +1582 -0
  756. package/dist/workspace/intent.schema.json +2420 -0
  757. package/dist/workspace/json-edit.js +221 -0
  758. package/dist/workspace/jsonc.js +235 -0
  759. package/dist/workspace/kind-readers.js +103 -0
  760. package/dist/workspace/kinds.js +587 -0
  761. package/dist/workspace/lexicon-symbols.js +112 -0
  762. package/dist/workspace/lineage-adopt-cli.js +102 -0
  763. package/dist/workspace/lineage-adopt.js +360 -0
  764. package/dist/workspace/lineage-check.js +282 -0
  765. package/dist/workspace/lineage-cli.js +121 -0
  766. package/dist/workspace/lineage-hash-index.js +284 -0
  767. package/dist/workspace/lineage-init.js +507 -0
  768. package/dist/workspace/lineage-lock.js +387 -0
  769. package/dist/workspace/lineage-merge.js +45 -0
  770. package/dist/workspace/lineage-migrations.d.ts.map +1 -1
  771. package/dist/workspace/lineage-migrations.js +329 -0
  772. package/dist/workspace/lineage-provenance.js +36 -0
  773. package/dist/workspace/lineage-update.js +138 -0
  774. package/dist/workspace/lineage-upgrade-cli.js +131 -0
  775. package/dist/workspace/lineage-upgrade.js +889 -0
  776. package/dist/workspace/lineage-vendor.js +171 -0
  777. package/dist/workspace/lineage-version.js +128 -0
  778. package/dist/workspace/lineage-versions.js +275 -0
  779. package/dist/workspace/links.js +330 -0
  780. package/dist/workspace/ls-generated.js +95 -0
  781. package/dist/workspace/ls.js +277 -0
  782. package/dist/workspace/ls.schema.json +333 -0
  783. package/dist/workspace/member-commands.js +508 -0
  784. package/dist/workspace/member-handles.js +216 -0
  785. package/dist/workspace/member-pipeline.js +258 -0
  786. package/dist/workspace/member-run.js +117 -0
  787. package/dist/workspace/member-write.schema.json +193 -0
  788. package/dist/workspace/nested-graph.js +156 -0
  789. package/dist/workspace/nesting.js +38 -0
  790. package/dist/workspace/patch.js +301 -0
  791. package/dist/workspace/patch.schema.json +321 -0
  792. package/dist/workspace/pin-cli.js +55 -0
  793. package/dist/workspace/pin-integrity.js +100 -0
  794. package/dist/workspace/plan-summary.schema.json +155 -0
  795. package/dist/workspace/point-answer.schema.json +129 -129
  796. package/dist/workspace/points-cli.js +291 -0
  797. package/dist/workspace/points-write.schema.json +660 -0
  798. package/dist/workspace/points.js +521 -0
  799. package/dist/workspace/points.schema.json +916 -0
  800. package/dist/workspace/pr-report.schema.json +108 -0
  801. package/dist/workspace/principal-classes.js +245 -0
  802. package/dist/workspace/reason-codes.js +326 -0
  803. package/dist/workspace/record-assets.js +151 -0
  804. package/dist/workspace/record-decided.js +105 -0
  805. package/dist/workspace/record-sessions.js +96 -0
  806. package/dist/workspace/record-source.js +114 -0
  807. package/dist/workspace/records-amend.schema.json +284 -0
  808. package/dist/workspace/records-checkout.js +76 -0
  809. package/dist/workspace/records-cli.js +707 -0
  810. package/dist/workspace/records-close.js +116 -0
  811. package/dist/workspace/records-close.schema.json +278 -0
  812. package/dist/workspace/records-new.schema.json +202 -0
  813. package/dist/workspace/records-review.schema.json +367 -0
  814. package/dist/workspace/records-since.js +317 -0
  815. package/dist/workspace/records-since.schema.json +218 -0
  816. package/dist/workspace/records-write.js +1229 -0
  817. package/dist/workspace/records.js +1345 -0
  818. package/dist/workspace/records.schema.json +604 -0
  819. package/dist/workspace/reference-kinds/app/package.json +10 -0
  820. package/dist/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  821. package/dist/workspace/returns.js +303 -0
  822. package/dist/workspace/root-refusal.js +75 -0
  823. package/dist/workspace/run-statement.schema.json +622 -0
  824. package/dist/workspace/runs-cli.js +584 -0
  825. package/dist/workspace/runs-write.schema.json +994 -0
  826. package/dist/workspace/runs.js +708 -0
  827. package/dist/workspace/runs.schema.json +1257 -0
  828. package/dist/workspace/runtimes.js +76 -0
  829. package/dist/workspace/session-kinds.js +83 -0
  830. package/dist/workspace/signers.schema.json +206 -0
  831. package/dist/workspace/source-block.js +125 -0
  832. package/dist/workspace/squash.js +177 -0
  833. package/dist/workspace/status-gates.js +162 -0
  834. package/dist/workspace/status-stewards.js +330 -0
  835. package/dist/workspace/status.js +514 -0
  836. package/dist/workspace/status.schema.json +998 -0
  837. package/dist/workspace/steward-index.js +191 -0
  838. package/dist/workspace/symbols.js +188 -0
  839. package/dist/workspace/template-manifest.js +227 -0
  840. package/dist/workspace/template-pins.js +115 -0
  841. package/dist/workspace/trailer-joins.js +65 -0
  842. package/dist/workspace/trailers.js +111 -0
  843. package/dist/workspace/tree.js +136 -0
  844. package/dist/workspace/trust/attestor.js +63 -0
  845. package/dist/workspace/trust/dsse.js +108 -0
  846. package/dist/workspace/trust/evidence-cli.js +175 -0
  847. package/dist/workspace/trust/evidence.js +161 -0
  848. package/dist/workspace/trust/gate-seal.js +226 -0
  849. package/dist/workspace/trust/policy.js +190 -0
  850. package/dist/workspace/trust/provenance.js +180 -0
  851. package/dist/workspace/trust/rotation.js +298 -0
  852. package/dist/workspace/trust/run-commits.js +101 -0
  853. package/dist/workspace/trust/run-statement.js +182 -0
  854. package/dist/workspace/trust/seal.js +272 -0
  855. package/dist/workspace/trust/signers-cli.js +152 -0
  856. package/dist/workspace/trust/ssh-commit.js +178 -0
  857. package/dist/workspace/trust/test-repo.js +118 -0
  858. package/dist/workspace/trust/trust-files.js +193 -0
  859. package/dist/workspace/trust/verify-cli.js +63 -0
  860. package/dist/workspace/trust/verify.js +192 -0
  861. package/dist/workspace/which-chant.js +141 -0
  862. package/dist/workspace/wip-cli.js +95 -0
  863. package/dist/workspace/wip-write.schema.json +504 -0
  864. package/dist/workspace/wip.js +631 -0
  865. package/dist/workspace/wip.schema.json +334 -0
  866. package/dist/workspace/work-cli.js +448 -0
  867. package/dist/workspace/work-evidence.js +122 -0
  868. package/dist/workspace/work-evidence.schema.json +222 -0
  869. package/dist/workspace/work-history.schema.json +421 -0
  870. package/dist/workspace/work-lease.schema.json +246 -0
  871. package/dist/workspace/work-size.js +77 -0
  872. package/dist/workspace/work.js +283 -0
  873. package/dist/workspace/workspace-kinds.schema.json +259 -259
  874. package/dist/workspace/workspace-principals.schema.json +53 -53
  875. package/dist/workspace/write-lock-cli.js +105 -0
  876. package/dist/workspace/write-lock.js +424 -0
  877. package/dist/workspace/write-lock.schema.json +172 -0
  878. package/dist/workspace/write-scope.js +484 -0
  879. package/dist/yaml.js +459 -0
  880. package/package.json +2 -2
  881. package/src/cli/commands/check-lexicon-plugin.ts +2 -0
  882. package/src/cli/commands/lint.ts +3 -0
  883. package/src/cli/commands/migrate.ts +2 -0
  884. package/src/cli/compiled-cli.e2e.test.ts +165 -0
  885. package/src/cli/main.ts +121 -27
  886. package/src/cli/mcp/workspace-tools.ts +1 -1
  887. package/src/codegen/pinned-upgrade.ts +2 -0
  888. package/src/components/discover.ts +2 -0
  889. package/src/components/sandbox/driver.ts +3 -1
  890. package/src/config-import.ts +3 -0
  891. package/src/discovery/fold-import.ts +23 -14
  892. package/src/discovery/import.ts +2 -0
  893. package/src/discovery/sandbox/driver.ts +3 -1
  894. package/src/lexicon-module.ts +3 -0
  895. package/src/lint/config.ts +1 -1
  896. package/src/lint/discover.ts +28 -8
  897. package/src/lint/policy-import.ts +4 -1
  898. package/src/lint/rule-loader.ts +2 -0
  899. package/src/op/discover.ts +3 -0
  900. package/src/ts-loader.test.ts +23 -0
  901. package/src/ts-loader.ts +122 -0
  902. package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
  903. package/src/workspace/declaration.ts +1 -1
  904. package/src/workspace/kinds.ts +1 -1
  905. package/src/workspace/lineage-migrations.ts +2 -0
  906. package/src/workspace/points.ts +1 -1
  907. package/src/workspace/principal-classes.ts +1 -1
@@ -0,0 +1,2540 @@
1
+ #!/usr/bin/env tsx
2
+ import { resolve } from "node:path";
3
+ import { isEntryPoint } from "./is-entry-point.js";
4
+ import { formatError } from "./format.js";
5
+ import { resolveCommand } from "./registry.js";
6
+ import { loadChantConfigUpward } from "../config.js";
7
+ import { findProjectRoot, findWorkspaceRoot } from "../project-root.js";
8
+ import { isNoLexiconDetected } from "../detectLexicon.js";
9
+ import { CHANT_VERSION } from "./version.js";
10
+ import { validateLexiconConfig, formatLexiconConfigProblems } from "../lexicon-config.js";
11
+ import { armSandboxConfigEvaluation } from "../config-sandbox.js";
12
+ import { armSandboxPolicyExecution } from "../lint/policy-import.js";
13
+ import { ENV_VAR, unknownEnvError } from "../env.js";
14
+ import { initRuntime } from "../runtime-adapter.js";
15
+ import { installCompiledCli } from "../ts-loader.js";
16
+ import { splitJoinedFlags, dispatchCommandGroup, collectCommandGroups, formatCommandGroupsHelp } from "./command-group.js";
17
+ const handlerModules = new Map();
18
+ function lazyHandler(load, pick) {
19
+ const handler = async (ctx) => pick(await load())(ctx);
20
+ handlerModules.set(handler, load);
21
+ return handler;
22
+ }
23
+ const buildHandlers = () => import("./handlers/build.js");
24
+ const runBuild = lazyHandler(buildHandlers, (m) => m.runBuild);
25
+ const lintHandlers = () => import("./handlers/lint.js");
26
+ const runLint = lazyHandler(lintHandlers, (m) => m.runLint);
27
+ const devHandlers = () => import("./handlers/dev.js");
28
+ const runDevGenerate = lazyHandler(devHandlers, (m) => m.runDevGenerate);
29
+ const runDevPublish = lazyHandler(devHandlers, (m) => m.runDevPublish);
30
+ const runDevOnboard = lazyHandler(devHandlers, (m) => m.runDevOnboard);
31
+ const runDevCheckLexicon = lazyHandler(devHandlers, (m) => m.runDevCheckLexicon);
32
+ const runDevSurfaceDiff = lazyHandler(devHandlers, (m) => m.runDevSurfaceDiff);
33
+ const runDevPinnedUpgrade = lazyHandler(devHandlers, (m) => m.runDevPinnedUpgrade);
34
+ const runDevRollingUpgrade = lazyHandler(devHandlers, (m) => m.runDevRollingUpgrade);
35
+ const runDevUnknown = lazyHandler(devHandlers, (m) => m.runDevUnknown);
36
+ const serveHandlers = () => import("./handlers/serve.js");
37
+ const runServeLsp = lazyHandler(serveHandlers, (m) => m.runServeLsp);
38
+ const runServeMcp = lazyHandler(serveHandlers, (m) => m.runServeMcp);
39
+ const runServeUnknown = lazyHandler(serveHandlers, (m) => m.runServeUnknown);
40
+ const initHandlers = () => import("./handlers/init.js");
41
+ const runInit = lazyHandler(initHandlers, (m) => m.runInit);
42
+ const runInitLexicon = lazyHandler(initHandlers, (m) => m.runInitLexicon);
43
+ const miscHandlers = () => import("./handlers/misc.js");
44
+ const runList = lazyHandler(miscHandlers, (m) => m.runList);
45
+ const runDescribe = lazyHandler(miscHandlers, (m) => m.runDescribe);
46
+ const runImport = lazyHandler(miscHandlers, (m) => m.runImport);
47
+ const runAudit = lazyHandler(miscHandlers, (m) => m.runAudit);
48
+ const runUpdate = lazyHandler(miscHandlers, (m) => m.runUpdate);
49
+ const runDoctor = lazyHandler(miscHandlers, (m) => m.runDoctor);
50
+ const vendorHandlers = () => import("./handlers/vendor.js");
51
+ const runVendor = lazyHandler(vendorHandlers, (m) => m.runVendor);
52
+ const migrateHandlers = () => import("./handlers/migrate.js");
53
+ const runMigrate = lazyHandler(migrateHandlers, (m) => m.runMigrate);
54
+ const carveHandlers = () => import("./handlers/carve.js");
55
+ const runCarveAdvise = lazyHandler(carveHandlers, (m) => m.runCarveAdvise);
56
+ const runCarveUnknown = lazyHandler(carveHandlers, (m) => m.runCarveUnknown);
57
+ const carveEmitHandlers = () => import("./handlers/carve-emit.js");
58
+ const runCarveEmit = lazyHandler(carveEmitHandlers, (m) => m.runCarveEmit);
59
+ const carveBridgeHandlers = () => import("./handlers/carve-bridge.js");
60
+ const runCarveBridge = lazyHandler(carveBridgeHandlers, (m) => m.runCarveBridge);
61
+ const carveApplyHandlers = () => import("./handlers/carve-apply.js");
62
+ const runCarveApply = lazyHandler(carveApplyHandlers, (m) => m.runCarveApply);
63
+ const carveStatusHandlers = () => import("./handlers/carve-status.js");
64
+ const runCarveStatus = lazyHandler(carveStatusHandlers, (m) => m.runCarveStatus);
65
+ const lifecycleHandlers = () => import("./handlers/lifecycle.js");
66
+ const runLifecycleSnapshot = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleSnapshot);
67
+ const runLifecycleShow = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleShow);
68
+ const runLifecycleDiff = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleDiff);
69
+ const runLifecycleRollback = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleRollback);
70
+ const runLifecyclePlan = lazyHandler(lifecycleHandlers, (m) => m.runLifecyclePlan);
71
+ const runLifecycleAffected = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleAffected);
72
+ const runLifecycleLog = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleLog);
73
+ const runLifecycleTeardown = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleTeardown);
74
+ const runLifecycleWhoami = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleWhoami);
75
+ const runLifecycleUnknown = lazyHandler(lifecycleHandlers, (m) => m.runLifecycleUnknown);
76
+ const componentsHandlers = () => import("./handlers/components.js");
77
+ const runComponentsStatus = lazyHandler(componentsHandlers, (m) => m.runComponentsStatus);
78
+ const runComponentsReleaseRecord = lazyHandler(componentsHandlers, (m) => m.runComponentsReleaseRecord);
79
+ const runComponentsExport = lazyHandler(componentsHandlers, (m) => m.runComponentsExport);
80
+ const runComponentsUnknown = lazyHandler(componentsHandlers, (m) => m.runComponentsUnknown);
81
+ const fanOutHandlers = () => import("./handlers/fan-out.js");
82
+ const runComponentsFanOut = lazyHandler(fanOutHandlers, (m) => m.runComponentsFanOut);
83
+ const promoteHandlers = () => import("./handlers/promote.js");
84
+ const runComponentsPromote = lazyHandler(promoteHandlers, (m) => m.runComponentsPromote);
85
+ const runComponentsRollback = lazyHandler(promoteHandlers, (m) => m.runComponentsRollback);
86
+ const runComponentsRedeploy = lazyHandler(promoteHandlers, (m) => m.runComponentsRedeploy);
87
+ const scenarioHandlers = () => import("./handlers/scenario.js");
88
+ const runScenarioCheck = lazyHandler(scenarioHandlers, (m) => m.runScenarioCheck);
89
+ const runScenarioUnknown = lazyHandler(scenarioHandlers, (m) => m.runScenarioUnknown);
90
+ const graphHandlers = () => import("./handlers/graph.js");
91
+ const runGraph = lazyHandler(graphHandlers, (m) => m.runGraph);
92
+ const explainHandlers = () => import("./handlers/explain.js");
93
+ const runExplain = lazyHandler(explainHandlers, (m) => m.runExplain);
94
+ const searchHandlers = () => import("./handlers/search.js");
95
+ const runSearch = lazyHandler(searchHandlers, (m) => m.runSearch);
96
+ const runHandlers = () => import("./handlers/run.js");
97
+ const runOp = lazyHandler(runHandlers, (m) => m.runOp);
98
+ const runOpList = lazyHandler(runHandlers, (m) => m.runOpList);
99
+ const runOpStatus = lazyHandler(runHandlers, (m) => m.runOpStatus);
100
+ const runOpApprove = lazyHandler(runHandlers, (m) => m.runOpApprove);
101
+ const runOpSignalRenamed = lazyHandler(runHandlers, (m) => m.runOpSignalRenamed);
102
+ const runOpCancel = lazyHandler(runHandlers, (m) => m.runOpCancel);
103
+ const runOpLog = lazyHandler(runHandlers, (m) => m.runOpLog);
104
+ const runWaveHandlers = () => import("./handlers/run-wave.js");
105
+ const runOpWaveCommand = lazyHandler(runWaveHandlers, (m) => m.runOpWaveCommand);
106
+ const operatorHandlers = () => import("./handlers/operator.js");
107
+ const runOperator = lazyHandler(operatorHandlers, (m) => m.runOperator);
108
+ const runOperatorStatus = lazyHandler(operatorHandlers, (m) => m.runOperatorStatus);
109
+ const runOperatorLog = lazyHandler(operatorHandlers, (m) => m.runOperatorLog);
110
+ const runApprove = lazyHandler(operatorHandlers, (m) => m.runApprove);
111
+ const emulatorHandlers = () => import("./handlers/emulator.js");
112
+ const runEmulator = lazyHandler(emulatorHandlers, (m) => m.runEmulator);
113
+ /** The lexicon plugin loader, which imports the lint, fold and build machinery: loaded when a command needs plugins (#3878). */
114
+ const loadPlugins = async (...a) => (await import("./plugins.js")).loadPlugins(...a);
115
+ const resolveProjectLexicons = async (...a) => (await import("./plugins.js")).resolveProjectLexicons(...a);
116
+ /**
117
+ * Long-form flags that are pure booleans in {@link parseArgs} — their branch
118
+ * below sets a field to `true` and never consumes a following array element.
119
+ * Used only to reject a joined `--flag=value` form for these (chant #1127):
120
+ * a boolean has no value to assign, and silently reinterpreting the joined
121
+ * value as the next positional argument (path, component name, ...) would be
122
+ * exactly the kind of silent misparse this issue exists to close. `--report`
123
+ * is deliberately excluded — it's context-sensitive (bare boolean vs a SARIF
124
+ * path, decided by lookahead), so a joined value for it is legitimate and
125
+ * already handled correctly once split.
126
+ */
127
+ const BOOLEAN_FLAGS = new Set([
128
+ "--help",
129
+ "--open",
130
+ "--version",
131
+ "--agents",
132
+ "--agent",
133
+ "--all-projects",
134
+ "--force",
135
+ "--fix",
136
+ "--watch",
137
+ "--verbose",
138
+ "--live",
139
+ "--overlay",
140
+ "--explain",
141
+ "--owned",
142
+ "--verbatim",
143
+ "--apply-rewrites",
144
+ "--write",
145
+ "--strict",
146
+ "--validate",
147
+ "--use-composites",
148
+ "--composites",
149
+ "--stacks",
150
+ "--components",
151
+ "--up",
152
+ "--down",
153
+ "--include-dependents",
154
+ "--local",
155
+ "--json",
156
+ "--progress-json",
157
+ "--update-snapshot",
158
+ "--update-baseline",
159
+ "--run-examples",
160
+ "--check",
161
+ "--bump",
162
+ "--no-release-record",
163
+ "--fold",
164
+ "--no-fold",
165
+ "--no-cache",
166
+ "--sandbox",
167
+ "--yes",
168
+ "--confirm-prod",
169
+ "--once",
170
+ "--expire",
171
+ "--check-live",
172
+ "--check-snapshot",
173
+ "--fail-on-drift",
174
+ "--durable-requests",
175
+ "--skip-mcp",
176
+ "--current",
177
+ "--uncommitted",
178
+ "--allow-code",
179
+ "--root-only",
180
+ "--generated",
181
+ "--decide",
182
+ "--record-plans",
183
+ ]);
184
+ /**
185
+ * Parse command line arguments
186
+ */
187
+ export function parseArgs(args) {
188
+ // Local mutable copy — chant #1127's joined-`--flag=value` splitting below
189
+ // rewrites the array in place (one token becomes two), so this must not
190
+ // mutate whatever array the caller passed in (e.g. `process.argv.slice(2)`
191
+ // is already a fresh copy, but callers shouldn't have to know that).
192
+ args = args.slice();
193
+ const result = {
194
+ command: "",
195
+ path: ".",
196
+ extraPositional: undefined,
197
+ extraPositional2: undefined,
198
+ output: undefined,
199
+ format: "",
200
+ force: undefined,
201
+ fix: false,
202
+ lexicon: undefined,
203
+ template: undefined,
204
+ watch: false,
205
+ verbose: false,
206
+ help: false,
207
+ param: undefined,
208
+ paramsFile: undefined,
209
+ report: undefined,
210
+ local: undefined,
211
+ profile: undefined,
212
+ json: undefined,
213
+ live: false,
214
+ migrateFrom: undefined,
215
+ migrateTo: undefined,
216
+ emit: undefined,
217
+ strict: false,
218
+ validate: false,
219
+ useComposites: false,
220
+ reportFile: undefined,
221
+ skill: undefined,
222
+ skipMcp: undefined,
223
+ src: undefined,
224
+ env: undefined,
225
+ };
226
+ // chant #1127 — generic joined `--flag=value` support, factored out to
227
+ // ./command-group.ts (chant #1078) so a lexicon's own mounted command can
228
+ // apply the identical splitting discipline to its own flag vocabulary.
229
+ // Every value-taking flag below is matched by an exact `arg === "--flag"`
230
+ // check and then consumes the *next* array element (`args[++i]`) as its
231
+ // value; a joined token like `--env=prod` never matches any of those,
232
+ // doesn't match the trailing positional branch either (it starts with
233
+ // `-`), and used to vanish with no error. Splitting the token at its FIRST
234
+ // `=` and re-dispatching as two array elements makes every flag below see
235
+ // the exact shape it already handles — including a flag like `--param`
236
+ // whose own value legitimately contains `=` (`--param=tier=production`
237
+ // splits to flag `--param`, value `tier=production`, not further split on
238
+ // the second `=`).
239
+ args = splitJoinedFlags(args, BOOLEAN_FLAGS);
240
+ let i = 0;
241
+ while (i < args.length) {
242
+ const arg = args[i];
243
+ if (arg === "--help" || arg === "-h") {
244
+ result.help = true;
245
+ }
246
+ else if (arg === "--version" || arg === "-V") {
247
+ result.version = true;
248
+ }
249
+ else if (arg === "--output" || arg === "-o") {
250
+ result.output = args[++i];
251
+ }
252
+ else if (arg === "--format" || arg === "-f") {
253
+ result.format = args[++i];
254
+ }
255
+ else if (arg === "--lexicon" || arg === "-d") {
256
+ result.lexicon = args[++i];
257
+ }
258
+ else if (arg === "--template" || arg === "-t") {
259
+ result.template = args[++i];
260
+ }
261
+ else if (arg === "--force") {
262
+ result.force = true;
263
+ }
264
+ else if (arg === "--fix") {
265
+ result.fix = true;
266
+ }
267
+ else if (arg === "--watch" || arg === "-w") {
268
+ result.watch = true;
269
+ }
270
+ else if (arg === "--verbose" || arg === "-v") {
271
+ result.verbose = true;
272
+ }
273
+ else if (arg === "--profile" || arg === "-p") {
274
+ result.profile = args[++i];
275
+ }
276
+ else if (arg === "--report") {
277
+ // --report alone is the boolean (used by `run`); --report <path> is
278
+ // the migrate-command file path. Look ahead for a non-flag.
279
+ const next = args[i + 1];
280
+ if (next && !next.startsWith("-")) {
281
+ result.reportFile = next;
282
+ i++;
283
+ }
284
+ else {
285
+ result.report = true;
286
+ }
287
+ }
288
+ else if (arg === "--live") {
289
+ result.live = true;
290
+ }
291
+ else if (arg === "--overlay") {
292
+ result.overlay = true;
293
+ }
294
+ else if (arg === "--between") {
295
+ result.betweenA = args[++i];
296
+ result.betweenB = args[++i];
297
+ if (!result.betweenA || !result.betweenB)
298
+ throw new Error("--between needs two snapshot refs: --between <refA> <refB>");
299
+ }
300
+ else if (arg === "--traffic") {
301
+ const v = args[++i];
302
+ if (!v)
303
+ throw new Error('--traffic needs a level, passed to the engine verbatim: --traffic "100 rps, p50"');
304
+ result.traffic = v;
305
+ }
306
+ else if (arg === "--overlay-anchor") {
307
+ const v = args[++i];
308
+ if (v !== "source" && v !== "live")
309
+ throw new Error(`--overlay-anchor must be 'source' or 'live', got '${v}'`);
310
+ result.overlayAnchor = v;
311
+ }
312
+ else if (arg === "--from") {
313
+ // Shared by `migrate --from <lexicon>`, `import --from <env>`,
314
+ // `components promote --from <env>` and `init --from <repo>@<ref>`;
315
+ // the commands never run together, so one field carries all four.
316
+ result.migrateFrom = args[++i];
317
+ }
318
+ else if (arg === "--kustomize") {
319
+ // `chant import --kustomize <dir>` (#1548): render the overlay, import
320
+ // the output through the k8s template parser.
321
+ result.kustomize = args[++i];
322
+ }
323
+ else if (arg === "--parser-option") {
324
+ // `chant import --parser-option key[=value]` (#2994), repeatable: checked
325
+ // against the lexicon's parserOptions() by the import command.
326
+ const v = args[++i];
327
+ if (!v || v.startsWith("-"))
328
+ throw new Error("--parser-option needs key or key=value: --parser-option acceptLossyV1");
329
+ (result.parserOption ?? (result.parserOption = [])).push(v);
330
+ }
331
+ else if (arg === "--type") {
332
+ result.selectType = args[++i];
333
+ }
334
+ else if (arg === "--name") {
335
+ result.selectName = args[++i];
336
+ }
337
+ else if (arg === "--owned") {
338
+ result.owned = true;
339
+ }
340
+ else if (arg === "--namespace") {
341
+ // The live read's namespace default (#1629), not a kubectl `-n`: it fills
342
+ // in for entities that declare no namespace and leaves the ones that do
343
+ // alone. No `-n` short form — that spelling belongs to `chant kube`,
344
+ // where it means kubectl's scope selector.
345
+ result.namespace = args[++i];
346
+ if (!result.namespace || result.namespace.startsWith("-"))
347
+ throw new Error("--namespace needs a namespace: --namespace <ns>");
348
+ }
349
+ else if (arg === "--verbatim") {
350
+ result.verbatim = true;
351
+ }
352
+ else if (arg === "--state") {
353
+ result.statePath = args[++i];
354
+ }
355
+ else if (arg === "--select") {
356
+ result.selectAddress = args[++i];
357
+ }
358
+ else if (arg === "--live-name") {
359
+ result.liveName = args[++i];
360
+ }
361
+ else if (arg === "--apply-rewrites") {
362
+ result.applyRewrites = true;
363
+ }
364
+ else if (arg === "--stack") {
365
+ result.carveStack = args[++i];
366
+ }
367
+ else if (arg === "--write") {
368
+ result.write = true;
369
+ }
370
+ else if (arg === "--write-source") {
371
+ result.writeSource = true;
372
+ }
373
+ else if (arg === "--to") {
374
+ result.migrateTo = args[++i];
375
+ }
376
+ else if (arg === "--emit") {
377
+ result.emit = args[++i];
378
+ }
379
+ else if (arg === "--dry-run") {
380
+ result.dryRun = true;
381
+ }
382
+ else if (arg === "--yes") {
383
+ result.yes = true;
384
+ }
385
+ else if (arg === "--confirm-prod") {
386
+ result.confirmProd = true;
387
+ }
388
+ else if (arg === "--strict") {
389
+ result.strict = true;
390
+ }
391
+ else if (arg === "--validate") {
392
+ result.validate = true;
393
+ }
394
+ else if (arg === "--use-composites") {
395
+ result.useComposites = true;
396
+ }
397
+ else if (arg === "--skill") {
398
+ result.skill = args[++i];
399
+ }
400
+ else if (arg === "--skip-mcp") {
401
+ result.skipMcp = true;
402
+ }
403
+ else if (arg === "--src") {
404
+ result.src = args[++i];
405
+ }
406
+ else if (arg === "--env") {
407
+ result.env = args[++i];
408
+ }
409
+ else if (arg === "--port") {
410
+ const value = args[++i];
411
+ if (!value || value.startsWith("-"))
412
+ throw new Error("--port needs a port: --port <container-port>=<host-port>");
413
+ (result.port ?? (result.port = [])).push(value);
414
+ }
415
+ else if (arg === "--promote-to") {
416
+ result.promoteTo = args[++i];
417
+ if (!result.promoteTo || result.promoteTo.startsWith("-"))
418
+ throw new Error("--promote-to needs an environment: --promote-to <env>");
419
+ }
420
+ else if (arg === "--tier") {
421
+ result.tier = args[++i];
422
+ }
423
+ else if (arg === "--agents") {
424
+ result.agents = true;
425
+ }
426
+ else if (arg === "--scope") {
427
+ result.scope = args[++i];
428
+ }
429
+ else if (arg === "--all-projects") {
430
+ result.allProjects = true;
431
+ }
432
+ else if (arg === "--runtime") {
433
+ result.runtime = args[++i];
434
+ }
435
+ else if (arg === "--fail-on") {
436
+ result.failOn = args[++i];
437
+ }
438
+ else if (arg === "--max-files") {
439
+ // Validated by the audit handler, like `--limit` below.
440
+ result.maxFiles = Number(args[++i]);
441
+ }
442
+ else if (arg === "--theme") {
443
+ result.theme = args[++i];
444
+ }
445
+ else if (arg === "--stacks") {
446
+ result.stacks = true;
447
+ }
448
+ else if (arg === "--components") {
449
+ result.components = true;
450
+ }
451
+ else if (arg === "--generate") {
452
+ result.generate = args[++i];
453
+ }
454
+ else if (arg === "--spec") {
455
+ result.opsSpec = args[++i];
456
+ }
457
+ else if (arg === "--dump-outputs") {
458
+ result.dumpOutputs = args[++i];
459
+ }
460
+ else if (arg === "--digest-file") {
461
+ result.digestFile = args[++i];
462
+ }
463
+ else if (arg === "--seed-outputs") {
464
+ (result.seedOutputs ?? (result.seedOutputs = [])).push(args[++i]);
465
+ }
466
+ else if (arg === "--detail") {
467
+ result.detail = Number(args[++i]);
468
+ }
469
+ else if (arg === "--lens") {
470
+ result.lens = args[++i];
471
+ }
472
+ else if (arg === "--explain") {
473
+ result.explain = true;
474
+ }
475
+ else if (arg === "--show") {
476
+ result.show = args[++i];
477
+ }
478
+ else if (arg === "--up") {
479
+ result.up = true;
480
+ }
481
+ else if (arg === "--down") {
482
+ result.down = true;
483
+ }
484
+ else if (arg === "--node-sizes") {
485
+ result.nodeSizes = args[++i];
486
+ }
487
+ else if (arg === "--layout-engine") {
488
+ result.layoutEngine = args[++i];
489
+ }
490
+ else if (arg === "--base") {
491
+ result.base = args[++i];
492
+ }
493
+ else if (arg === "--head") {
494
+ result.head = args[++i];
495
+ }
496
+ else if (arg === "--include-dependents") {
497
+ result.includeDependents = true;
498
+ }
499
+ else if (arg === "--from-affected") {
500
+ result.fromAffected = args[++i];
501
+ }
502
+ else if (arg === "--gate") {
503
+ result.gate = args[++i];
504
+ }
505
+ else if (arg === "--wave-gate") {
506
+ result.waveGate = args[++i];
507
+ if (!result.waveGate || result.waveGate.startsWith("-"))
508
+ throw new Error("--wave-gate needs a gate name: --wave-gate <name>");
509
+ }
510
+ else if (arg === "--wave") {
511
+ const raw = args[++i];
512
+ const wave = Number(raw);
513
+ if (!Number.isInteger(wave) || wave < 1)
514
+ throw new Error(`--wave needs a wave number from 1: got "${raw ?? ""}"`);
515
+ result.wave = wave;
516
+ }
517
+ else if (arg === "--decide") {
518
+ result.decide = true;
519
+ }
520
+ else if (arg === "--record-plans") {
521
+ result.recordPlans = true;
522
+ }
523
+ else if (arg === "--share") {
524
+ const raw = args[++i];
525
+ const share = Number(raw);
526
+ if (!Number.isInteger(share) || share < 1)
527
+ throw new Error(`--share needs a share number from 1: got "${raw ?? ""}"`);
528
+ result.share = share;
529
+ }
530
+ else if (arg === "--canary") {
531
+ const raw = args[++i];
532
+ if (!raw || raw.startsWith("-"))
533
+ throw new Error("--canary needs a component name: --canary <name>[,<name>...]");
534
+ (result.canary ?? (result.canary = [])).push(...raw.split(",").map((n) => n.trim()).filter(Boolean));
535
+ }
536
+ else if (arg === "--pr") {
537
+ const raw = args[++i];
538
+ const pr = Number(raw);
539
+ if (!Number.isInteger(pr) || pr < 1)
540
+ throw new Error(`--pr needs a pull or merge request number: got "${raw ?? ""}"`);
541
+ result.pr = pr;
542
+ }
543
+ else if (arg === "--forge") {
544
+ result.forge = args[++i];
545
+ if (!result.forge || result.forge.startsWith("-"))
546
+ throw new Error("--forge needs a forge: --forge github|gitlab|forgejo");
547
+ }
548
+ else if (arg === "--require-review") {
549
+ result.requireReview = true;
550
+ }
551
+ else if (arg === "--pr-loop") {
552
+ result.prLoop = true;
553
+ }
554
+ else if (arg === "--resume") {
555
+ // `chant approve <op> <gate> --resume` (#3683) takes no value; the
556
+ // fan-out and pull-request apply take the attempt file they resume.
557
+ const next = args[i + 1];
558
+ if (next === undefined || next.startsWith("-"))
559
+ result.resumeRun = true;
560
+ else
561
+ result.resume = args[++i];
562
+ }
563
+ else if (arg === "--local") {
564
+ result.local = true;
565
+ }
566
+ else if (arg === "--json") {
567
+ result.json = true;
568
+ }
569
+ else if (arg === "--progress-json") {
570
+ result.progressJson = true;
571
+ }
572
+ else if (arg === "--gated-exit") {
573
+ // `chant run <op> --gated-exit <code>` (#2243) — remap only the gated
574
+ // outcome's exit code. Parsed as a number here and range-checked in the
575
+ // handler, where the refusal can name the flag alongside the run.
576
+ result.gatedExit = Number(args[++i]);
577
+ }
578
+ else if (arg === "--durable-requests") {
579
+ // `chant run approve ... --on <lexicon> --durable-requests` (#2126) —
580
+ // resolve the gate on the hosting runtime's own request path rather
581
+ // than by posting a follow-up prompt. Core only carries the flag; the
582
+ // runtime decides whether it has such a path.
583
+ result.durableRequests = true;
584
+ }
585
+ else if (arg === "--update-snapshot") {
586
+ result.updateSnapshot = true;
587
+ }
588
+ else if (arg === "--update-baseline") {
589
+ result.updateBaseline = true;
590
+ }
591
+ else if (arg === "--deep") {
592
+ result.deep = true;
593
+ }
594
+ else if (arg === "--at") {
595
+ result.at = args[++i];
596
+ }
597
+ else if (arg === "--kind") {
598
+ // `chant workspace records|graph|check --kind <kind file>` (#2546, #2549)
599
+ result.kind = args[++i];
600
+ if (!result.kind || result.kind.startsWith("-"))
601
+ throw new Error("--kind needs a kind file: --kind <path>");
602
+ // Repeatable for `workspace graph --intent` (#2651); the others read the last one.
603
+ (result.kinds ?? (result.kinds = [])).push(result.kind);
604
+ }
605
+ else if (arg === "--composites") {
606
+ // `chant workspace graph --composites` (#2662)
607
+ result.composites = true;
608
+ }
609
+ else if (arg === "--intent") {
610
+ // `chant workspace graph --intent <path[:start-end]|path#symbol>` (#2651), or `--intent --record <id>` with no region.
611
+ const value = args[i + 1];
612
+ if (value !== undefined && !value.startsWith("-"))
613
+ result.intent = args[++i];
614
+ else if (args.includes("--record"))
615
+ result.intent = "";
616
+ else
617
+ throw new Error("--intent needs a region: --intent <path[:start-end]|path#symbol>, or --intent --record <id>");
618
+ }
619
+ else if (arg === "--follow-squash") {
620
+ // `chant workspace graph --intent ... --follow-squash` and `chant workspace runs --follow-squash` (#3035)
621
+ result.followSquash = true;
622
+ }
623
+ else if (arg === "--record") {
624
+ // `chant workspace graph --intent --record <id>`
625
+ result.record = args[++i];
626
+ if (!result.record || result.record.startsWith("-"))
627
+ throw new Error("--record needs a record id: --record <id>");
628
+ }
629
+ else if (arg === "--path") {
630
+ // `chant workspace patch <range> --path <p>`, repeatable
631
+ const value = args[++i];
632
+ if (!value || value.startsWith("-"))
633
+ throw new Error("--path needs a path: --path <path>");
634
+ (result.paths ?? (result.paths = [])).push(value);
635
+ }
636
+ else if (arg === "--worktree") {
637
+ // `chant workspace patch [<commit>] --worktree`
638
+ result.worktree = true;
639
+ }
640
+ else if (arg === "--max-bytes") {
641
+ // `chant workspace patch <range> --max-bytes <n>`
642
+ const value = Number(args[++i]);
643
+ if (!Number.isInteger(value) || value < 1)
644
+ throw new Error("--max-bytes needs a whole number of bytes above 0");
645
+ result.maxBytes = value;
646
+ }
647
+ else if (arg === "--changes") {
648
+ // `chant workspace check --changes <base>..<head>` (#2773)
649
+ result.changes = args[++i];
650
+ if (!result.changes || result.changes.startsWith("-"))
651
+ throw new Error("--changes needs a range: --changes <base>..<head>");
652
+ }
653
+ else if (arg === "--severity") {
654
+ // `chant workspace check --changes <range> --severity off|warn|fail` (#2773)
655
+ result.severity = args[++i];
656
+ if (!result.severity || result.severity.startsWith("-"))
657
+ throw new Error("--severity needs off, warn or fail");
658
+ }
659
+ else if (arg === "--current") {
660
+ result.current = true;
661
+ }
662
+ else if (arg === "--uncommitted") {
663
+ // `chant workspace records --uncommitted` (#3160)
664
+ result.uncommitted = true;
665
+ }
666
+ else if (arg === "--set") {
667
+ // `chant workspace records amend <id> --set <file|->` (#2670)
668
+ result.set = args[++i];
669
+ if (!result.set || (result.set.startsWith("-") && result.set !== "-"))
670
+ throw new Error("--set needs a JSON file, or - for standard input: --set <file|->");
671
+ }
672
+ else if (arg === "--cover") {
673
+ // `chant workspace box listing set <member> --cover <image>` (#3308)
674
+ result.cover = args[++i];
675
+ if (!result.cover || result.cover.startsWith("-"))
676
+ throw new Error("--cover needs a PNG, JPEG or WebP file: --cover <image>");
677
+ }
678
+ else if (arg === "--cover-path") {
679
+ // `chant workspace box listing set <member> --cover <image> --cover-path <path>` (#3308)
680
+ result.coverPath = args[++i];
681
+ if (!result.coverPath || result.coverPath.startsWith("-"))
682
+ throw new Error("--cover-path needs a path from the workspace root: --cover-path <path>");
683
+ }
684
+ else if (arg === "--records") {
685
+ // `chant workspace box publish <member> --records` (#3165): the records kept uncommitted, not a work item.
686
+ result.records = true;
687
+ }
688
+ else if (arg === "--expect") {
689
+ // `chant workspace records amend|review|close <id> --expect <digest>` (#3173): the record's digest the caller last read.
690
+ result.expect = args[++i];
691
+ if (!result.expect || result.expect.startsWith("-"))
692
+ throw new Error("--expect needs the record's digest, as records --json prints it: --expect <digest>");
693
+ }
694
+ else if (arg === "--label") {
695
+ // `chant workspace wip save --label <text>` (#3172)
696
+ result.label = args[++i];
697
+ if (!result.label || result.label.startsWith("-"))
698
+ throw new Error("--label needs the snapshot's name, such as a turn id: --label <text>");
699
+ }
700
+ else if (arg === "--branch") {
701
+ // `chant workspace wip --branch <branch>` (#3172)
702
+ result.branch = args[++i];
703
+ if (!result.branch || result.branch.startsWith("-"))
704
+ throw new Error("--branch needs a branch name: --branch <branch>");
705
+ }
706
+ else if (arg === "--workflow") {
707
+ // `chant ci workflow --workflow <name>`, repeatable (#3573)
708
+ const name = args[++i];
709
+ if (!name || name.startsWith("-"))
710
+ throw new Error("--workflow needs a workflow's name: --workflow <name>");
711
+ result.ciWorkflows = [...(result.ciWorkflows ?? []), name];
712
+ }
713
+ else if (arg === "--chant") {
714
+ // `chant ci workflow --chant <command>` (#3573): what the tick step runs chant with.
715
+ result.ciChant = args[++i];
716
+ if (!result.ciChant || result.ciChant.startsWith("-"))
717
+ throw new Error("--chant needs the command that runs chant, such as \"npx tsx packages/core/src/cli/main.ts\": --chant <command>");
718
+ }
719
+ else if (arg === "--install") {
720
+ // `chant ci workflow --install <command>` (#3573): a step before the tick that installs what --chant runs.
721
+ result.ciInstall = args[++i];
722
+ if (!result.ciInstall || result.ciInstall.startsWith("-"))
723
+ throw new Error("--install needs the install command, such as \"npm install\": --install <command>");
724
+ }
725
+ else if (arg === "--token-secret") {
726
+ // `chant ci workflow --token-secret <NAME>` (#3573): the secret the tick's tag push authenticates with.
727
+ result.ciTokenSecret = args[++i];
728
+ if (!result.ciTokenSecret || result.ciTokenSecret.startsWith("-"))
729
+ throw new Error("--token-secret needs a repository secret's name, such as CI_GREEN_TOKEN: --token-secret <NAME>");
730
+ }
731
+ else if (arg === "--app-id-var") {
732
+ // `chant ci workflow --app-id-var <VAR> --app-key-secret <NAME>` (#3573): a GitHub App token pushes the tags.
733
+ result.ciAppIdVar = args[++i];
734
+ if (!result.ciAppIdVar || result.ciAppIdVar.startsWith("-"))
735
+ throw new Error("--app-id-var needs the Actions variable holding the App's id: --app-id-var <VAR>");
736
+ }
737
+ else if (arg === "--app-key-secret") {
738
+ result.ciAppKeySecret = args[++i];
739
+ if (!result.ciAppKeySecret || result.ciAppKeySecret.startsWith("-"))
740
+ throw new Error("--app-key-secret needs the secret holding the App's private key: --app-key-secret <NAME>");
741
+ }
742
+ else if (arg === "--verdict") {
743
+ // `chant workspace records review <id> --verdict agree|dissent|abstain` (#2670)
744
+ result.verdict = args[++i];
745
+ if (!result.verdict || result.verdict.startsWith("-"))
746
+ throw new Error("--verdict needs agree, dissent or abstain");
747
+ }
748
+ else if (arg === "--by") {
749
+ // `chant workspace records review <id> --by <principal>` (#2670): whoever the caller says.
750
+ result.by = args[++i];
751
+ if (!result.by || result.by.startsWith("-"))
752
+ throw new Error("--by needs the reviewer: --by <principal>");
753
+ // Repeatable for `workspace points answer` (#2739): each person who answered.
754
+ (result.bys ?? (result.bys = [])).push(result.by);
755
+ }
756
+ else if (arg === "--open") {
757
+ // `chant workspace points --open` (#2739): only the questions still open.
758
+ result.open = true;
759
+ }
760
+ else if (arg === "--inputs") {
761
+ // `chant workspace points ask <point> --inputs <file|-|json>` (#2739; JSON itself, #3403)
762
+ result.inputs = args[++i];
763
+ if (!result.inputs || (result.inputs.startsWith("-") && result.inputs !== "-"))
764
+ throw new Error("--inputs needs a JSON file, - for standard input, or the JSON itself: --inputs <file|-|json>");
765
+ }
766
+ else if (arg === "--candidates") {
767
+ // `chant workspace points ask <point> --candidates <file|-|json>` (#3403): an ad-hoc point's question and candidates.
768
+ result.candidates = args[++i];
769
+ if (!result.candidates || (result.candidates.startsWith("-") && result.candidates !== "-"))
770
+ throw new Error("--candidates needs a JSON file, - for standard input, or the JSON itself: --candidates <file|-|json>");
771
+ }
772
+ else if (arg === "--response") {
773
+ // `chant workspace points ask <point> --response <file>` (#2739): a POST /v1/systemone response the caller got.
774
+ result.response = args[++i];
775
+ if (!result.response || result.response.startsWith("-"))
776
+ throw new Error("--response needs a JSON file: --response <file>");
777
+ }
778
+ else if (arg === "--subject") {
779
+ // `chant workspace points ask <point> --subject <id>` (#2739): what the question is about.
780
+ result.subject = args[++i];
781
+ if (!result.subject || result.subject.startsWith("-"))
782
+ throw new Error("--subject needs what the question is about, such as a work item id: --subject <id>");
783
+ }
784
+ else if (arg === "--store") {
785
+ // `chant workspace points ask <point> --store ledger` (#3815): where a new question goes.
786
+ const store = args[++i];
787
+ if (store !== "tree" && store !== "ledger")
788
+ throw new Error("--store is tree (the answer kind's directory in the working tree) or ledger (chant/lifecycle): --store <tree|ledger>");
789
+ result.store = store;
790
+ }
791
+ else if (arg === "--answer") {
792
+ // `chant workspace points answer <id> --answer <value>` (#2739)
793
+ result.answer = args[++i];
794
+ if (result.answer === undefined || result.answer === "")
795
+ throw new Error("--answer needs one of the question's candidates: --answer <value>");
796
+ }
797
+ else if (arg === "--sign") {
798
+ // `chant workspace records review <id> --sign [<key file>]` (#2687): seal the verdict.
799
+ // `records new` and `records amend` take it too, to seal the record's author (#2688).
800
+ // `chant approve <op> <gate> --sign [<key file>]` seals a gate approval (#3163).
801
+ // With no key file, git's user.signingkey, as `git commit -S` reads it.
802
+ const next = args[i + 1];
803
+ result.sign = next !== undefined && !next.startsWith("-") ? args[++i] : true;
804
+ }
805
+ else if (arg === "--session") {
806
+ // `chant workspace records review <id> --session <id>` (#2670)
807
+ result.session = args[++i];
808
+ if (!result.session || result.session.startsWith("-"))
809
+ throw new Error("--session needs a session id: --session <id>");
810
+ }
811
+ else if (arg === "--prefix") {
812
+ // `chant workspace records new <kind> --prefix <prefix>` (#2670): the id prefix to allocate under.
813
+ result.prefix = args[++i];
814
+ if (!result.prefix || result.prefix.startsWith("-"))
815
+ throw new Error("--prefix needs an id prefix: --prefix <prefix>");
816
+ }
817
+ else if (arg === "--key" || arg === "--check-id" || arg === "--claim" || arg === "--environment" || arg === "--envelope" || arg === "--threshold") {
818
+ // `chant workspace evidence sign|verify` and `chant workspace signers` (#2553)
819
+ const value = args[++i];
820
+ if (value === undefined || value.startsWith("-"))
821
+ throw new Error(`${arg} needs a value`);
822
+ const field = { "--key": "key", "--check-id": "checkId", "--claim": "claim", "--environment": "environment", "--envelope": "envelope", "--threshold": "threshold" }[arg];
823
+ result[field] = value;
824
+ }
825
+ else if (arg === "--require") {
826
+ // `chant workspace records|verify --require attested` (#2547)
827
+ result.require = args[++i];
828
+ if (!result.require || result.require.startsWith("-"))
829
+ throw new Error("--require needs a provenance level: --require attested");
830
+ }
831
+ else if (arg === "--ambient") {
832
+ result.ambient = true;
833
+ }
834
+ else if (arg === "--check-live") {
835
+ result.checkLive = true;
836
+ }
837
+ else if (arg === "--check-snapshot") {
838
+ result.checkSnapshot = true;
839
+ }
840
+ else if (arg === "--fail-on-drift") {
841
+ result.failOnDrift = true;
842
+ }
843
+ else if (arg === "--run-examples") {
844
+ result.runExamples = true;
845
+ }
846
+ else if (arg === "--pinned-digest") {
847
+ result.pinnedDigest = args[++i];
848
+ }
849
+ else if (arg === "--check") {
850
+ result.check = true;
851
+ }
852
+ else if (arg === "--bump") {
853
+ result.bump = true;
854
+ }
855
+ else if (arg === "--component") {
856
+ result.component = args[++i];
857
+ }
858
+ else if (arg === "--digest") {
859
+ result.digest = args[++i];
860
+ if (result.digest !== undefined)
861
+ (result.digests ?? (result.digests = [])).push(result.digest);
862
+ }
863
+ else if (arg === "--release-plan") {
864
+ result.releasePlanFile = args[++i];
865
+ }
866
+ else if (arg === "--git-sha") {
867
+ result.gitSha = args[++i];
868
+ }
869
+ else if (arg === "--run-id") {
870
+ result.runId = args[++i];
871
+ }
872
+ else if (arg === "--actor") {
873
+ result.actor = args[++i];
874
+ }
875
+ else if (arg === "--approver") {
876
+ result.approver = args[++i];
877
+ }
878
+ else if (arg === "--relayed-by") {
879
+ // `chant approve <op> <gate> --relayed-by <principal>` and `workspace points answer <id> --relayed-by <principal>` (#3402):
880
+ // who carried the approval or answer to chant for the person it names.
881
+ result.relayedBy = args[++i];
882
+ if (!result.relayedBy || result.relayedBy.startsWith("-"))
883
+ throw new Error("--relayed-by needs the principal that relayed it: --relayed-by <principal>");
884
+ }
885
+ else if (arg === "--on") {
886
+ // `chant run ... --on <lexicon>` (#2121) — which runtime hosts the run.
887
+ result.on = args[++i];
888
+ if (!result.on || result.on.startsWith("-"))
889
+ throw new Error("--on needs a runtime name: --on <lexicon>");
890
+ }
891
+ else if (arg === "--compare-to") {
892
+ result.compareTo = args[++i];
893
+ }
894
+ else if (arg === "--no-release-record") {
895
+ result.noReleaseRecord = true;
896
+ }
897
+ else if (arg === "--fold") {
898
+ result.fold = true;
899
+ }
900
+ else if (arg === "--no-cache") {
901
+ // `chant workspace graph --no-cache` (#2876): read every member.
902
+ result.noCache = true;
903
+ }
904
+ else if (arg === "--no-fold") {
905
+ // chant #1134 — fold is the default build path; this is the explicit
906
+ // opt-out, and like --fold it beats chant.config.ts's build.fold.
907
+ result.fold = false;
908
+ }
909
+ else if (arg === "--sandbox") {
910
+ result.sandbox = true;
911
+ }
912
+ else if (arg === "--fold-rank") {
913
+ // chant #1083 — same context-sensitive shape as --report above:
914
+ // `--fold-rank` alone prints the ranked-blocker report; `--fold-rank
915
+ // <path>` ALSO writes the Brendan Gregg collapsed-format export there.
916
+ const next = args[i + 1];
917
+ if (next && !next.startsWith("-")) {
918
+ result.foldRankCollapsedFile = next;
919
+ i++;
920
+ }
921
+ else {
922
+ result.foldRank = true;
923
+ }
924
+ }
925
+ else if (arg === "--param") {
926
+ // chant #1118/#1127 — `--param name=value` (space-separated) and
927
+ // `--param=name=value` (joined, split above at its first `=` into flag
928
+ // `--param` + value `name=value`) both land here and behave
929
+ // identically; there is no separate joined-form error anymore (the
930
+ // #1118 hard error this superseded only existed because the parser
931
+ // didn't support joined forms at all — now that it does, the joined
932
+ // form is just as valid as the space-separated one).
933
+ (result.param ?? (result.param = [])).push(args[++i]);
934
+ }
935
+ else if (arg === "--lexicon-output") {
936
+ // `--lexicon-output <lexicon>=<path>` (repeatable); the joined form
937
+ // `--lexicon-output=otel=a.yml` arrives here already split at the first `=`.
938
+ (result.lexiconOutput ?? (result.lexiconOutput = [])).push(args[++i]);
939
+ }
940
+ else if (arg === "--params-file") {
941
+ result.paramsFile = args[++i];
942
+ }
943
+ else if (arg === "--projection") {
944
+ result.projection = args[++i];
945
+ }
946
+ else if (arg === "--interval") {
947
+ result.interval = args[++i];
948
+ }
949
+ else if (arg === "--lease-ttl") {
950
+ result.leaseTtl = args[++i];
951
+ }
952
+ else if (arg === "--steward") {
953
+ // #2731 — the name is optional: a project with one steward runs it
954
+ // with a bare `--steward`.
955
+ const next = args[i + 1];
956
+ if (next !== undefined && !next.startsWith("-")) {
957
+ result.steward = next;
958
+ i++;
959
+ }
960
+ else {
961
+ result.steward = "";
962
+ }
963
+ }
964
+ else if (arg === "--once") {
965
+ result.once = true;
966
+ }
967
+ else if (arg === "--work") {
968
+ // `chant run <op> --work <id>` (#2748)
969
+ const value = args[++i];
970
+ if (!value || value.startsWith("-"))
971
+ throw new Error("--work needs a work item id: --work <id>");
972
+ result.work = value;
973
+ }
974
+ else if (arg === "--holder" || arg === "--ttl" || arg === "--token" || arg === "--outcome") {
975
+ // `chant workspace work claim|renew|release <id>` (#2732)
976
+ const value = args[++i];
977
+ if (!value || value.startsWith("-"))
978
+ throw new Error(`${arg} needs a value: ${arg} <${arg.slice(2)}>`);
979
+ result[arg.slice(2)] = value;
980
+ }
981
+ else if (arg === "--signer") {
982
+ // `chant workspace runs statement <id> --signer <principal>` (#3192): the runner principal that will sign.
983
+ const value = args[++i];
984
+ if (!value || value.startsWith("-"))
985
+ throw new Error("--signer needs a principal: --signer <principal>");
986
+ result.signer = value;
987
+ }
988
+ else if (arg === "--unit" || arg === "--decision") {
989
+ // `chant workspace runs --unit <id> | --decision <id>` (#3033): the runs on one work item, or for one decision.
990
+ const value = args[++i];
991
+ if (!value || value.startsWith("-"))
992
+ throw new Error(`${arg} needs an id: ${arg} <id>`);
993
+ result[arg.slice(2)] = value;
994
+ }
995
+ else if (arg === "--note") {
996
+ result.note = args[++i];
997
+ }
998
+ else if (arg === "--reason") {
999
+ // `chant approve policy-override <subject> --reason <text>` (#3760): why the denied plan goes out anyway.
1000
+ result.reason = args[++i];
1001
+ if (result.reason === undefined || result.reason.startsWith("-"))
1002
+ throw new Error("--reason needs the text of the reason: --reason <text>");
1003
+ }
1004
+ else if (arg === "--rule") {
1005
+ // `chant approve policy-override <subject> --rule <id>` (#3760), once per rule that denied the plan.
1006
+ const value = args[++i];
1007
+ if (!value || value.startsWith("-"))
1008
+ throw new Error("--rule needs a rule id: --rule <id>");
1009
+ (result.rules ?? (result.rules = [])).push(value);
1010
+ }
1011
+ else if (arg === "--expire") {
1012
+ result.expire = true;
1013
+ }
1014
+ else if (arg === "--role") {
1015
+ // #2508 — a role the approver holds, for a gate whose quorum names
1016
+ // roles. Repeatable, and a comma list works too.
1017
+ const value = args[++i] ?? "";
1018
+ result.roles = [...(result.roles ?? []), ...value.split(",").map((r) => r.trim()).filter(Boolean)];
1019
+ }
1020
+ else if (arg === "--agent") {
1021
+ // #2508 — record the approval as an agent's rather than a person's.
1022
+ result.agent = true;
1023
+ }
1024
+ else if (arg === "--allow-code") {
1025
+ // #2550 — `chant workspace upgrade` runs a template's code migrations
1026
+ // only when asked to.
1027
+ result.allowCode = true;
1028
+ }
1029
+ else if (arg === "--source") {
1030
+ // #2551 — `chant workspace upgrade --source <repo>[#<member>]`.
1031
+ result.source = args[++i];
1032
+ if (!result.source || result.source.startsWith("-"))
1033
+ throw new Error("--source needs a template: --source <repo>[#<member>]");
1034
+ }
1035
+ else if (arg === "--tags") {
1036
+ // #2551 — `chant workspace adopt-lineage --tags <glob>`, also hash-index and versions.
1037
+ result.tags = args[++i];
1038
+ if (!result.tags || result.tags.startsWith("-"))
1039
+ throw new Error("--tags needs a tag glob: --tags 'v*'");
1040
+ }
1041
+ else if (arg === "--index") {
1042
+ // #2551 — `chant workspace adopt-lineage --index <file>`.
1043
+ result.index = args[++i];
1044
+ if (!result.index || result.index.startsWith("-"))
1045
+ throw new Error("--index needs a hash index file: --index <file>");
1046
+ }
1047
+ else if (arg === "--remove") {
1048
+ // #2552 — `chant workspace import --remove` removes the export member instead of writing it again.
1049
+ result.remove = true;
1050
+ }
1051
+ else if (arg === "--available") {
1052
+ // #2551 — `chant workspace versions --available` lists the template's version tags.
1053
+ result.available = true;
1054
+ }
1055
+ else if (arg === "--root-only") {
1056
+ // #2537 — `chant build` and `chant lint` at a declared workspace root
1057
+ // run on the root project alone instead of refusing with WSP000.
1058
+ result.rootOnly = true;
1059
+ }
1060
+ else if (arg === "--generated") {
1061
+ // #2641 — `chant workspace check --generated` runs each declared
1062
+ // generator and compares its output with the file in the tree.
1063
+ result.generated = true;
1064
+ }
1065
+ else if (arg === "--member") {
1066
+ // #2537 — `chant workspace build|lint|audit|graph --member <name>`.
1067
+ // Repeatable, and a comma list works too.
1068
+ const value = args[++i];
1069
+ if (!value || value.startsWith("-"))
1070
+ throw new Error("--member needs a member or group name: --member <name>");
1071
+ result.members = [...(result.members ?? []), ...value.split(",").map((m) => m.trim()).filter(Boolean)];
1072
+ }
1073
+ else if (arg === "--allow-same-origin") {
1074
+ // chant#2384 — record a resolution the same-origin rule would refuse,
1075
+ // deliberately. Flagged on the record, not just accepted quietly.
1076
+ result.allowSameOrigin = true;
1077
+ }
1078
+ else if (arg === "--plan") {
1079
+ result.plan = args[++i];
1080
+ }
1081
+ else if (arg === "--url") {
1082
+ result.url = args[++i];
1083
+ }
1084
+ else if (arg === "--op") {
1085
+ result.op = args[++i];
1086
+ }
1087
+ else if (arg === "--since") {
1088
+ result.since = args[++i];
1089
+ }
1090
+ else if (arg === "--limit") {
1091
+ // Parsed here, validated by the handler — `parseArgs` reports shape, not
1092
+ // policy, the same split every other value flag here uses.
1093
+ result.limit = Number(args[++i]);
1094
+ }
1095
+ else if (arg.startsWith("--")) {
1096
+ // chant #1127 — every recognized flag is matched above; anything left
1097
+ // starting with `--` is unrecognized, whether it arrived bare
1098
+ // (`--bogus`) or joined (`--bogus=value`, already split into
1099
+ // `--bogus` + `value` above). This used to fall through silently (the
1100
+ // "ignores unknown flags" case) — a typo'd or misremembered flag would
1101
+ // vanish with no diagnostic, exactly like the silent-drop this issue
1102
+ // closes for joined values. Point at --help rather than enumerating
1103
+ // every flag here: this parser's flag set is one flat list shared by
1104
+ // every command, not scoped per-command, so "the command's known
1105
+ // flags" isn't something this loop can name in isolation.
1106
+ throw new Error(`Unknown flag: ${arg}\nRun "chant --help" to see supported flags.`);
1107
+ }
1108
+ else if (!arg.startsWith("-")) {
1109
+ if (result.command)
1110
+ (result.positionals ?? (result.positionals = [])).push(arg);
1111
+ if (!result.command) {
1112
+ result.command = arg;
1113
+ }
1114
+ else if (result.path === ".") {
1115
+ result.path = arg;
1116
+ }
1117
+ else if (!result.extraPositional) {
1118
+ result.extraPositional = arg;
1119
+ }
1120
+ else {
1121
+ result.extraPositional2 = arg;
1122
+ }
1123
+ }
1124
+ i++;
1125
+ }
1126
+ // #2603 — `--promote-to` (#2575) adds a job to the pipeline that generate
1127
+ // mode synthesizes; no other command or mode reads it. Checked here, once
1128
+ // the whole command line is known, rather than in the build handler, so
1129
+ // `chant build --promote-to prod` and `chant run --promote-to prod` both
1130
+ // fail instead of running as if the flag were absent. A lexicon-mounted
1131
+ // command that takes its own `--promote-to` still gets it: `main` tries the
1132
+ // plugin commands before rethrowing a parse error.
1133
+ if (result.promoteTo && !(result.command === "build" && result.components && result.generate)) {
1134
+ throw new Error("--promote-to needs build --components --generate <lexicon>: it adds a promote job to the generated CI pipeline, and only generate mode emits one.");
1135
+ }
1136
+ return result;
1137
+ }
1138
+ /**
1139
+ * Print help message. `groups` — lexicon-contributed command groups
1140
+ * (chant #1078), best-effort loaded from the current project; composed in
1141
+ * below the static command list so `--help` lists every mounted verb group
1142
+ * alongside core's own commands.
1143
+ */
1144
+ function printHelp(groups = []) {
1145
+ console.log(`
1146
+ chant - Declarative infrastructure specification toolkit
1147
+
1148
+ Usage:
1149
+ chant <command> [options] [path]
1150
+
1151
+ Commands:
1152
+ init Initialize a new chant project
1153
+ (--from <repo>@<ref>[#<member>] copies a template
1154
+ repository and records its lineage, and --from
1155
+ <dir>[#<member>] copies a template directory on
1156
+ disk; --param
1157
+ <name>=<value> sets a parameter the template's
1158
+ chant.template.json declares, repeatable)
1159
+ init lexicon <name> Scaffold a new lexicon plugin project
1160
+ build Build infrastructure from specification files
1161
+ (--components --generate github|gitlab|forgejo:
1162
+ generate mode (#563), which synthesizes a thin CI
1163
+ pipeline that triggers each discovered component's
1164
+ own deploy in wave order, instead of a normal
1165
+ lexicon build)
1166
+ At a declared workspace root it refuses with WSP000;
1167
+ --root-only builds the root project alone
1168
+ lint Check specifications for issues
1169
+ (at a declared workspace root: WSP000 unless --root-only)
1170
+ list List discovered entities
1171
+ describe Show the effective config for one component
1172
+ explain Summarize discovered entities (--format markdown|json|okf;
1173
+ okf emits an OKF v0.2 knowledge bundle — one markdown
1174
+ concept per entity + index.md; -o <dir> writes the
1175
+ bundle tree, otherwise JSON path→content on stdout)
1176
+ generate Generate typed code from sources chant.config declares
1177
+ (k8s.crds, helm.charts) into src/generated/<lexicon>/
1178
+ (codegen.outDir); --check exits 1 when the committed
1179
+ output no longer matches its sources, as build does
1180
+ vendor Pull pinned, checksummed patterns into your repo
1181
+ (pull [name] | check | migrate; migrate moves
1182
+ vendor.json into .chant/workspace.lock.json)
1183
+ import Import external template into TypeScript
1184
+ (--agents re-expresses this machine's agent config as
1185
+ chant code instead of reading a template file)
1186
+ audit [path|url] Audit a repo's CI YAML for security issues
1187
+ (--format stylish|json|sarif|markdown|html, -o <file>,
1188
+ --tier merge-worthy|all, --fail-on merge-worthy|warning|error|none,
1189
+ --template <file> / --theme <file> for the html report,
1190
+ --max-files <n> to walk more than 1000 files)
1191
+ --agents audits this machine's agent configuration —
1192
+ instruction files, MCP servers, skills, plugins,
1193
+ permissions — instead of a repository
1194
+ (--scope system,user,project, --runtime claude,codex,...,
1195
+ --all-projects)
1196
+ migrate <file> Translate a workflow between lexicons
1197
+ (default: --from github --to gitlab)
1198
+ carve advise Read-only peelability advisor: rank which resources
1199
+ --from <dir> are cheap to carve into native chant
1200
+ (--json, --report <path>). Emits nothing, changes nothing.
1201
+ --from a Terraform dir needs @cdktn/hcl2json
1202
+ (npm install -D @cdktn/hcl2json); --from a CDK cloud
1203
+ assembly (cdk.out) needs nothing and ranks constructs.
1204
+ carve emit Adopt a selected TF resource into chant source + report
1205
+ --from <tf-dir> its boundary. --state <tfstate> adopts offline
1206
+ --select <addr> (recommended for TF-managed resources); --env
1207
+ --state|--env <env> adopts via live cloud import (--live-name
1208
+ <logical-id> narrows a multi-resource stack).
1209
+ Persists a carve manifest bridge/apply compose
1210
+ with; scaffolds the output dir into a buildable
1211
+ chant project (src/ + config + package.json).
1212
+ carve bridge Generate the surviving-TF patch (data sources + rewired
1213
+ --from <tf-dir> refs) + deferred inputs + reversible runbook,
1214
+ [--select <addr>] plus one git-applyable .patch for the whole
1215
+ edit. Writes proposals for review;
1216
+ --apply-rewrites edits the .tf in place.
1217
+ --select is optional when the output dir
1218
+ holds one carve manifest.
1219
+ carve apply Apply graduation: ownership marker + finalized apply
1220
+ --from <tf-dir> runbook (dial-turn observe→apply). BYOL —
1221
+ [--select <addr>] no cloud call; --write saves the doc. --select
1222
+ --env <env> is optional with a carve manifest present.
1223
+ --write-source stamps the ownership marker
1224
+ into the emitted chant source.
1225
+ carve status Status read over a tree of carve manifests: every
1226
+ [--from <dir>] *.carve.json under --from (default: cwd) with
1227
+ (--json) its target, stage (planned/emitted/bridged/
1228
+ applied) and path. Read-only.
1229
+
1230
+ CI:
1231
+ ci last-green [--json] The newest first-parent commit of ci.green's branch
1232
+ with a ci/green tag and no ci/revoked tag. Reads local
1233
+ tags only; fetch them first.
1234
+ ci tick [--dry-run] [--forge github] Tag each commit within ci.green's
1235
+ window whose required phases all passed ci/green/<sha>,
1236
+ and revoke a green one that now fails ci/revoked/<sha>.
1237
+ Reads check runs from the forge, pushes the tags.
1238
+ ci workflow [--workflow <name>]... [--output <file>] Write
1239
+ [--chant <command>] [--install <command>]
1240
+ [--token-secret <NAME> | --app-id-var <VAR> --app-key-secret <NAME>]
1241
+ .github/workflows/chant-ci-green.yml, which runs the
1242
+ tick when a required workflow completes and every 15m.
1243
+ --chant replaces the npx @intentius/chant pin the tick
1244
+ runs; --install adds a step before it. --token-secret,
1245
+ or a GitHub App's id and key, pushes the tags with a
1246
+ token that may tag commits changing workflow files.
1247
+
1248
+ Change sets:
1249
+ change-set summary <file> The grouped plan summary of a change-set
1250
+ [--format text|json|markdown] document: members taking
1251
+ [--limit <chars>] the same change grouped, every destroy,
1252
+ replacement, failure and hole named.
1253
+ markdown fits an MR/PR note of --limit
1254
+ characters (default 65536). Read-only.
1255
+
1256
+ Ops:
1257
+ run <name> Run an Op on the resolved runtime (--on; local by default)
1258
+ [--work <id>] [--holder <name>]: the work item an Op
1259
+ with a work lease runs under, and who holds it
1260
+ --fail-on-drift: exit 2 when the run completes and
1261
+ its Drift outcome is true (WatchOp failOn: "drift")
1262
+ run list List all Ops with the runtime's state for each
1263
+ run status <name> Show the runtime's state for one Op's latest run
1264
+ run approve <op> <gate> Record a gate's resolution and wake the runtime
1265
+ run cancel <name> Cancel the active run (requires --force)
1266
+ run log <name> Show run history for an Op
1267
+ run wave --spec <file> --wave <k> Plan, gate and apply wave k of an Op
1268
+ waves spec (#3679): the job a generated waves
1269
+ pipeline runs. --decide plans and decides only;
1270
+ --share <i> applies one share of a decided wave.
1271
+ --record-plans (no --wave), in a pull request's
1272
+ pipeline: plan every wave at its head and record the
1273
+ digests a pr-review approval mode compares
1274
+ run resume [--op <name>] [--gate <name>] Start again each CI job that
1275
+ waits at a gate an approval now answers, through the
1276
+ forge's API (#3683); approves nothing. --gate resumes
1277
+ that gate's job alone (#3854). Skips an approval a
1278
+ wave already applied under; restarts an apply that
1279
+ stopped once its run is gone (#3858). --dry-run
1280
+ starts nothing; with --json it says per gate whether
1281
+ it would resume and why
1282
+ run --generate <provider> Write one CI pipeline file per scheduled Op for
1283
+ github, gitlab or forgejo (#2533), from every Op that
1284
+ declares a schedule or from --spec <file.json>.
1285
+ Files go to the forge's own directory unless
1286
+ --output <dir>; --format json prints them instead
1287
+ run --components <name|all> Run discovered Component(s) through the interpret
1288
+ driver on the local executor (--env <env>; #585).
1289
+ On success, auto-emits a release-ledger record per
1290
+ component that published a digest (default: on;
1291
+ --no-release-record to opt out; #597)
1292
+ --progress-json: stream one NDJSON RunProgressEvent
1293
+ per line to stdout while the run executes, for a
1294
+ consumer to render live wave/component/phase/step
1295
+ progress instead of tailing raw logs (additive; run
1296
+ semantics/exit code unchanged)
1297
+ operator Run scheduled ticks for discovered ConvergeOps
1298
+ locally (#1485): acquire/renew a per-op
1299
+ lease (git ref CAS), tick on --interval, record every
1300
+ result as a ledger fact. --env <env> scopes to one
1301
+ environment; --interval <dur> (default 60s) and
1302
+ --lease-ttl <dur> (default 5m) tune cadence; --once
1303
+ runs a single round and exits (cron/systemd-timer/
1304
+ CronJob invokers use this instead of the daemon).
1305
+ --steward [<name>] runs a declared steward's local
1306
+ form instead (#2731): its scheduled Ops on their
1307
+ crons, under the steward's own lease, and its
1308
+ beside Ops as chant run processes of their own
1309
+ (#2861)
1310
+ operator status Last tick, outcomes, and pending gates per
1311
+ ConvergeOp, read from the chant/lifecycle orphan
1312
+ branch alone — no daemon needs to be running
1313
+ (--env <env>, --json)
1314
+ operator log Converge tick history and the gate resolutions
1315
+ against it, merged into one timestamp-ordered
1316
+ timeline, from the same orphan branch (--env <env>,
1317
+ --op <name>, --since <iso>, --limit <n>, --json).
1318
+ --json also carries the count of ledger lines that
1319
+ were unreadable, so a short timeline is never
1320
+ silently short
1321
+ approve <op> <gate> Record a gate's out-of-band resolution fact
1322
+ (--actor <name>, --note <text>, --url <url>) — the
1323
+ durable counterpart to the pending fact a run records
1324
+ when it reaches the gate; see the pending-gates list
1325
+ in operator status. --url is the PR/MR the resolution
1326
+ happened at, recorded typed rather than as free text,
1327
+ and defaults to the PR/MR of the surrounding CI job.
1328
+ The next "chant run <op>" walks through the gate.
1329
+ --expire clears a pending fact without approving it,
1330
+ so the gate is re-decided from scratch next run.
1331
+ --sign [<key file>] seals the approval with an ssh
1332
+ key; a gate the workspace's identity.gates names
1333
+ counts only an approval sealed by a key the signers
1334
+ file at base lists for --actor. --relayed-by
1335
+ <principal> records who carried the approval to chant
1336
+ for --actor (a follower, a bot); --sign covers it.
1337
+ --resume then starts the CI job that waits at the
1338
+ gate again (GitHub re-run, GitLab retry, Forgejo
1339
+ dispatch) with CHANT_FORGE_TOKEN
1340
+ On op policy-override the gate is the subject a
1341
+ policy denied: --rule <id> names each rule that
1342
+ denied it and --reason <text> says why the plan goes
1343
+ out anyway; the next run that plans the same digest
1344
+ applies it once, if .chant/overriders at base lists
1345
+ --actor
1346
+
1347
+ graph Show Op dependency graph (--stacks for cross-stack order,
1348
+ --format ir|mermaid|dot|layout for the lint-gated graph IR,
1349
+ a Mermaid flowchart, Graphviz DOT, or node positions;
1350
+ layout uses dagre by default (no native dep) — pass
1351
+ --node-sizes <json|-|@file> for size-aware spacing,
1352
+ --layout-engine graphviz to use dot instead;
1353
+ --detail 0..3: stacks|composites|declarables|attributes;
1354
+ --lens lexicon:<n>|stack:<n>|blast:<node> (--up/--down))
1355
+ --components --format ir --projection gitlab|github|forgejo:
1356
+ add the CI/pipeline projection (stages/jobs/needs) to
1357
+ the component-graph IR, from the same generator
1358
+ 'build --components --generate' uses (#989)
1359
+ --traffic "<level>": ask the project's predicting
1360
+ lexicon what the estate does at that traffic level, and
1361
+ carry each entity's prediction on the IR. On the
1362
+ declared graph it predicts the file; with --live it
1363
+ predicts the account. The level reaches the engine
1364
+ verbatim; without the flag nothing is asked (#2377)
1365
+
1366
+ Workspace (level 1, #2524):
1367
+ workspace init [dir] Propose a chant.workspace.json from the projects and
1368
+ packages already in the repository, print it with the
1369
+ directories that would leave the root project, and
1370
+ write it only on confirmation (--yes writes without
1371
+ asking; --name <name> names the workspace; --verbose
1372
+ lists every file leaving the root project)
1373
+ workspace ls [dir] List the declaration's members and example groups.
1374
+ A member that can't be read is listed with a reason
1375
+ code and still exits 0. --at <rev> reads a commit's
1376
+ git objects; --json prints the read-contract document
1377
+ workspace status <env> [dir] [--compare-to <env>] [--json]
1378
+ Each member's latest release in <env>, as digest and
1379
+ git SHA, read from its ledger on the local
1380
+ chant/lifecycle branch (_members/<member>/ or the flat
1381
+ layout). --compare-to <env> shows a second environment
1382
+ beside it and marks the members whose digests differ.
1383
+ Read only; never fetches. --json prints the
1384
+ read-contract document
1385
+ workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--json]
1386
+ Without --kind, every record kind the declaration
1387
+ names. Read the records a record kind locates, validated
1388
+ against its schema, with reason codes for invalid
1389
+ ones. --current leaves out superseded records; --at
1390
+ reads a commit's git objects. Needs no workspace file.
1391
+ Each record reports its provenance level, judged by
1392
+ the signers at --base (default: the target branch);
1393
+ --require attested exits 2 if any record is not
1394
+ attested. A pinned file that changed is a warning,
1395
+ asset-drift or asset-missing. In the working tree,
1396
+ each record says whether it is committed, modified
1397
+ or new against HEAD, with the branch and base;
1398
+ --uncommitted lists only the modified and new ones
1399
+ workspace records [--kind <kind file>] --since <rev|session id> [--at <rev>] [--json]
1400
+ What changed in the records between <rev> and --at
1401
+ (default: the working tree): new and removed records,
1402
+ state transitions, new verdicts, new supersessions
1403
+ and changed pins. A session id compares the commits
1404
+ the session opened and closed at
1405
+ workspace records pin <path>
1406
+ Print the path from the workspace root and the
1407
+ sha256 of a file, for a decision's evidence pin
1408
+ workspace records new [<kind file>] --from <file|-> [--prefix <prefix>] [--sign [<key file>]] [--dry-run]
1409
+ Write one new record in the kind's directory from
1410
+ the JSON fields given, after validating them as
1411
+ records would read them. Without a kind file, the one
1412
+ kind the declaration names. Allocates the next id when
1413
+ the fields hold none. --sign seals the record's author
1414
+ (decided_by for decisions) with an ssh key. Prints
1415
+ {path, id} as JSON and never commits
1416
+ workspace records amend <id> [--kind <kind file>] --set <file|-> [--expect <digest>] [--sign [<key file>]] [--dry-run]
1417
+ Set top-level fields of one record. A closed record
1418
+ never changes, and an approved one changes only its
1419
+ state (upward), pins and reviews; anything else is
1420
+ refused with amend-supersede-instead. Moving a
1421
+ record to its kind's ratified state (ratified for
1422
+ decisions) is refused with ratify-quorum-not-met
1423
+ until its quorum is met. --sign seals the author
1424
+ again; without it an amendment removes the author
1425
+ seal and says so. --expect refuses the write with
1426
+ record-conflict when the record's digest has moved
1427
+ on. Prints {path, id, changed, digest}
1428
+ workspace records review <id> [--kind <kind file>] --verdict agree|dissent|abstain --by <principal> [--note <text>] [--session <id>] [--expect <digest>] [--sign [<key file>]] [--dry-run]
1429
+ Append a review to one record, dated and bound to
1430
+ the digest of the record text. A dissent needs
1431
+ --note. --sign seals it with an ssh key (git's
1432
+ user.signingkey without a file); under a signers
1433
+ file at base only a sealed verdict counts. With
1434
+ --session, the session must be open, and the verdict
1435
+ is appended to its verdicts too. --expect refuses a
1436
+ verdict on a record that moved on. Prints
1437
+ {path, id, review, digest}
1438
+ workspace records close <session id> [--kind <session kind file>] [--expect <digest>] [--dry-run]
1439
+ Close an open review session: its state, close time,
1440
+ closing commit and seal, in one write. Without
1441
+ --kind, the one session kind the declaration names.
1442
+ Prints {path, id, changed, seal, closedRev}
1443
+ Every working-tree write holds the working tree's
1444
+ write lock (CHANT_WRITE_LOCK_WAIT_MS, default 15s)
1445
+ workspace lock [acquire --holder <name> [--ttl <duration>] | release --token <token>] [--json]
1446
+ Who holds the working tree's write lock; take it for
1447
+ a batch of writes across chant calls, each run with
1448
+ CHANT_WRITE_LOCK=<token>, and give it back
1449
+ workspace work claim|renew|release <id> --holder <name> [--kind <kind file>] [--ttl <seconds|duration>] [--token <token>] [--outcome <outcome>] [--note <text>] [--json]
1450
+ Take, heartbeat or give back the lease on a work item:
1451
+ refs/chant/lease/work/<id>, a compare-and-set ref with a
1452
+ fencing token and an expiry, pushed to the remote so
1453
+ separate clones coordinate. A claim is refused, exit 2,
1454
+ while anyone holds it live. Each change appends to
1455
+ _leases/<id>.jsonl on chant/lifecycle
1456
+ workspace work history <id> [--kind <kind file>] [--json]
1457
+ A work item's lease history: each claim with its token
1458
+ and holder, and how it ended, released with an outcome
1459
+ or never released (expired or lost). Read-only
1460
+ workspace work evidence <id> --holder <name> --token <token> --from <file|-> [--kind <kind file>]
1461
+ Attach evidence for one acceptance criterion under the
1462
+ lease you hold: the entry (criterion, result, title,
1463
+ a url or a path pinned by hash) is appended to the
1464
+ item's pins through records amend. Prints the
1465
+ work-evidence document and never commits
1466
+ workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--follow-squash] [--json]
1467
+ The agent runs in the run ledger on chant/lifecycle, each
1468
+ with its model, tokens, cost and the commits it made,
1469
+ and totals per work item, decision and principal; a run
1470
+ that reports no cost is listed as unpriced, never zero.
1471
+ Read-only, never fetches; --follow-squash joins each
1472
+ squash merge to its pull request's runs, fetching a
1473
+ missing refs/pull/<n>/head from origin
1474
+ workspace runs start --from <file|->
1475
+ Record that an agent run started: who it worked for,
1476
+ its harness, model, work item and lease. Prints the run
1477
+ and its Chant-Run trailer. chant never starts a run
1478
+ workspace runs end <run id> [--from <file|->]
1479
+ Record how a started run ended: its outcome, tokens,
1480
+ cost and price source, the transcript pinned by hash,
1481
+ and the commits it made
1482
+ workspace runs record --from <file|->
1483
+ Record a finished run, its start and end in one write
1484
+ workspace runs sign <run id> (--key <runner.pem> | --envelope <file|->) [--base <rev>]
1485
+ Store a DSSE statement over an ended run (its record's
1486
+ hash, work item, harness, model and commits), signed
1487
+ with a runner or steward key .chant/trust.json lists
1488
+ at base, or signed elsewhere and checked here
1489
+ workspace runs statement <run id> --signer <principal>
1490
+ Print the statement for a signer whose key is
1491
+ elsewhere, such as a lobby, with the payload to sign
1492
+ workspace runs verify [<run id>] [--require signed] [--base <rev>] [--json]
1493
+ Judge each run's stored statements against the runner
1494
+ keys at base. Reports only, unless --require signed
1495
+ workspace box listing set <member> [--from <file|->] [--cover <image> [--cover-path <path>]] [--by <principal>] [--dry-run]
1496
+ Change a box's listing (published, title, line, cover)
1497
+ in the declaration, in place, keeping its formatting
1498
+ and comments; --cover copies a PNG, JPEG or WebP into
1499
+ the repository. Judged by the write scope at base.
1500
+ Prints the box-listing-write document; never commits
1501
+ workspace member add <name> --from <file|-> [--by <principal>] [--dry-run]
1502
+ workspace member remove <name> [--by <principal>] [--dry-run]
1503
+ workspace host set <name> --from <file|-> [--by <principal>] [--dry-run]
1504
+ Add or remove a member's entry, or add or replace a
1505
+ host's, in the declaration, in place, keeping its
1506
+ formatting and comments. Refuses a declaration that
1507
+ doesn't read, or two boxes sharing a port. Judged by
1508
+ the write scope at base. Prints the member-write
1509
+ document; never commits
1510
+ workspace box factory set <member> --from <file|-> [--by <principal>] [--dry-run]
1511
+ Change a box's factory (builds, check, checks,
1512
+ builders, tiers, publish) in the declaration, in
1513
+ place, such as where a planted box publishes. Judged
1514
+ by the write scope at base. Prints the
1515
+ box-factory-write document; never commits
1516
+ workspace box publish <member> (<item> | --records) [--by <principal>] [--head <owner/name>] [--dry-run]
1517
+ Publish a built work item, or the records kept
1518
+ uncommitted, through the publisher the box block names:
1519
+ run with a JSON request on stdin, its answer checked
1520
+ and its commit held to the apply record (ws-088).
1521
+ Prints the box-publish document; chant itself never
1522
+ commits, pushes or calls a forge
1523
+ workspace wip [--branch <branch>] [--json]
1524
+ List the work-in-progress snapshots under
1525
+ refs/chant/wip/<branch>, newest first, and how far each
1526
+ ref the box's replicate policy names is from its remote.
1527
+ Reads locally; never fetches (#3172)
1528
+ workspace wip save [--label <text>] [--by <principal>]
1529
+ Snapshot the whole working tree, uncommitted records
1530
+ included, onto refs/chant/wip/<branch> without touching
1531
+ the index or the branch; pushes when the policy says so
1532
+ workspace wip restore [<snapshot>] [--by <principal>]
1533
+ Put the working tree back as the snapshot (the branch's
1534
+ latest by default) holds it, after a snapshot of how it
1535
+ is now; HEAD never moves
1536
+ workspace wip push Push the refs the box's replicate policy names to its
1537
+ remote, never forced, for the host's schedule
1538
+ workspace wip fetch On a replacement box, bring back what was replicated:
1539
+ create or fast-forward the local refs, then wip restore
1540
+ workspace points [--open] [--kind <kind file>] [--at <rev>] [--json]
1541
+ List the decision points the declared answer kinds'
1542
+ points files declare, and the questions asked of them;
1543
+ --open keeps the escalated and proposed ones (ws-058)
1544
+ workspace points ask <point> --inputs <file|-|json> [--candidates <file|-|json>] [--response <file>] [--subject <id>] [--store <tree|ledger>] [--kind <kind file>] [--dry-run]
1545
+ Ask a point's table, model and quorum deciders and
1546
+ record the answer: proposed from a model, escalated to
1547
+ people below its threshold. --response is a POST
1548
+ /v1/systemone response the caller got; chant calls no model.
1549
+ --candidates gives an ad-hoc point's question and
1550
+ candidates, { question, criteria }. --store ledger
1551
+ holds the question on chant/lifecycle and pushes it,
1552
+ for a checkout that does not outlive the run (CI)
1553
+ workspace points answer <id> --answer <value> --by <name>... [--note <text>] [--relayed-by <principal>] [--kind <kind file>] [--resume] [--dry-run]
1554
+ Record people's answer to an open question, or confirm
1555
+ a model's proposal, once the point's quorum is met,
1556
+ with their note and who relayed it. --resume then
1557
+ starts again the CI job waiting at the gate the
1558
+ question names, when the answer passes it
1559
+ workspace points retract <id> --by <name>... [--note <text>] [--kind <kind file>] [--dry-run]
1560
+ Take an answer back: the question is open for people
1561
+ again, and the answer stays in its retractions
1562
+ workspace pin <path> [--json]
1563
+ Print the integrity value that pins the plugin at
1564
+ <path>, to put in a path pin of chant.workspace.json.
1565
+ chant checks it before it reads the plugin
1566
+ workspace agent [<name>] [--json]
1567
+ Print an agent session from the declaration: the one
1568
+ member it is bound to, the record kinds and verbs its
1569
+ write scope allows, and the spec records --current
1570
+ prints. Without a name, the session CHANT_AGENT names
1571
+ workspace verify [--base <rev>] [--head <rev>] [--require attested | attested-runs]
1572
+ Check the commits in base..head against the signers
1573
+ and roles read from base. A change to the signers file
1574
+ or .chant/trust.json needs a signature by a signer
1575
+ trusted at base, and a new signer set needs a
1576
+ threshold of the old one. A commit an agent run made
1577
+ is attested by the run's signed statement; with
1578
+ attested-runs, only those commits must be
1579
+ workspace signers [--json] [rotate [--threshold <n>] | sign --key <file>]
1580
+ Show the signer history at base, or propose the next
1581
+ signer set and sign it with a current signer's key
1582
+ workspace evidence sign --kind <kind file> --key <runner.pem> --check-id <id>
1583
+ Sign runner evidence over the records' hashes in a
1584
+ DSSE envelope, with a runner key .chant/trust.json
1585
+ lists. For CI and services, never a person's key
1586
+ workspace evidence verify --envelope <file> [--at <rev>] [--json]
1587
+ Verify runner evidence offline, and whether the
1588
+ records it covers are unchanged
1589
+ workspace lineage [--json]
1590
+ Show each scope in .chant/workspace.lock.json: its
1591
+ template and pin, locally edited files and open
1592
+ manual steps. Needs no workspace file
1593
+ workspace lineage resolve <path>
1594
+ Close a manual step once the file is merged by hand
1595
+ workspace upgrade [<scope>] [--to <ref|dir>] [--source <repo>[#<member>]] [--allow-code] [--dry-run] [--output <file>]
1596
+ Bring a lineage scope to a newer template version: fetch
1597
+ it, migrate and merge per file in a worktree, run build,
1598
+ lint and workspace check there, then gate on the digest
1599
+ of the patch (chant approve workspace-upgrade <scope>).
1600
+ A second run with the approval applies the patch.
1601
+ --source <repo>[#<member>] moves the scope to another
1602
+ template through that template's bridge migration
1603
+ workspace adopt-lineage [<scope>] --from <repo>[@<ref>][#<member>] [--tags <glob>]
1604
+ [--index <file>] [--param name=value] [--dry-run] [--json]
1605
+ Give a scope a git lineage: match a scope with none
1606
+ against the template's versions and record the best
1607
+ one, with the adopted commit range in .chant/trust.json,
1608
+ or move a directory lineage onto the version that
1609
+ reproduces its recorded files
1610
+ workspace hash-index --from <repo>[#<member>] [--tags <glob>] [--output <file>]
1611
+ Compute the per-version file hashes adopt-lineage
1612
+ matches against, for a template's CI to publish
1613
+ workspace versions [<dir>] [--template <id>] [--available [--tags <glob>]] [--json]
1614
+ Report the template, chant and lexicon versions of
1615
+ every lineage lock under <dir>, grouped into families
1616
+ by template; --available also lists each git
1617
+ template's version tags and where each lock sits
1618
+ workspace export [<member>[,<member>...]] [--to <member>] [--param name=value] [--dry-run] [--json]
1619
+ Write members that set travel, with their lineage and
1620
+ records, into the export member (role export) as a
1621
+ workspace of their own; with no member named, every
1622
+ member that travels and the workspace's own records.
1623
+ --param gives a host-bound parameter its value there
1624
+ workspace import [<dir>] [--remove] [--dry-run] [--json]
1625
+ Bring an export back: merge per file against the
1626
+ export's hashes, switch host values back, record the
1627
+ return in .chant/returns/<id>.json with the commits the
1628
+ files were made in, then write the export member again
1629
+ or, with --remove, remove it
1630
+ workspace admit <return id> [--note <text>] [--dry-run] [--json]
1631
+ Admit the signers of a return in .chant/trust.json, so
1632
+ its signed work reads as attested once merged
1633
+ workspace check [--at <rev>] [--json] [--format stylish|json|sarif] [--generated] [--kind <kind file>] [--live --env <env>]
1634
+ Fail on an unreadable lineage lock or an open manual
1635
+ step, and, in a declared workspace, on a WSP check of
1636
+ the declaration, member ledgers, pipelines or
1637
+ generated files. --generated runs declared generators
1638
+ and compares their output. --kind warns on records
1639
+ whose pinned files changed. Needs no workspace file.
1640
+ --at reads a commit's git objects; --format json
1641
+ prints the read-contract document. --live --env
1642
+ resolves each declared member link against the live
1643
+ graph of <env> (each chant member runs chant graph
1644
+ --live, which reaches the account) and reports
1645
+ WSP141 and WSP142
1646
+ workspace check --changes <base>..<head> [--work <id>] [--severity off|warn|fail] [--kind <kind file>...] [--json]
1647
+ Map each path the diff changes to the current records
1648
+ whose constrains cover it: change-uncovered when none
1649
+ does, change-out-of-scope when a record in hand (the
1650
+ --work item and its decisions) lists it in
1651
+ out_of_scope. The declaration's changes block sets
1652
+ the severity (warn by default) and ignore globs. When
1653
+ the declaration at base has writeScope or agents, each
1654
+ commit that writes outside its writer's scope fails
1655
+ the check (write-scope-member, write-scope-kind)
1656
+ workspace patch <base>..<head>|<base>...<head>|<commit> [--path <p>...] [--max-bytes <n>] [--json]
1657
+ workspace patch [<commit>] --worktree [--path <p>...] [--max-bytes <n>] [--json]
1658
+ The hunks of a diff, file by file: a range, a work
1659
+ branch, or one commit against its first parent. Each
1660
+ file's hunk text stops at --max-bytes (64 KiB) and
1661
+ says it was truncated
1662
+ workspace build [dir] [--member <name>] [-o <dir>] [--dry-run]
1663
+ Build every chant member and example project, each with
1664
+ its own chant, one process per toolchain. -o <dir>
1665
+ writes <dir>/<member>.json; --member narrows the run;
1666
+ --dry-run prints which chant runs which project
1667
+ workspace lint [dir] [--format stylish|json|sarif] [--member <name>]
1668
+ Lint every chant member and example project with its
1669
+ own chant; sarif writes one run per member
1670
+ workspace audit [dir] [--json] [--member <name>]
1671
+ Audit each chant member with its own .chant-audit.json;
1672
+ every finding carries a member field
1673
+ workspace graph [dir] [--at <rev>] [--member <name>] [--kind <kind file>] [-o <file>]
1674
+ Compose each chant member's chant graph into one IR,
1675
+ with <member>/<id> ids and groups.byMember: the
1676
+ read-contract document. --at <rev> runs each member's
1677
+ source as it was at that commit; --kind adds the
1678
+ records' asset and constrains links. A member whose
1679
+ source and toolchain are unchanged is served from
1680
+ the cache in $CHANT_CACHE_DIR or ~/.cache/chant;
1681
+ --no-cache reads every member
1682
+ workspace graph --composites [--at <rev>] [--member <name>] [-o <file>]
1683
+ Each composite instance the members declare, with the
1684
+ components whose contract can deploy it; an instance
1685
+ with none lists an empty set
1686
+ workspace graph --intent <path[:start-end]|path#symbol> [--at <rev>] [--kind <kind file>...] [--follow-squash] [--json]
1687
+ The intent graph over one region: the commits that
1688
+ touched it, the decisions whose constrains cover it,
1689
+ the artifacts they pin, and findings with closed codes.
1690
+ Without --kind, every record kind the declaration names.
1691
+ --follow-squash follows a squash merge to its pull
1692
+ request's commits, fetching a missing ref from origin
1693
+ workspace graph --intent --record <id> [--at <rev>] [--kind <kind file>...] [--follow-squash] [--json]
1694
+ One decision's intent walk over every path: and member:
1695
+ entry it constrains: the commits in its window, each
1696
+ own, worked, within-other or unexplained, with counts
1697
+
1698
+ Lifecycle (alias: lc):
1699
+ lifecycle snapshot <env> Query API, save metadata to orphan branch
1700
+ --deep: also record each resource's property tree,
1701
+ not just its identity — what a fold over topology
1702
+ needs (costs more provider calls; #1267)
1703
+ lifecycle show <env> Show latest lifecycle snapshot
1704
+ lifecycle diff <env> Compare current build against last snapshot
1705
+ --live: query cloud now and detect drift
1706
+ (lexicons with a deep reader also report
1707
+ property-level drift; --update-baseline records
1708
+ what it reports as accepted so it stops alerting)
1709
+ lifecycle plan <env> Typed change set (create/update/delete/adopt) vs live
1710
+ --deep: also report properties declared
1711
+ heldElsewhere(). Never changes what the plan
1712
+ proposes; costs a provider call pair per readable
1713
+ resource, so the read's cost becomes a function of
1714
+ estate size rather than stack count (#2405)
1715
+ lifecycle affected Stacks a change affects (--base <ref> [--include-dependents])
1716
+ --json: emit the ChangeSet as JSON
1717
+ lifecycle whoami <env> Who chant would act as in each configured lexicon,
1718
+ and what that principal is scoped to — read-only,
1719
+ before anything acts (--json, --strict)
1720
+ lifecycle teardown <env> Plan what deleting the environment would remove —
1721
+ marker-scoped (this project's stack + env); --yes
1722
+ executes the plan (production-like names also need
1723
+ --confirm-prod, or an interactive confirmation)
1724
+ lifecycle log [env] History of lifecycle snapshots
1725
+
1726
+ Plan scenarios (#1292):
1727
+ scenario check Evaluate every declared Scenario's expect clause
1728
+ offline, against its given fixture (no cloud, no
1729
+ credentials); --json: emit verdicts as JSON.
1730
+ Nonzero exit on any failing scenario.
1731
+
1732
+ Component release ledger + status:
1733
+ components status [env] What's built vs what's deployed where, joined by
1734
+ digest (--live: reconcile against live+ownership;
1735
+ --json: stable machine-readable contract;
1736
+ --compare-to <env>: cross-check the same
1737
+ component's recorded digest against another env)
1738
+ components fan-out Run a change out across the components downstream
1739
+ of it, in an order derived from the source
1740
+ (--base <ref> [--head <ref>] [--include-dependents],
1741
+ or --from-affected <file>; --dry-run prints the
1742
+ derivation and dispatches nothing; --gate <name>
1743
+ puts one approval over the whole set;
1744
+ --wave-gate <name> puts one on each wave, planned
1745
+ when the wave is reached, with --canary <name>
1746
+ for wave 1 and --wave <n> for one wave per CI
1747
+ job; --resume <file> finishes an attempt that
1748
+ stopped)
1749
+ components pr-plan Plan the components a pull request reaches and
1750
+ the ones that depend on them, and write the
1751
+ report and note (--base <ref> --pr <n>
1752
+ [--forge github|gitlab|forgejo] posts them);
1753
+ applies nothing
1754
+ components pr-apply On merge: plan the same members again and apply
1755
+ them only if an approval stands for that digest
1756
+ (chant approve pr-<n> pr-apply --plan <digest>);
1757
+ a moved plan refuses with exit 3
1758
+ (--require-review: the approver must have
1759
+ approved the pull request on the forge;
1760
+ --member <name>, both commands: a workspace
1761
+ member's loop, gate op pr-<n>-<member>;
1762
+ --resume <file> finishes an apply that failed
1763
+ partway under the same approval)
1764
+ components release <env> Append one immutable release record
1765
+ (--component <name> --digest <sha256:...>
1766
+ [--git-sha <sha>] [--run-id <id>] [--actor <name>]);
1767
+ --release-plan <file> takes --digest's place,
1768
+ persisting the release plan the file holds to
1769
+ _plans/<digest>.json (ws-055) and recording its
1770
+ own digest
1771
+ components export <env> Materialize a persisted build archive manifest to
1772
+ a portable directory (--component <name>
1773
+ [--digest <manifestDigest>] -o <dir> [--json]);
1774
+ copies every image/template/asset/sbom entry
1775
+ byte-for-byte plus a self-describing manifest.json
1776
+ components promote Deploy the digests one environment's release
1777
+ ledger records to another, without a build
1778
+ (--from <env> --to <env> [--component <name>
1779
+ [--digest <sha256:...>]]; --dry-run prints the
1780
+ plan; the target's gates still apply)
1781
+ components rollback <env> Redeploy an earlier release of an environment
1782
+ from its recorded digest (--component <name>
1783
+ [--digest <sha256:...>]; defaults to the release
1784
+ before the current one; --dry-run prints the plan)
1785
+ components redeploy <env> Redeploy the release an environment's ledger
1786
+ records as current, after a deploy that failed
1787
+ partway (--component <name> [--digest <sha256:...>];
1788
+ --dry-run prints the plan; gates still apply)
1789
+
1790
+ Lexicon development:
1791
+ dev generate Generate lexicon artifacts (+ validate + coverage)
1792
+ dev publish Package lexicon for distribution
1793
+ dev onboard <name> Patch CI, Dockerfiles, and workflows for a new lexicon
1794
+ dev check-lexicon <dir> Check lexicon completeness (tier 1/2/3)
1795
+ dev surface-diff <dir> Regen lexicon, validate, diff API surface vs committed baseline
1796
+ (--force: bypass spec cache; --update-snapshot: write new baseline;
1797
+ --bump: with --update-snapshot, bump package version by drift severity;
1798
+ --check: fail if the committed baseline drifted (never writes);
1799
+ --run-examples: also run example build harness;
1800
+ --pinned-digest <file>: verify spec digest before regen)
1801
+ dev pinned-upgrade <dir> [pin]
1802
+ Report if a lexicon that declares upstreamPin (k8s, k3s, gcp, docker,
1803
+ gitlab, cedar, sql) has a newer upstream release; dry-run bump + regen +
1804
+ surface-diff, then revert. A pin that moves with other constants (sql's
1805
+ image digest) is reported with how to move it, not edited. A lexicon
1806
+ with several pins (sql: clickhouse, postgres-14 .. postgres-18) gets one
1807
+ report per pin; name a pin to check only that one
1808
+ (reports only; --force bypasses the spec cache, -f json for JSON)
1809
+ dev rolling-upgrade <dir> Report rolling-spec drift (aws, azure, github): regen from
1810
+ latest, diff surface vs committed baseline, print delta + PR
1811
+ label (dry run; --force bypasses the spec cache, --format json)
1812
+
1813
+ Local:
1814
+ emulator <up|down|status> Boot/stop/inspect configured lexicons' local
1815
+ emulators (Floci etc.); --lexicon <name>, --json,
1816
+ --port; \`chant emulator --help\` lists ports and logins
1817
+
1818
+ Servers:
1819
+ serve lsp Start the LSP server (stdio)
1820
+ serve mcp Start the MCP server (stdio)
1821
+
1822
+ Project:
1823
+ update Sync lexicon types into .chant/types/
1824
+ doctor Check project health and configuration
1825
+
1826
+ Options:
1827
+ -o, --output <file> Write output to file instead of stdout
1828
+ -f, --format <fmt> Output format (command-specific):
1829
+ - build: json (default) or yaml
1830
+ - list: text (default) or json
1831
+ - lint: stylish (default), json, or sarif
1832
+ --lexicon-output <lexicon>=<path>
1833
+ build: write that lexicon's output to its own file
1834
+ (repeatable). Lexicons not named go to --output when
1835
+ given, and are skipped otherwise
1836
+ -d, --lexicon <name> Build only the specified lexicon (e.g. aws, gitlab);
1837
+ import: use this lexicon instead of detecting one
1838
+ --env <name> Active environment: sets CHANT_ENV so env-aware source
1839
+ re-evaluates for that environment (build + graph), and
1840
+ drives organizational policy. Must be in chant.config
1841
+ \`environments\` when declared.
1842
+ -t, --template <name> Init template (e.g. node-pipeline, docker-build);
1843
+ records its lineage in .chant/workspace.lock.json
1844
+ --skill <name> Init: install only this skill from the lexicon
1845
+ --skip-mcp Init: scaffold without writing the project's .mcp.json
1846
+ --fix Auto-fix fixable issues (lint command)
1847
+ --force Force overwrite existing files (import command)
1848
+ -w, --watch Watch for changes and rebuild/re-lint (build, lint)
1849
+ -v, --verbose Show stack traces on errors; (build) list every
1850
+ resolved build parameter and per-file fold decision
1851
+ instead of the one-line summaries
1852
+ -h, --help Show this help message
1853
+ -V, --version Print the installed chant's version
1854
+ --on <lexicon> Which runtime hosts the run: a configured lexicon with
1855
+ an opRuntime, or local. Omitted, run.on in
1856
+ chant.config.ts decides, then the built-in local
1857
+ runtime (every run subcommand; #2121, #2523)
1858
+ --local Run an Op with the local in-process executor (default)
1859
+ -p, --profile <name> Named connection profile the hosting runtime targets
1860
+ (fountain.profiles in chant.config.ts); each runtime's
1861
+ own default when omitted (#2124)
1862
+ --json Emit the structured run result as JSON (run command)
1863
+ --report With a path arg: SARIF report destination (migrate)
1864
+ OR '--report gitlab-mr': emit the GitLab MR plan-widget
1865
+ JSON (lifecycle plan)
1866
+ OR '--report markdown': emit a reviewer-facing markdown
1867
+ render, holes and disruption included (lifecycle plan)
1868
+ --from <name> Source lexicon for migrate (default: github)
1869
+ --to <name> Target lexicon for migrate (default: gitlab)
1870
+ --emit <fmt> Migration output format: yaml (default) or ts
1871
+ --strict Escalate needs-review/validation to errors (migrate);
1872
+ exit nonzero on an unresolved identity (lifecycle whoami)
1873
+ --validate Run external validator (glci/glab) after migrate
1874
+ --use-composites Rewrite to composite calls when patterns match (migrate)
1875
+ --components Target discovered Component declarations instead of
1876
+ lexicon resources (list, describe, graph, build, run)
1877
+ --generate <lexicon> Generate mode: synthesize CI YAML for <lexicon> (github,
1878
+ gitlab or forgejo) instead of running. build
1879
+ --components: one pipeline for the components; run:
1880
+ one pipeline file per scheduled Op
1881
+ --spec <file> (run --generate) JSON Op specs: an array, or
1882
+ { ops, options }
1883
+ --promote-to <env> (build --components --generate) Add a job that
1884
+ promotes the deployed releases to <env>
1885
+ --no-release-record Skip auto-emitting a release-ledger record after a
1886
+ successful \`run --components\` deploy (default: on;
1887
+ also settable via chant.config.ts's
1888
+ release.autoRecord: false; #597)
1889
+ --fold (build) Fold source modules statically instead of
1890
+ running them; folds resource constructors and
1891
+ composite factory calls (#1022/#1023), falling back
1892
+ to run per-file for anything else outside the fold
1893
+ subset (a cross-file-only reference, a re-export,
1894
+ \`export default\`, ...). Logs a fold/run count
1895
+ (per-file lines under --verbose). DEFAULT since #1134 — this flag forces it on
1896
+ over a chant.config.ts \`build.fold: false\`.
1897
+ --no-fold (build) Opt out of folding for this invocation: every
1898
+ source module is imported and run, the pre-#1134
1899
+ behavior. Beats chant.config.ts's build.fold.
1900
+ --fold-rank [<path>] (build, with --fold) Rank run-mode files by dominator
1901
+ retained-count over the forward import-failure graph
1902
+ (#1083) — fixing the top blocker unblocks the most
1903
+ files. Files held back only by the reverse rule
1904
+ (#1044) are reported separately, never folded into
1905
+ the ranking. With a path argument, also writes a
1906
+ Brendan Gregg collapsed-format export (weighted by
1907
+ retained count) there, for any flame/icicle viewer.
1908
+ --sandbox (build) Run run-fallback source files (or every
1909
+ file, without --fold) together, isolated, in one
1910
+ sandboxed child process instead of in-process
1911
+ (#1045). No filesystem write, no child process, no
1912
+ worker threads, no ambient environment visible to
1913
+ project source; network egress is NOT blocked (see
1914
+ docs). Default: off (also settable via
1915
+ chant.config.ts's build.sandbox: true; #1045)
1916
+ --param <name=value> (build, graph, run --components, components fan-out,
1917
+ components promote, components rollback,
1918
+ components redeploy) Bind a
1919
+ declared build-time parameter (chant.config.ts's buildParams)
1920
+ to a value, for source to read as params.<name>
1921
+ (#1064) instead of process.env — repeatable.
1922
+ Distinct from the AWS lexicon's deploy-time
1923
+ Parameter(): this resolves before synthesis, so it
1924
+ can change which resources are produced at all.
1925
+ Highest precedence. With init --from, it sets a
1926
+ template parameter that the template's
1927
+ chant.template.json declares instead (#2627).
1928
+ --params-file <path> (build, graph, run --components, components fan-out,
1929
+ components promote, components rollback,
1930
+ components redeploy) JSON file
1931
+ of { "name": value } build-time parameter values
1932
+ (#1064). Second precedence, after --param.
1933
+ init --from refuses it: pass --param instead.
1934
+
1935
+ Examples:
1936
+ chant build ./infra/
1937
+ chant build ./infra/ --output stack.json
1938
+ chant build ./infra/ --format yaml
1939
+ chant build ./infra/ --watch
1940
+ chant build ./infra/ --fold
1941
+ chant build ./infra/ --components --generate gitlab
1942
+ chant build ./infra/ --components --generate gitlab --output .gitlab-ci.yml
1943
+ chant run --generate github
1944
+ chant run --components search-service --env staging
1945
+ chant run --components all --env production
1946
+ chant components export prod --component search-service -o ./dist/search-service
1947
+ chant import template.json --output ./infra/
1948
+ chant import manifest.yaml --lexicon k8s --output ./infra/
1949
+ chant import dash.json --lexicon grafana --parser-option acceptLossyV1
1950
+ chant import --from prod --name my-bucket --output src/
1951
+ chant lint ./infra/
1952
+ chant lint ./infra/ --format sarif
1953
+ chant lint ./infra/ --watch
1954
+ chant list ./infra/
1955
+ chant list ./infra/ --format json
1956
+ chant describe myComponent src/
1957
+ chant describe myComponent src/ --format json
1958
+ `);
1959
+ const groupsHelp = formatCommandGroupsHelp(groups);
1960
+ if (groupsHelp)
1961
+ console.log(groupsHelp);
1962
+ }
1963
+ /**
1964
+ * Best-effort load the current project's lexicon plugins for a purely
1965
+ * read-only lookup (help composition, plugin-command dispatch) — never
1966
+ * throws, empty on any failure (no config, no lexicons, not a chant
1967
+ * project at all). Mirrors the existing best-effort loading already used
1968
+ * for `emulator`/`components status` in {@link main} below.
1969
+ */
1970
+ async function loadPluginsBestEffort() {
1971
+ try {
1972
+ const lexiconNames = await resolveProjectLexicons(resolve("."));
1973
+ return await loadPlugins(lexiconNames);
1974
+ }
1975
+ catch {
1976
+ return [];
1977
+ }
1978
+ }
1979
+ /**
1980
+ * chant #1078 — the lexicon command-group seam's dispatch-time half. Core's
1981
+ * own `parseArgs`/`resolveCommand` know nothing about a lexicon's mounted
1982
+ * verbs, so this is only ever consulted after BOTH of those have already
1983
+ * failed to make sense of the invocation: either `parseArgs` threw on a flag
1984
+ * it doesn't recognize (which is *expected* for a mounted command's own
1985
+ * vocabulary — core has none), or it parsed fine but `resolveCommand` found
1986
+ * no match in the static registry (a mounted command with no extra flags,
1987
+ * e.g. `chant kube version`). Either way, a lexicon-mounted command's group
1988
+ * name and verb are always the first two CLI tokens (mirrors the `emulator
1989
+ * <up|down|status>` compound shape from #920), so `rawArgv` — the untouched
1990
+ * `process.argv.slice(2)` — is all this needs; nothing from the partially or
1991
+ * fully parsed `ParsedArgs` is used, on purpose, since core's flag-parsing
1992
+ * failure or success is irrelevant to a namespace it doesn't own.
1993
+ *
1994
+ * Returns `undefined` when nothing claims the leading token as a command
1995
+ * group at all, so the caller falls back to its own error handling
1996
+ * unchanged — a project with no lexicon exposing `commands()` (or none of
1997
+ * its plugins matching) is completely unaffected.
1998
+ */
1999
+ async function tryPluginCommand(rawArgv) {
2000
+ const [groupName, verbName] = rawArgv;
2001
+ if (!groupName || groupName.startsWith("-"))
2002
+ return undefined;
2003
+ const plugins = await loadPluginsBestEffort();
2004
+ // A group declaring a `defaultVerb` (#2125) answers its bare name, so
2005
+ // `chant acp` and `chant acp --durable-requests` both reach that verb. The
2006
+ // slicing follows: with no verb token consumed, everything after the group
2007
+ // name is the default verb's own argument list.
2008
+ const group = collectCommandGroups(plugins).find((g) => g.name === groupName);
2009
+ const useDefault = group?.defaultVerb !== undefined && (verbName === undefined || verbName.startsWith("-"));
2010
+ const verb = useDefault ? group?.defaultVerb : verbName;
2011
+ const rawArgs = rawArgv.slice(useDefault ? 1 : 2);
2012
+ const result = await dispatchCommandGroup(plugins, groupName, verb, rawArgs);
2013
+ if (result.kind === "no-group")
2014
+ return undefined;
2015
+ if (result.kind === "usage-error") {
2016
+ console.error(formatError({ message: result.message, hint: result.hint }));
2017
+ return 1;
2018
+ }
2019
+ return result.exitCode;
2020
+ }
2021
+ /**
2022
+ * Load lexicon plugins for the given project path, or exit with an error.
2023
+ */
2024
+ async function loadPluginsOrExit(path, lexicon) {
2025
+ let plugins;
2026
+ try {
2027
+ // chant #3648 — `--lexicon <name>` loads that lexicon even when the
2028
+ // project's config and imports name none.
2029
+ const lexiconNames = await resolveProjectLexicons(resolve(path), { lexicon });
2030
+ plugins = await loadPlugins(lexiconNames);
2031
+ }
2032
+ catch (error) {
2033
+ const errorMessage = error instanceof Error ? error.message : String(error);
2034
+ console.error(formatError({ message: errorMessage }));
2035
+ process.exit(1);
2036
+ }
2037
+ if (plugins.length === 0) {
2038
+ console.error(formatError({
2039
+ message: "No lexicon detected",
2040
+ hint: 'Run "chant init --lexicon <name>" to initialize a project, or add a lexicon to chant.config.ts',
2041
+ }));
2042
+ process.exit(1);
2043
+ }
2044
+ // #1344 — a lexicon that declares the shape of its own `chant.config.ts`
2045
+ // namespace gets it validated here, once, before any command runs. The
2046
+ // config schema is `.passthrough()`, so before this an unknown key inside a
2047
+ // namespace was accepted and silently ignored: `forgejo: { runnerLabel: … }`
2048
+ // left the dialect on its defaults with nothing said. A namespace whose
2049
+ // lexicon declares no schema keeps that passthrough.
2050
+ try {
2051
+ const { config } = await loadChantConfigUpward(resolve(path));
2052
+ const problems = validateLexiconConfig(plugins, config);
2053
+ if (problems.length > 0) {
2054
+ console.error(formatError({
2055
+ message: `Invalid lexicon configuration in chant.config:\n${formatLexiconConfigProblems(problems)}`,
2056
+ hint: "Remove or correct the key. A lexicon's namespace accepts only the keys it declares.",
2057
+ }));
2058
+ process.exit(1);
2059
+ }
2060
+ }
2061
+ catch {
2062
+ // No config, or one that failed to load — the caller's own handling stands.
2063
+ }
2064
+ return plugins;
2065
+ }
2066
+ /**
2067
+ * #2700 — whether `path` is the root of a declared workspace and holds no
2068
+ * lexicon of its own: no `lexicons` in a root config, and no lexicon import in
2069
+ * the root's source, which leaves the members' directories out (#2527). A
2070
+ * generated app repo can be this shape: its lexicons are all under a
2071
+ * delivery directory, not the root. `chant serve mcp` starts there instead of
2072
+ * refusing with "No lexicon detected", and serves core with the chant
2073
+ * members' lexicons.
2074
+ *
2075
+ * A directory with no workspace declaration costs only `findWorkspaceRoot`'s
2076
+ * existence checks, so a level-0 project reaches `loadPluginsOrExit` as before.
2077
+ */
2078
+ async function isLexiconlessWorkspaceRoot(path) {
2079
+ const target = resolve(path);
2080
+ if (findWorkspaceRoot(target)?.dir !== target)
2081
+ return false;
2082
+ try {
2083
+ await resolveProjectLexicons(target);
2084
+ return false;
2085
+ }
2086
+ catch (error) {
2087
+ return isNoLexiconDetected(error);
2088
+ }
2089
+ }
2090
+ /** Whether `def` must run without evaluating the project's `chant.config.ts` (chant#2591). */
2091
+ function commandRunsNoConfig(def, args) {
2092
+ return typeof def.runsNoConfig === "function" ? def.runsNoConfig(args) : def.runsNoConfig === true;
2093
+ }
2094
+ /**
2095
+ * Run one level-0 command line in this process and return its exit code
2096
+ * (#2537). `chant workspace member-run` calls it once per member, from inside
2097
+ * the member's directory, so each member is built, linted, audited or graphed
2098
+ * as `chant <verb> .` would do it there, while members that share a toolchain
2099
+ * share one process. It is main()'s dispatch without the help, the root
2100
+ * refusal and the lexicon command groups: the config is loaded, `--env` is
2101
+ * checked, plugins are loaded when the command needs them, and the handler
2102
+ * runs. A `process.exit` inside (loadPluginsOrExit's, say) is the caller's to
2103
+ * catch.
2104
+ */
2105
+ export async function runCommandInProcess(argv) {
2106
+ const args = parseArgs(argv);
2107
+ const match = resolveCommand(args, commandRegistry);
2108
+ if (!match) {
2109
+ console.error(formatError({ message: `Unknown command: ${args.command}` }));
2110
+ return 1;
2111
+ }
2112
+ if (args.env)
2113
+ process.env[ENV_VAR] = args.env;
2114
+ let loadedConfig;
2115
+ try {
2116
+ // chant#2618 — `workspace audit` reaches `audit` through here, once per
2117
+ // member. A `runsNoConfig` command skips the load, as it does in main().
2118
+ if (!commandRunsNoConfig(match.def, args))
2119
+ loadedConfig = await loadChantConfigUpward(resolve(args.path));
2120
+ }
2121
+ catch {
2122
+ // A project with no config is the handler's to report, as in main().
2123
+ }
2124
+ const envErr = unknownEnvError(args.env, loadedConfig?.config.environments);
2125
+ if (envErr) {
2126
+ console.error(formatError({ message: envErr, hint: "Declare it in chant.config `environments`, or omit --env." }));
2127
+ return 1;
2128
+ }
2129
+ const plugins = match.def.requiresPlugins ? await loadPluginsOrExit(match.compound ? "." : args.path, args.lexicon) : [];
2130
+ return match.def.handler({ args, plugins, serializers: plugins.map((p) => p.serializer) });
2131
+ }
2132
+ // ── Command registry ──────────────────────────────────────────────
2133
+ /**
2134
+ * Every command word `chant` answers to, and the handler behind it.
2135
+ *
2136
+ * Exported because a caller other than `main()` now needs to ask "is this a
2137
+ * chant verb, and what runs it?" — the fountain lexicon's ACP server (#2125)
2138
+ * treats a prompt as a chant command line, and the only honest answer to
2139
+ * whether `chant lifecycle diff` is a verb is this list. A hand-kept copy
2140
+ * would be wrong the first time a command is added, and the ACP server would
2141
+ * refuse a verb that works at the terminal.
2142
+ */
2143
+ export const commandRegistry = [
2144
+ // Primary commands
2145
+ { name: "build", requiresPlugins: true, handler: runBuild },
2146
+ { name: "lint", handler: runLint },
2147
+ { name: "list", handler: runList },
2148
+ { name: "describe", handler: runDescribe },
2149
+ { name: "explain", handler: runExplain },
2150
+ { name: "search", handler: runSearch },
2151
+ // chant#2591 — `import --agents` and `audit` read chant.config statically
2152
+ // and never evaluate it (chant#2589 for audit, which audits code it must not run).
2153
+ { name: "import", handler: runImport, runsNoConfig: (args) => args.agents === true },
2154
+ { name: "audit", handler: runAudit, runsNoConfig: true },
2155
+ { name: "migrate", handler: runMigrate },
2156
+ // Read-only Terraform peelability advisor (#214). Compound so "advise" lands
2157
+ // in args.path; the estate dir comes from --from. No plugins, no project.
2158
+ { name: "carve advise", handler: runCarveAdvise },
2159
+ // Emit step (#197): adopt a selected TF resource into chant source. The
2160
+ // --state path is offline (no plugins); the --env live path loads the target
2161
+ // lexicon lazily in the handler, so this command does not require plugins.
2162
+ { name: "carve emit", handler: runCarveEmit },
2163
+ // Boundary bridging (#197): patch the surviving TF (data sources + rewired
2164
+ // refs) + runbook. No plugins; Terraform-side only. Read-only unless
2165
+ // --apply-rewrites.
2166
+ { name: "carve bridge", handler: runCarveBridge },
2167
+ // Apply graduation (#197): ownership marker + finalized apply runbook.
2168
+ // BYOL-honest — no cloud call; --write saves the graduation doc.
2169
+ { name: "carve apply", handler: runCarveApply },
2170
+ // Status read over a tree of carve manifests (#2038): the contract a
2171
+ // renderer replaces its own walk-and-guess discovery with. Read-only.
2172
+ { name: "carve status", handler: runCarveStatus },
2173
+ // #3573 — which commits passed CI, kept as ci/green and ci/revoked tags (ws-103). Imported on first use.
2174
+ { name: "ci last-green", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-green-cli.js")).runCiLastGreen(ctx) },
2175
+ { name: "ci tick", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-green-cli.js")).runCiTick(ctx) },
2176
+ { name: "ci workflow", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-green-cli.js")).runCiWorkflow(ctx) },
2177
+ // #3188 — the grouped plan summary of a change-set document. Reads one file; imported on first use.
2178
+ { name: "change-set summary", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/change-set.js")).runChangeSetSummary(ctx) },
2179
+ { name: "init", handler: runInit, runsNoConfig: true },
2180
+ { name: "init lexicon", handler: runInitLexicon },
2181
+ { name: "update", handler: runUpdate },
2182
+ { name: "doctor", handler: runDoctor },
2183
+ // Dev subcommands
2184
+ { name: "dev generate", requiresPlugins: true, handler: runDevGenerate },
2185
+ { name: "dev publish", requiresPlugins: true, handler: runDevPublish },
2186
+ { name: "dev onboard", handler: runDevOnboard, runsNoConfig: true },
2187
+ { name: "dev check-lexicon", handler: runDevCheckLexicon },
2188
+ { name: "dev surface-diff", handler: runDevSurfaceDiff },
2189
+ { name: "dev pinned-upgrade", handler: runDevPinnedUpgrade },
2190
+ { name: "dev rolling-upgrade", handler: runDevRollingUpgrade },
2191
+ // Op / run subcommands
2192
+ { name: "run list", handler: runOpList },
2193
+ { name: "run status", handler: runOpStatus },
2194
+ { name: "run approve", handler: runOpApprove },
2195
+ { name: "run signal", handler: runOpSignalRenamed },
2196
+ { name: "run cancel", handler: runOpCancel },
2197
+ { name: "run log", handler: runOpLog },
2198
+ { name: "run wave", handler: runOpWaveCommand },
2199
+ // #3683 — start the CI jobs that wait at gates whose approval arrived. Imported on first use.
2200
+ { name: "run resume", handler: async (ctx) => (await import("./handlers/gate-resume.js")).runResumeCommand(ctx) },
2201
+ { name: "run", handler: runOp },
2202
+ { name: "operator status", handler: runOperatorStatus },
2203
+ { name: "operator log", handler: runOperatorLog },
2204
+ { name: "operator", handler: runOperator },
2205
+ { name: "approve", handler: runApprove },
2206
+ { name: "graph", handler: runGraph },
2207
+ { name: "vendor", handler: runVendor },
2208
+ // Project-local codegen: typed code from sources chant.config declares
2209
+ // (k8s.crds, helm.charts). Imported on first use.
2210
+ { name: "generate", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/generate.js")).runGenerate(ctx) },
2211
+ // Workspace reads (#2524). Imported on first use, so a level-0 command never
2212
+ // loads anything under workspace/ (#2525 rule 5, pinned by #2526's goldens).
2213
+ { name: "workspace records", handler: async (ctx) => (await import("../workspace/records-cli.js")).runWorkspaceRecords(ctx) },
2214
+ // ws-058 (#2739) — decision points and the questions asked of them; never calls a model.
2215
+ { name: "workspace points", handler: async (ctx) => (await import("../workspace/points-cli.js")).runWorkspacePoints(ctx) },
2216
+ { name: "workspace init", handler: async (ctx) => (await import("../workspace/init.js")).runWorkspaceInit(ctx) },
2217
+ { name: "workspace ls", handler: async (ctx) => (await import("../workspace/ls.js")).runWorkspaceLs(ctx) },
2218
+ // #2732 — the work lease: claim, renew and release a work item.
2219
+ { name: "workspace work", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/work-cli.js")).runWorkspaceWork(ctx) },
2220
+ // #3033 — the agent run record: what each run cost and which commits it made. chant records runs and never starts one.
2221
+ { name: "workspace runs", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/runs-cli.js")).runWorkspaceRuns(ctx) },
2222
+ { name: "workspace status", handler: async (ctx) => (await import("../workspace/status.js")).runWorkspaceStatus(ctx) },
2223
+ { name: "workspace lineage", handler: async (ctx) => (await import("../workspace/lineage-cli.js")).runWorkspaceLineage(ctx) },
2224
+ { name: "workspace upgrade", handler: async (ctx) => (await import("../workspace/lineage-upgrade-cli.js")).runWorkspaceUpgrade(ctx) },
2225
+ // #2551 — adopt a lineage, the hash index it matches against, and the versions of a family of workspaces.
2226
+ { name: "workspace adopt-lineage", handler: async (ctx) => (await import("../workspace/lineage-adopt-cli.js")).runWorkspaceAdoptLineage(ctx) },
2227
+ { name: "workspace hash-index", handler: async (ctx) => (await import("../workspace/lineage-adopt-cli.js")).runWorkspaceHashIndex(ctx) },
2228
+ // #2552 — export a workspace or members, bring an export back, and admit a return's signers.
2229
+ { name: "workspace export", handler: async (ctx) => (await import("../workspace/export-cli.js")).runWorkspaceExport(ctx) },
2230
+ { name: "workspace import", handler: async (ctx) => (await import("../workspace/export-cli")).runWorkspaceImport(ctx) },
2231
+ { name: "workspace admit", handler: async (ctx) => (await import("../workspace/export-cli.js")).runWorkspaceAdmit(ctx) },
2232
+ { name: "workspace versions", handler: async (ctx) => (await import("../workspace/lineage-versions.js")).runWorkspaceVersions(ctx) },
2233
+ // #2641 — workspace check reads member configs statically and never runs one.
2234
+ { name: "workspace check", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/lineage-check.js")).runWorkspaceCheck(ctx) },
2235
+ // The hunks of a diff, for a reader that runs no git of its own.
2236
+ { name: "workspace patch", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/patch.js")).runWorkspacePatch(ctx) },
2237
+ // #2537 — per-member commands. Each member runs under its own chant, one
2238
+ // process per toolchain identity; `member-run` is that process's entry.
2239
+ { name: "workspace build", handler: async (ctx) => (await import("../workspace/member-commands.js")).runWorkspaceMembers(ctx, "build") },
2240
+ { name: "workspace lint", handler: async (ctx) => (await import("../workspace/member-commands.js")).runWorkspaceMembers(ctx, "lint") },
2241
+ // chant#2618 — audit runs no project code, at the workspace level too.
2242
+ { name: "workspace audit", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-commands.js")).runWorkspaceMembers(ctx, "audit") },
2243
+ { name: "workspace graph", handler: async (ctx) => (await import("../workspace/member-commands.js")).runWorkspaceMembers(ctx, "graph") },
2244
+ // Each unit decides for itself whether its config is loaded (runCommandInProcess).
2245
+ { name: "workspace member-run", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-run.js")).runWorkspaceMemberRun(ctx, runCommandInProcess) },
2246
+ // #3308 — a box's listing, written through chant so a tool never edits the declaration itself (ws-074).
2247
+ { name: "workspace box", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/box-cli.js")).runWorkspaceBox(ctx) },
2248
+ // #3596 — a declaration's members and hosts, written through chant so a lobby never edits the declaration itself (ws-074).
2249
+ { name: "workspace member", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/declaration-write-cli.js")).runWorkspaceMember(ctx) },
2250
+ { name: "workspace host", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/declaration-write-cli.js")).runWorkspaceHost(ctx) },
2251
+ // #3173 — the working tree's write lock, held across chant calls for a batch of writes (ws-089).
2252
+ { name: "workspace lock", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/write-lock-cli.js")).runWorkspaceLock(ctx) },
2253
+ // #3172 — work in progress under refs/chant/wip/<branch>, replicated under the box's policy (ws-085).
2254
+ { name: "workspace wip", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/wip-cli.js")).runWorkspaceWip(ctx) },
2255
+ { name: "workspace pin", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/pin-cli.js")).runWorkspacePin(ctx) },
2256
+ // #2548 — an agent session's member, write scope and spec, for a session that resumes.
2257
+ { name: "workspace agent", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/agent-cli.js")).runWorkspaceAgent(ctx) },
2258
+ { name: "workspace verify", handler: async (ctx) => (await import("../workspace/trust/verify-cli.js")).runWorkspaceVerify(ctx) },
2259
+ { name: "workspace signers", handler: async (ctx) => (await import("../workspace/trust/signers-cli.js")).runWorkspaceSigners(ctx) },
2260
+ { name: "workspace evidence", handler: async (ctx) => (await import("../workspace/trust/evidence-cli.js")).runWorkspaceEvidence(ctx) },
2261
+ // State subcommands
2262
+ { name: "lifecycle snapshot", requiresPlugins: true, handler: runLifecycleSnapshot },
2263
+ { name: "lifecycle show", handler: runLifecycleShow },
2264
+ { name: "lifecycle diff", requiresPlugins: true, handler: runLifecycleDiff },
2265
+ { name: "lifecycle rollback", handler: runLifecycleRollback },
2266
+ { name: "lifecycle plan", requiresPlugins: true, handler: runLifecyclePlan },
2267
+ { name: "lifecycle affected", requiresPlugins: true, handler: runLifecycleAffected },
2268
+ { name: "lifecycle whoami", requiresPlugins: true, handler: runLifecycleWhoami },
2269
+ { name: "lifecycle teardown", requiresPlugins: true, handler: runLifecycleTeardown },
2270
+ { name: "lifecycle log", handler: runLifecycleLog },
2271
+ // Plan scenarios (#1292) — fully offline, no plugin network calls, but
2272
+ // requiresPlugins:true so the build step has serializers to partition
2273
+ // against, same as every other build-then-something verb.
2274
+ { name: "scenario check", requiresPlugins: true, handler: runScenarioCheck },
2275
+ // Component release ledger + status surface (#568, epic #551)
2276
+ { name: "components fan-out", requiresPlugins: true, handler: runComponentsFanOut },
2277
+ // #3183 — the pull-request loop the generated CI runs. Imported on first use.
2278
+ { name: "components pr-plan", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr.js")).runComponentsPrPlan(ctx) },
2279
+ { name: "components pr-apply", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr.js")).runComponentsPrApply(ctx) },
2280
+ { name: "components status", requiresPlugins: true, handler: runComponentsStatus },
2281
+ { name: "components release", handler: runComponentsReleaseRecord },
2282
+ { name: "components export", handler: runComponentsExport },
2283
+ { name: "components promote", handler: runComponentsPromote },
2284
+ { name: "components rollback", handler: runComponentsRollback },
2285
+ { name: "components redeploy", handler: runComponentsRedeploy },
2286
+ // Local emulators of configured lexicons (#920). Compound so the action word
2287
+ // lands in args.path (not consumed as a project dir) and projectPath is forced ".".
2288
+ { name: "emulator up", requiresPlugins: true, handler: runEmulator },
2289
+ { name: "emulator down", requiresPlugins: true, handler: runEmulator },
2290
+ { name: "emulator status", requiresPlugins: true, handler: runEmulator },
2291
+ // Serve subcommands
2292
+ { name: "serve lsp", requiresPlugins: true, handler: runServeLsp },
2293
+ { name: "serve mcp", requiresPlugins: true, handler: runServeMcp },
2294
+ // Fallback for unknown subcommands (must come after compound entries)
2295
+ { name: "carve", handler: runCarveUnknown },
2296
+ { name: "emulator", requiresPlugins: true, handler: runEmulator },
2297
+ { name: "lifecycle", handler: runLifecycleUnknown },
2298
+ { name: "scenario", handler: runScenarioUnknown },
2299
+ { name: "dev", handler: runDevUnknown },
2300
+ { name: "serve", handler: runServeUnknown },
2301
+ { name: "components", handler: runComponentsUnknown },
2302
+ { name: "workspace", handler: async (ctx) => (await import("../workspace/records-cli.js")).runWorkspaceUnknown(ctx) },
2303
+ ];
2304
+ /**
2305
+ * Main entry point
2306
+ */
2307
+ async function main() {
2308
+ // #3878 — run from dist/ with plain node, TypeScript loads only when
2309
+ // something imports it. A no-op from source.
2310
+ installCompiledCli();
2311
+ const rawArgv = process.argv.slice(2);
2312
+ let args;
2313
+ try {
2314
+ args = parseArgs(rawArgv);
2315
+ }
2316
+ catch (err) {
2317
+ // chant #1078 — core's parser has no idea what flags a lexicon's own
2318
+ // mounted verb accepts, so an "unknown flag" here is expected, not a
2319
+ // real error, until we've checked whether this invocation actually
2320
+ // targets a command group. `tryPluginCommand` returns `undefined` when
2321
+ // nothing claims the leading token, in which case this was a genuine
2322
+ // core-flag error and the original is rethrown unchanged.
2323
+ const code = await tryPluginCommand(rawArgv);
2324
+ if (code !== undefined) {
2325
+ await flushAndExit(code);
2326
+ return;
2327
+ }
2328
+ throw err;
2329
+ }
2330
+ // #2701 — `chant --version` / `-V` prints the installed chant's version, the
2331
+ // one the MCP server reports (./version.ts). With a command word it answers
2332
+ // only for one of core's own commands; a lexicon-mounted verb keeps the flag.
2333
+ if (args.version && (!args.command || resolveCommand(args, commandRegistry))) {
2334
+ console.log(CHANT_VERSION);
2335
+ await flushAndExit(0);
2336
+ return;
2337
+ }
2338
+ // #3673 — `chant emulator --help` is the emulator's own usage, with the
2339
+ // ports and sign-in each configured lexicon's emulator uses, not the
2340
+ // global command list it used to print.
2341
+ if (args.help && args.command === "emulator") {
2342
+ console.log((await emulatorHandlers()).formatEmulatorHelp(await loadPluginsBestEffort().catch(() => [])));
2343
+ await flushAndExit(0);
2344
+ return;
2345
+ }
2346
+ if (args.help || !args.command) {
2347
+ const groups = await loadPluginsBestEffort().then(collectCommandGroups).catch(() => []);
2348
+ printHelp(groups);
2349
+ process.exit(args.help ? 0 : 1);
2350
+ }
2351
+ // `--env <name>` is a build-context switch for the whole invocation: set it
2352
+ // *before* anything imports the project so env-aware source (and thus the graph
2353
+ // / build) reflects that environment. Set early, before config import, since
2354
+ // chant.config itself may branch on the env. (#505)
2355
+ if (args.env)
2356
+ process.env[ENV_VAR] = args.env;
2357
+ // chant #1113 — `--sandbox` is a property of the whole invocation, and it
2358
+ // has to be known BEFORE the first config load, because `chant.config.ts` is
2359
+ // itself project-authored code. Arming here, straight off the parsed flag,
2360
+ // is the only ordering that works: the project's own `build.sandbox: true`
2361
+ // cannot cover its own evaluation (reading it means running it), so the
2362
+ // command-line flag is what puts the config inside the boundary. See
2363
+ // `../config-sandbox.ts`.
2364
+ if (args.sandbox)
2365
+ armSandboxConfigEvaluation();
2366
+ // chant #1131 — the same for `lint.policies`. Armed from the flag here so
2367
+ // the mode is set for the whole invocation, not just `chant build`; the build
2368
+ // command arms it again from the RESOLVED value (a project's own
2369
+ // `build.sandbox: true` also sandboxes its policies — unlike the config,
2370
+ // policies have no bootstrap limit, since they load long after the config is
2371
+ // known). See `../lint/policy-sandbox.ts`.
2372
+ if (args.sandbox)
2373
+ armSandboxPolicyExecution();
2374
+ // Initialize runtime adapter early — before plugins or commands run.
2375
+ // chant #1117 — walks up from `args.path` to the project root: for a
2376
+ // subdirectory build/command (`chant build src/<stack> --env prod`) the
2377
+ // declared `environments` almost always live in the root `chant.config.ts`,
2378
+ // not `args.path` itself.
2379
+ //
2380
+ // chant#2591 — a command marked `runsNoConfig` skips this load: it must not
2381
+ // run the project's `chant.config.ts` (see `CommandDef.runsNoConfig`). Such a
2382
+ // command gets no `--env` check against the declared environments either.
2383
+ const earlyMatch = resolveCommand(args, commandRegistry);
2384
+ const runsNoConfig = earlyMatch != null && commandRunsNoConfig(earlyMatch.def, args);
2385
+ // #3878 — load the command's own modules (and the plugin loader, when it
2386
+ // needs plugins) before anything imports TypeScript: once a chant.config.ts
2387
+ // has registered tsx, every module after it is resolved and loaded through
2388
+ // tsx's hooks, which costs far more than plain node.
2389
+ await Promise.all([
2390
+ earlyMatch ? handlerModules.get(earlyMatch.def.handler)?.() : undefined,
2391
+ earlyMatch?.def.requiresPlugins ? import("./plugins.js") : undefined,
2392
+ ]);
2393
+ const projectPath0 = resolve(args.path === "." ? "." : args.path);
2394
+ let loadedConfig;
2395
+ try {
2396
+ if (!runsNoConfig)
2397
+ loadedConfig = await loadChantConfigUpward(projectPath0);
2398
+ initRuntime();
2399
+ }
2400
+ catch {
2401
+ // Config may not exist yet (e.g. `chant init`)
2402
+ initRuntime();
2403
+ }
2404
+ // Reject an --env that isn't among the project's declared `environments`.
2405
+ const envErr = unknownEnvError(args.env, loadedConfig?.config.environments);
2406
+ if (envErr) {
2407
+ console.error(formatError({ message: envErr, hint: 'Declare it in chant.config `environments`, or omit --env.' }));
2408
+ process.exit(1);
2409
+ }
2410
+ const match = earlyMatch;
2411
+ if (!match) {
2412
+ // chant #1078 — not one of core's own commands; check whether a lexicon
2413
+ // mounted a command group under this name before giving up. This is the
2414
+ // "parsed fine, matched nothing" trigger for the seam — the flag-error
2415
+ // trigger is above, in the `parseArgs` catch block.
2416
+ const code = await tryPluginCommand(rawArgv);
2417
+ if (code !== undefined) {
2418
+ await flushAndExit(code);
2419
+ return;
2420
+ }
2421
+ console.error(formatError({
2422
+ message: `Unknown command: ${args.command}`,
2423
+ hint: 'Run "chant --help" to see available commands',
2424
+ }));
2425
+ process.exit(1);
2426
+ }
2427
+ // #2537 (#2524 D0) — at the root of a declared workspace, `build` and
2428
+ // `lint` refuse with WSP000 unless `--root-only` or `rootOnly: true` says
2429
+ // to run on the root project alone. Both lookups only test whether files
2430
+ // exist; the workspace code loads only when this project is a declared root.
2431
+ if (match.def.name === "build" || match.def.name === "lint") {
2432
+ const target = resolve(args.path);
2433
+ const workspace = findWorkspaceRoot(target);
2434
+ if (workspace && findProjectRoot(target) === workspace.dir) {
2435
+ const { guardRootCommand } = await import("../workspace/root-refusal.js");
2436
+ const refused = guardRootCommand({
2437
+ verb: match.def.name,
2438
+ target,
2439
+ workspaceDir: workspace.dir,
2440
+ rootOnly: args.rootOnly === true || loadedConfig?.config.rootOnly === true,
2441
+ });
2442
+ if (refused !== undefined) {
2443
+ await flushAndExit(refused);
2444
+ return;
2445
+ }
2446
+ }
2447
+ }
2448
+ // For compound commands (e.g. "run list", "lifecycle plan <env>"), the first
2449
+ // positional is a subcommand argument — an environment, op, or lexicon name —
2450
+ // not a project path. Plugins always load from the cwd; the handler reads its
2451
+ // own positionals from args.extraPositional. Using extraPositional as the path
2452
+ // here pointed plugin resolution at e.g. "./local" for `lifecycle plan local`,
2453
+ // which then fell through to import-detection on an empty file set and failed
2454
+ // with "No lexicon detected" even though chant.config.ts lists the lexicons.
2455
+ const projectPath = match.compound ? "." : args.path;
2456
+ // `chant build --components --generate <lexicon>` (#563, generate mode)
2457
+ // discovers `Component` declarations, not lexicon resources — a project
2458
+ // made entirely of components has no reason to declare a chant lexicon
2459
+ // plugin at all. Load plugins best-effort here instead of exiting, so
2460
+ // generate mode works whether or not `chant.config.ts` names a lexicon.
2461
+ // `components status` (#568) is the same shape: a components-only project
2462
+ // may have no lexicon plugin, and `--live` reconciliation is opt-in, so
2463
+ // missing plugins there is "no live evidence" (a warning), not a hard exit.
2464
+ const isGenerateComponents = match.def.name === "build" && args.components && !!args.generate;
2465
+ const isComponentsStatus = match.def.name === "components status";
2466
+ // `components fan-out` (#2420) needs serializers only when it derives the
2467
+ // change signal itself (`--base` builds both refs). Reading one somebody
2468
+ // else already produced (`--from-affected`) touches no lexicon at all, so a
2469
+ // components-only project is not turned away for a step it will not run.
2470
+ const isFanOutFromFile = match.def.name === "components fan-out" && !args.base;
2471
+ // `emulator` (#920) is a property of the *configured* lexicons, not of any infra
2472
+ // file — a fresh/local project with no declarables still boots Floci. Load from
2473
+ // chant.config best-effort, like components status, rather than detectLexicon.
2474
+ const isEmulator = match.def.name === "emulator" || match.def.name.startsWith("emulator ");
2475
+ const plugins = match.def.requiresPlugins
2476
+ ? isGenerateComponents || isComponentsStatus || isEmulator || isFanOutFromFile
2477
+ ? await loadPlugins(await resolveProjectLexicons(resolve(projectPath)).catch(() => [])).catch(() => [])
2478
+ : match.def.name === "serve mcp" && (await isLexiconlessWorkspaceRoot(projectPath))
2479
+ ? [] // #2700 — runServeMcp loads the chant members' lexicons itself.
2480
+ : await loadPluginsOrExit(projectPath, args.lexicon)
2481
+ : [];
2482
+ const serializers = plugins.map((p) => p.serializer);
2483
+ const ctx = { args, plugins, serializers };
2484
+ await flushAndExit(await match.def.handler(ctx));
2485
+ }
2486
+ /**
2487
+ * Wait until a writable stream has flushed its buffer. `process.exit()` discards
2488
+ * data still buffered for an async sink (a pipe or file), truncating large output
2489
+ * at the ~64 KB pipe buffer — so `chant graph --format ir` piped into a consumer
2490
+ * loses everything past 64 KB and its JSON won't parse. A TTY writes
2491
+ * synchronously (`writableLength` stays 0), so this is a no-op there. Resolves on
2492
+ * `error`/`close` too, so a reader that closes early (EPIPE) can't hang exit.
2493
+ * Exported for testing.
2494
+ */
2495
+ export function waitForStreamDrain(stream) {
2496
+ return new Promise((resolve) => {
2497
+ const tick = () => {
2498
+ if (stream.writableLength === 0 || stream.writableEnded || stream.destroyed) {
2499
+ cleanup();
2500
+ resolve();
2501
+ return;
2502
+ }
2503
+ stream.once("drain", tick);
2504
+ };
2505
+ const stop = () => {
2506
+ cleanup();
2507
+ resolve();
2508
+ };
2509
+ const cleanup = () => {
2510
+ stream.off("drain", tick);
2511
+ stream.off("error", stop);
2512
+ stream.off("close", stop);
2513
+ };
2514
+ stream.once("error", stop);
2515
+ stream.once("close", stop);
2516
+ tick();
2517
+ });
2518
+ }
2519
+ /** Flush stdout+stderr, then exit — so a large piped payload isn't truncated. */
2520
+ async function flushAndExit(code) {
2521
+ await waitForStreamDrain(process.stdout);
2522
+ await waitForStreamDrain(process.stderr);
2523
+ process.exit(code);
2524
+ }
2525
+ // Only run main when executed directly, not when imported. Robust to symlinked
2526
+ // invocation paths — see isEntryPoint (a raw string compare silently no-ops the
2527
+ // whole CLI through the npm .bin shim / a symlinked checkout).
2528
+ const isMain = isEntryPoint(process.argv[1], import.meta.url);
2529
+ if (isMain) {
2530
+ main().catch(async (err) => {
2531
+ const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
2532
+ if (verbose && err instanceof Error && err.stack) {
2533
+ console.error(err.stack);
2534
+ }
2535
+ else {
2536
+ console.error(formatError({ message: err instanceof Error ? err.message : String(err) }));
2537
+ }
2538
+ await flushAndExit(1);
2539
+ });
2540
+ }