@intentius/chant 0.80.0 → 0.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/dist/audit/discover.d.ts +8 -16
  2. package/dist/audit/discover.d.ts.map +1 -1
  3. package/dist/audit/report-html.d.ts +5 -0
  4. package/dist/audit/report-html.d.ts.map +1 -1
  5. package/dist/audit/report-model.d.ts +13 -0
  6. package/dist/audit/report-model.d.ts.map +1 -1
  7. package/dist/audit/terraform-state.d.ts +4 -5
  8. package/dist/audit/terraform-state.d.ts.map +1 -1
  9. package/dist/cli/commands/audit.d.ts +25 -9
  10. package/dist/cli/commands/audit.d.ts.map +1 -1
  11. package/dist/cli/commands/check-lexicon.d.ts +8 -0
  12. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  13. package/dist/cli/commands/doctor.d.ts.map +1 -1
  14. package/dist/cli/commands/import-agents.d.ts.map +1 -1
  15. package/dist/cli/commands/init.d.ts.map +1 -1
  16. package/dist/cli/commands/lint.d.ts.map +1 -1
  17. package/dist/cli/commands/update.d.ts +6 -0
  18. package/dist/cli/commands/update.d.ts.map +1 -1
  19. package/dist/cli/commands/vendor.d.ts +5 -0
  20. package/dist/cli/commands/vendor.d.ts.map +1 -1
  21. package/dist/cli/handlers/build.d.ts.map +1 -1
  22. package/dist/cli/handlers/components.d.ts.map +1 -1
  23. package/dist/cli/handlers/dev.d.ts.map +1 -1
  24. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  25. package/dist/cli/handlers/init.d.ts.map +1 -1
  26. package/dist/cli/handlers/operator.d.ts +7 -0
  27. package/dist/cli/handlers/operator.d.ts.map +1 -1
  28. package/dist/cli/handlers/promote.d.ts +7 -4
  29. package/dist/cli/handlers/promote.d.ts.map +1 -1
  30. package/dist/cli/handlers/run-generate.d.ts.map +1 -1
  31. package/dist/cli/handlers/run.d.ts +4 -1
  32. package/dist/cli/handlers/run.d.ts.map +1 -1
  33. package/dist/cli/handlers/vendor.d.ts +8 -3
  34. package/dist/cli/handlers/vendor.d.ts.map +1 -1
  35. package/dist/cli/main.d.ts +12 -0
  36. package/dist/cli/main.d.ts.map +1 -1
  37. package/dist/cli/plugins.d.ts +12 -7
  38. package/dist/cli/plugins.d.ts.map +1 -1
  39. package/dist/cli/registry.d.ts +32 -0
  40. package/dist/cli/registry.d.ts.map +1 -1
  41. package/dist/codegen/fetch.d.ts +10 -0
  42. package/dist/codegen/fetch.d.ts.map +1 -1
  43. package/dist/components/cli-support.d.ts +3 -1
  44. package/dist/components/cli-support.d.ts.map +1 -1
  45. package/dist/components/discover.d.ts.map +1 -1
  46. package/dist/components/driver.d.ts +16 -2
  47. package/dist/components/driver.d.ts.map +1 -1
  48. package/dist/components/gate-plan.d.ts +40 -0
  49. package/dist/components/gate-plan.d.ts.map +1 -0
  50. package/dist/components/promote.d.ts +60 -7
  51. package/dist/components/promote.d.ts.map +1 -1
  52. package/dist/components/sandbox/driver.d.ts.map +1 -1
  53. package/dist/components/sandbox/run.d.ts.map +1 -1
  54. package/dist/components/verbs/build-archive.d.ts +22 -11
  55. package/dist/components/verbs/build-archive.d.ts.map +1 -1
  56. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  57. package/dist/config-static.d.ts +59 -0
  58. package/dist/config-static.d.ts.map +1 -0
  59. package/dist/config.d.ts +32 -10
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/content-digest.d.ts +17 -0
  62. package/dist/content-digest.d.ts.map +1 -0
  63. package/dist/discovery/files.d.ts +10 -5
  64. package/dist/discovery/files.d.ts.map +1 -1
  65. package/dist/discovery/fold-import.d.ts +20 -4
  66. package/dist/discovery/fold-import.d.ts.map +1 -1
  67. package/dist/discovery/index.d.ts.map +1 -1
  68. package/dist/discovery/sandbox/driver.d.ts +20 -0
  69. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  70. package/dist/discovery/sandbox/fork.d.ts +20 -0
  71. package/dist/discovery/sandbox/fork.d.ts.map +1 -1
  72. package/dist/discovery/walk.d.ts +119 -0
  73. package/dist/discovery/walk.d.ts.map +1 -0
  74. package/dist/graph-ir.d.ts +4 -1
  75. package/dist/graph-ir.d.ts.map +1 -1
  76. package/dist/join-key.d.ts +31 -0
  77. package/dist/join-key.d.ts.map +1 -0
  78. package/dist/lexicon-module.d.ts +51 -6
  79. package/dist/lexicon-module.d.ts.map +1 -1
  80. package/dist/lexicon.d.ts +58 -1
  81. package/dist/lexicon.d.ts.map +1 -1
  82. package/dist/lifecycle/build-ledger-store.d.ts.map +1 -1
  83. package/dist/lifecycle/digest.d.ts +5 -1
  84. package/dist/lifecycle/digest.d.ts.map +1 -1
  85. package/dist/lifecycle/gate-ledger.d.ts +20 -5
  86. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  87. package/dist/lifecycle/git.d.ts +64 -0
  88. package/dist/lifecycle/git.d.ts.map +1 -1
  89. package/dist/lifecycle/lease.d.ts +8 -1
  90. package/dist/lifecycle/lease.d.ts.map +1 -1
  91. package/dist/lifecycle/legacy-digest.d.ts +41 -8
  92. package/dist/lifecycle/legacy-digest.d.ts.map +1 -1
  93. package/dist/lifecycle/member-ledger.d.ts +67 -0
  94. package/dist/lifecycle/member-ledger.d.ts.map +1 -0
  95. package/dist/lifecycle/plan-digest.d.ts +4 -3
  96. package/dist/lifecycle/plan-digest.d.ts.map +1 -1
  97. package/dist/lifecycle/release-ledger.d.ts +18 -2
  98. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  99. package/dist/lifecycle/status.d.ts +90 -5
  100. package/dist/lifecycle/status.d.ts.map +1 -1
  101. package/dist/op/activities/activity-contracts.d.ts +32 -0
  102. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  103. package/dist/op/activities/index.d.ts +2 -0
  104. package/dist/op/activities/index.d.ts.map +1 -1
  105. package/dist/op/activities/propose-upgrade.d.ts +75 -0
  106. package/dist/op/activities/propose-upgrade.d.ts.map +1 -0
  107. package/dist/op/discover.d.ts.map +1 -1
  108. package/dist/op/gate-name.d.ts +7 -0
  109. package/dist/op/gate-name.d.ts.map +1 -1
  110. package/dist/op/gate-summary.d.ts +16 -0
  111. package/dist/op/gate-summary.d.ts.map +1 -1
  112. package/dist/op/gate.d.ts +16 -2
  113. package/dist/op/gate.d.ts.map +1 -1
  114. package/dist/project-root.d.ts +26 -0
  115. package/dist/project-root.d.ts.map +1 -1
  116. package/dist/workspace/__fixtures__/contract-repo.d.ts +37 -0
  117. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -0
  118. package/dist/workspace/__fixtures__/two-member-workspace.d.ts +11 -0
  119. package/dist/workspace/__fixtures__/two-member-workspace.d.ts.map +1 -0
  120. package/dist/workspace/checks/generated.d.ts +156 -0
  121. package/dist/workspace/checks/generated.d.ts.map +1 -0
  122. package/dist/workspace/checks/ledgers.d.ts +78 -0
  123. package/dist/workspace/checks/ledgers.d.ts.map +1 -0
  124. package/dist/workspace/checks/links.d.ts +25 -0
  125. package/dist/workspace/checks/links.d.ts.map +1 -0
  126. package/dist/workspace/checks/pipelines.d.ts +76 -0
  127. package/dist/workspace/checks/pipelines.d.ts.map +1 -0
  128. package/dist/workspace/checks.d.ts +161 -0
  129. package/dist/workspace/checks.d.ts.map +1 -0
  130. package/dist/workspace/compose-graph.d.ts +115 -0
  131. package/dist/workspace/compose-graph.d.ts.map +1 -0
  132. package/dist/workspace/compose-reports.d.ts +68 -0
  133. package/dist/workspace/compose-reports.d.ts.map +1 -0
  134. package/dist/workspace/declaration.d.ts +220 -0
  135. package/dist/workspace/declaration.d.ts.map +1 -0
  136. package/dist/workspace/declaration.schema.json +434 -0
  137. package/dist/workspace/generated-files.d.ts +65 -0
  138. package/dist/workspace/generated-files.d.ts.map +1 -0
  139. package/dist/workspace/glob.d.ts +13 -0
  140. package/dist/workspace/glob.d.ts.map +1 -0
  141. package/dist/workspace/graph-cli.d.ts +75 -0
  142. package/dist/workspace/graph-cli.d.ts.map +1 -0
  143. package/dist/workspace/init.d.ts +96 -0
  144. package/dist/workspace/init.d.ts.map +1 -0
  145. package/dist/workspace/jsonc.d.ts +38 -0
  146. package/dist/workspace/jsonc.d.ts.map +1 -0
  147. package/dist/workspace/kinds.d.ts +192 -0
  148. package/dist/workspace/kinds.d.ts.map +1 -0
  149. package/dist/workspace/lineage-check.d.ts +84 -0
  150. package/dist/workspace/lineage-check.d.ts.map +1 -0
  151. package/dist/workspace/lineage-cli.d.ts +31 -0
  152. package/dist/workspace/lineage-cli.d.ts.map +1 -0
  153. package/dist/workspace/lineage-init.d.ts +101 -0
  154. package/dist/workspace/lineage-init.d.ts.map +1 -0
  155. package/dist/workspace/lineage-lock.d.ts +258 -0
  156. package/dist/workspace/lineage-lock.d.ts.map +1 -0
  157. package/dist/workspace/lineage-merge.d.ts +14 -0
  158. package/dist/workspace/lineage-merge.d.ts.map +1 -0
  159. package/dist/workspace/lineage-migrations.d.ts +178 -0
  160. package/dist/workspace/lineage-migrations.d.ts.map +1 -0
  161. package/dist/workspace/lineage-update.d.ts +59 -0
  162. package/dist/workspace/lineage-update.d.ts.map +1 -0
  163. package/dist/workspace/lineage-upgrade-cli.d.ts +40 -0
  164. package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -0
  165. package/dist/workspace/lineage-upgrade.d.ts +146 -0
  166. package/dist/workspace/lineage-upgrade.d.ts.map +1 -0
  167. package/dist/workspace/lineage-vendor.d.ts +63 -0
  168. package/dist/workspace/lineage-vendor.d.ts.map +1 -0
  169. package/dist/workspace/lineage-version.d.ts +32 -0
  170. package/dist/workspace/lineage-version.d.ts.map +1 -0
  171. package/dist/workspace/links.d.ts +150 -0
  172. package/dist/workspace/links.d.ts.map +1 -0
  173. package/dist/workspace/ls.d.ts +99 -0
  174. package/dist/workspace/ls.d.ts.map +1 -0
  175. package/dist/workspace/member-commands.d.ts +139 -0
  176. package/dist/workspace/member-commands.d.ts.map +1 -0
  177. package/dist/workspace/member-handles.d.ts +54 -0
  178. package/dist/workspace/member-handles.d.ts.map +1 -0
  179. package/dist/workspace/member-pipeline.d.ts +143 -0
  180. package/dist/workspace/member-pipeline.d.ts.map +1 -0
  181. package/dist/workspace/member-run.d.ts +67 -0
  182. package/dist/workspace/member-run.d.ts.map +1 -0
  183. package/dist/workspace/reason-codes.d.ts +65 -0
  184. package/dist/workspace/reason-codes.d.ts.map +1 -0
  185. package/dist/workspace/records-cli.d.ts +28 -4
  186. package/dist/workspace/records-cli.d.ts.map +1 -1
  187. package/dist/workspace/records.d.ts.map +1 -1
  188. package/dist/workspace/root-refusal.d.ts +53 -0
  189. package/dist/workspace/root-refusal.d.ts.map +1 -0
  190. package/dist/workspace/status.d.ts +150 -0
  191. package/dist/workspace/status.d.ts.map +1 -0
  192. package/dist/workspace/template-manifest.d.ts +90 -0
  193. package/dist/workspace/template-manifest.d.ts.map +1 -0
  194. package/dist/workspace/tree.d.ts +36 -0
  195. package/dist/workspace/tree.d.ts.map +1 -0
  196. package/dist/workspace/trust/attestor.d.ts +67 -0
  197. package/dist/workspace/trust/attestor.d.ts.map +1 -0
  198. package/dist/workspace/trust/policy.d.ts +111 -0
  199. package/dist/workspace/trust/policy.d.ts.map +1 -0
  200. package/dist/workspace/trust/provenance.d.ts +67 -0
  201. package/dist/workspace/trust/provenance.d.ts.map +1 -0
  202. package/dist/workspace/trust/ssh-commit.d.ts +43 -0
  203. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -0
  204. package/dist/workspace/trust/test-repo.d.ts +42 -0
  205. package/dist/workspace/trust/test-repo.d.ts.map +1 -0
  206. package/dist/workspace/trust/verify-cli.d.ts +9 -0
  207. package/dist/workspace/trust/verify-cli.d.ts.map +1 -0
  208. package/dist/workspace/trust/verify.d.ts +66 -0
  209. package/dist/workspace/trust/verify.d.ts.map +1 -0
  210. package/dist/workspace/which-chant.d.ts +58 -0
  211. package/dist/workspace/which-chant.d.ts.map +1 -0
  212. package/dist/workspace/workspace-kinds.schema.json +133 -0
  213. package/package.json +2 -1
  214. package/src/audit/discover.ts +66 -78
  215. package/src/audit/report-html.ts +3 -1
  216. package/src/audit/report-model.ts +14 -1
  217. package/src/audit/terraform-state.test.ts +4 -9
  218. package/src/audit/terraform-state.ts +4 -5
  219. package/src/cli/commands/audit-truncation.test.ts +167 -0
  220. package/src/cli/commands/audit.ts +89 -60
  221. package/src/cli/commands/check-lexicon.ts +24 -0
  222. package/src/cli/commands/doctor.test.ts +30 -0
  223. package/src/cli/commands/doctor.ts +18 -0
  224. package/src/cli/commands/import-agents.ts +6 -2
  225. package/src/cli/commands/init.ts +22 -3
  226. package/src/cli/commands/lint.test.ts +17 -23
  227. package/src/cli/commands/lint.ts +24 -84
  228. package/src/cli/commands/update.ts +13 -4
  229. package/src/cli/commands/vendor.ts +11 -6
  230. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +38 -0
  231. package/src/cli/handlers/build-member.test.ts +127 -0
  232. package/src/cli/handlers/build.ts +35 -1
  233. package/src/cli/handlers/components.test.ts +127 -0
  234. package/src/cli/handlers/components.ts +70 -8
  235. package/src/cli/handlers/dev.ts +5 -3
  236. package/src/cli/handlers/fan-out.ts +9 -2
  237. package/src/cli/handlers/init.ts +54 -1
  238. package/src/cli/handlers/operator.test.ts +68 -0
  239. package/src/cli/handlers/operator.ts +37 -9
  240. package/src/cli/handlers/promote.test.ts +118 -2
  241. package/src/cli/handlers/promote.ts +82 -16
  242. package/src/cli/handlers/run-generate-member.test.ts +83 -0
  243. package/src/cli/handlers/run-generate.test.ts +6 -8
  244. package/src/cli/handlers/run-generate.ts +36 -1
  245. package/src/cli/handlers/run.test.ts +47 -0
  246. package/src/cli/handlers/run.ts +28 -5
  247. package/src/cli/handlers/vendor.ts +147 -43
  248. package/src/cli/main.test.ts +105 -1
  249. package/src/cli/main.ts +230 -17
  250. package/src/cli/plugins.ts +17 -17
  251. package/src/cli/registry.ts +32 -0
  252. package/src/cli/static-config-read.test.ts +208 -0
  253. package/src/codegen/fetch.test.ts +63 -1
  254. package/src/codegen/fetch.ts +30 -1
  255. package/src/components/cli-support.ts +6 -1
  256. package/src/components/discover.test.ts +27 -57
  257. package/src/components/discover.ts +13 -68
  258. package/src/components/driver.test.ts +78 -1
  259. package/src/components/driver.ts +43 -7
  260. package/src/components/gate-plan.ts +53 -0
  261. package/src/components/promote.test.ts +276 -2
  262. package/src/components/promote.ts +119 -15
  263. package/src/components/sandbox/driver.ts +8 -8
  264. package/src/components/sandbox/run.ts +4 -1
  265. package/src/components/verbs/build-archive.ts +27 -21
  266. package/src/components/verbs/run-agent.ts +3 -5
  267. package/src/config-static.test.ts +136 -0
  268. package/src/config-static.ts +232 -0
  269. package/src/config.test.ts +2 -2
  270. package/src/config.ts +48 -15
  271. package/src/content-digest.test.ts +120 -0
  272. package/src/content-digest.ts +21 -0
  273. package/src/discovery/files.test.ts +10 -10
  274. package/src/discovery/files.ts +25 -81
  275. package/src/discovery/fold-import.ts +49 -5
  276. package/src/discovery/index.ts +1 -0
  277. package/src/discovery/sandbox/driver.ts +73 -35
  278. package/src/discovery/sandbox/fork-diagnostic.test.ts +136 -13
  279. package/src/discovery/sandbox/fork.ts +83 -43
  280. package/src/discovery/sandbox/path-lexicon-multifile.test.ts +285 -0
  281. package/src/discovery/walk.test.ts +263 -0
  282. package/src/discovery/walk.ts +334 -0
  283. package/src/effect-receipt.ts +2 -2
  284. package/src/graph-ir.ts +4 -1
  285. package/src/join-key.test.ts +25 -0
  286. package/src/join-key.ts +39 -0
  287. package/src/lexicon-module.ts +108 -10
  288. package/src/lexicon.ts +79 -1
  289. package/src/lifecycle/build-ledger-store.ts +11 -10
  290. package/src/lifecycle/digest.ts +9 -5
  291. package/src/lifecycle/gate-ledger.test.ts +20 -0
  292. package/src/lifecycle/gate-ledger.ts +28 -6
  293. package/src/lifecycle/git.test.ts +13 -1
  294. package/src/lifecycle/git.ts +221 -176
  295. package/src/lifecycle/lease.ts +25 -10
  296. package/src/lifecycle/legacy-digest.test.ts +115 -23
  297. package/src/lifecycle/legacy-digest.ts +60 -19
  298. package/src/lifecycle/member-ledger.test.ts +319 -0
  299. package/src/lifecycle/member-ledger.ts +145 -0
  300. package/src/lifecycle/plan-digest.ts +7 -7
  301. package/src/lifecycle/release-ledger.test.ts +20 -0
  302. package/src/lifecycle/release-ledger.ts +23 -7
  303. package/src/lifecycle/status.test.ts +151 -1
  304. package/src/lifecycle/status.ts +228 -7
  305. package/src/op/activities/activity-contracts.ts +37 -0
  306. package/src/op/activities/index.ts +10 -0
  307. package/src/op/activities/propose-upgrade.ts +206 -0
  308. package/src/op/discover.test.ts +14 -4
  309. package/src/op/discover.ts +19 -27
  310. package/src/op/gate-name.ts +8 -0
  311. package/src/op/gate-summary.test.ts +14 -0
  312. package/src/op/gate-summary.ts +25 -2
  313. package/src/op/gate.ts +36 -7
  314. package/src/op/generate-pipeline.test.ts +14 -5
  315. package/src/project-root.test.ts +66 -1
  316. package/src/project-root.ts +48 -0
  317. package/src/workspace/__fixtures__/contract-repo.ts +100 -0
  318. package/src/workspace/__fixtures__/two-member-workspace.ts +35 -0
  319. package/src/workspace/behold-kinds.test.ts +162 -0
  320. package/src/workspace/check-contract.test.ts +127 -0
  321. package/src/workspace/check.schema.json +347 -0
  322. package/src/workspace/checks/generated.test.ts +287 -0
  323. package/src/workspace/checks/generated.ts +475 -0
  324. package/src/workspace/checks/ledgers.test.ts +139 -0
  325. package/src/workspace/checks/ledgers.ts +246 -0
  326. package/src/workspace/checks/links.ts +183 -0
  327. package/src/workspace/checks/pipelines.test.ts +133 -0
  328. package/src/workspace/checks/pipelines.ts +225 -0
  329. package/src/workspace/checks-repo.test.ts +71 -0
  330. package/src/workspace/checks.test.ts +450 -0
  331. package/src/workspace/checks.ts +461 -0
  332. package/src/workspace/compose-graph.test.ts +146 -0
  333. package/src/workspace/compose-graph.ts +228 -0
  334. package/src/workspace/compose-reports.test.ts +109 -0
  335. package/src/workspace/compose-reports.ts +186 -0
  336. package/src/workspace/declaration.schema.json +434 -0
  337. package/src/workspace/declaration.test.ts +347 -0
  338. package/src/workspace/declaration.ts +623 -0
  339. package/src/workspace/generated-files.test.ts +114 -0
  340. package/src/workspace/generated-files.ts +94 -0
  341. package/src/workspace/glob.ts +49 -0
  342. package/src/workspace/graph-cli.ts +220 -0
  343. package/src/workspace/graph-contract.test.ts +204 -0
  344. package/src/workspace/graph.schema.json +662 -0
  345. package/src/workspace/init.test.ts +223 -0
  346. package/src/workspace/init.ts +585 -0
  347. package/src/workspace/jsonc.test.ts +65 -0
  348. package/src/workspace/jsonc.ts +231 -0
  349. package/src/workspace/kinds.test.ts +288 -0
  350. package/src/workspace/kinds.ts +506 -0
  351. package/src/workspace/lineage-check.ts +264 -0
  352. package/src/workspace/lineage-cli.ts +114 -0
  353. package/src/workspace/lineage-init.test.ts +231 -0
  354. package/src/workspace/lineage-init.ts +365 -0
  355. package/src/workspace/lineage-lock.test.ts +224 -0
  356. package/src/workspace/lineage-lock.ts +357 -0
  357. package/src/workspace/lineage-merge.ts +44 -0
  358. package/src/workspace/lineage-migrations.test.ts +178 -0
  359. package/src/workspace/lineage-migrations.ts +343 -0
  360. package/src/workspace/lineage-update.ts +160 -0
  361. package/src/workspace/lineage-upgrade-cli.ts +151 -0
  362. package/src/workspace/lineage-upgrade.test.ts +474 -0
  363. package/src/workspace/lineage-upgrade.ts +624 -0
  364. package/src/workspace/lineage-vendor.test.ts +126 -0
  365. package/src/workspace/lineage-vendor.ts +215 -0
  366. package/src/workspace/lineage-version.ts +127 -0
  367. package/src/workspace/links.test.ts +344 -0
  368. package/src/workspace/links.ts +331 -0
  369. package/src/workspace/ls-contract.test.ts +200 -0
  370. package/src/workspace/ls.schema.json +190 -0
  371. package/src/workspace/ls.ts +254 -0
  372. package/src/workspace/member-commands.e2e.test.ts +244 -0
  373. package/src/workspace/member-commands.test.ts +217 -0
  374. package/src/workspace/member-commands.ts +540 -0
  375. package/src/workspace/member-handles.test.ts +76 -0
  376. package/src/workspace/member-handles.ts +228 -0
  377. package/src/workspace/member-pipeline.test.ts +135 -0
  378. package/src/workspace/member-pipeline.ts +317 -0
  379. package/src/workspace/member-run.ts +146 -0
  380. package/src/workspace/read-contract.test.ts +129 -0
  381. package/src/workspace/reason-codes.test.ts +113 -0
  382. package/src/workspace/reason-codes.ts +81 -0
  383. package/src/workspace/records-cli.ts +86 -14
  384. package/src/workspace/records-contract.test.ts +5 -0
  385. package/src/workspace/records.schema.json +32 -2
  386. package/src/workspace/records.ts +3 -2
  387. package/src/workspace/root-refusal.ts +97 -0
  388. package/src/workspace/status-contract.test.ts +308 -0
  389. package/src/workspace/status.schema.json +210 -0
  390. package/src/workspace/status.ts +412 -0
  391. package/src/workspace/template-manifest.test.ts +79 -0
  392. package/src/workspace/template-manifest.ts +221 -0
  393. package/src/workspace/tree.ts +132 -0
  394. package/src/workspace/trust/attestor.ts +93 -0
  395. package/src/workspace/trust/policy.ts +306 -0
  396. package/src/workspace/trust/provenance.ts +181 -0
  397. package/src/workspace/trust/ssh-commit.ts +138 -0
  398. package/src/workspace/trust/test-repo.ts +138 -0
  399. package/src/workspace/trust/trust.test.ts +397 -0
  400. package/src/workspace/trust/verify-cli.ts +56 -0
  401. package/src/workspace/trust/verify.ts +194 -0
  402. package/src/workspace/which-chant.test.ts +117 -0
  403. package/src/workspace/which-chant.ts +151 -0
  404. package/src/workspace/workspace-kinds.schema.json +133 -0
  405. package/dist/components/unbound-gate-approval.d.ts +0 -24
  406. package/dist/components/unbound-gate-approval.d.ts.map +0 -1
  407. package/dist/discovery/convergence.d.ts +0 -97
  408. package/dist/discovery/convergence.d.ts.map +0 -1
  409. package/src/cli/commands/audit-walk-warnings.test.ts +0 -156
  410. package/src/components/unbound-gate-approval.test.ts +0 -82
  411. package/src/components/unbound-gate-approval.ts +0 -51
  412. package/src/discovery/convergence.test.ts +0 -231
  413. package/src/discovery/convergence.ts +0 -399
  414. package/src/op/discover-convergence.test.ts +0 -70
package/src/cli/main.ts CHANGED
@@ -6,6 +6,7 @@ import { formatSuccess, formatError } from "./format";
6
6
  import { loadPlugins, resolveProjectLexicons } from "./plugins";
7
7
  import { resolveCommand, type CommandDef, type ParsedArgs } from "./registry";
8
8
  import { loadChantConfigUpward } from "../config";
9
+ import { findProjectRoot, findWorkspaceRoot } from "../project-root";
9
10
  import { validateLexiconConfig, formatLexiconConfigProblems } from "../lexicon-config";
10
11
  import { armSandboxConfigEvaluation } from "../config-sandbox";
11
12
  import { armSandboxPolicyExecution } from "../lint/policy-import";
@@ -27,7 +28,7 @@ import { runCarveStatus } from "./handlers/carve-status";
27
28
  import { runLifecycleSnapshot, runLifecycleShow, runLifecycleDiff, runLifecycleRollback, runLifecyclePlan, runLifecycleAffected, runLifecycleLog, runLifecycleTeardown, runLifecycleWhoami, runLifecycleUnknown } from "./handlers/lifecycle";
28
29
  import { runComponentsStatus, runComponentsReleaseRecord, runComponentsExport, runComponentsUnknown } from "./handlers/components";
29
30
  import { runComponentsFanOut } from "./handlers/fan-out";
30
- import { runComponentsPromote, runComponentsRollback } from "./handlers/promote";
31
+ import { runComponentsPromote, runComponentsRollback, runComponentsRedeploy } from "./handlers/promote";
31
32
  import { runScenarioCheck, runScenarioUnknown } from "./handlers/scenario";
32
33
  import { runGraph } from "./handlers/graph";
33
34
  import { runExplain } from "./handlers/explain";
@@ -95,6 +96,9 @@ const BOOLEAN_FLAGS = new Set([
95
96
  "--durable-requests",
96
97
  "--skip-mcp",
97
98
  "--current",
99
+ "--allow-code",
100
+ "--root-only",
101
+ "--generated",
98
102
  ]);
99
103
 
100
104
  /**
@@ -207,9 +211,9 @@ export function parseArgs(args: string[]): ParsedArgs {
207
211
  if (v !== "source" && v !== "live") throw new Error(`--overlay-anchor must be 'source' or 'live', got '${v}'`);
208
212
  result.overlayAnchor = v;
209
213
  } else if (arg === "--from") {
210
- // Shared by `migrate --from <lexicon>`, `import --from <env>` and
211
- // `components promote --from <env>`; the commands never run together,
212
- // so one field carries all three.
214
+ // Shared by `migrate --from <lexicon>`, `import --from <env>`,
215
+ // `components promote --from <env>` and `init --from <repo>@<ref>`;
216
+ // the commands never run together, so one field carries all four.
213
217
  result.migrateFrom = args[++i];
214
218
  } else if (arg === "--kustomize") {
215
219
  // `chant import --kustomize <dir>` (#1548): render the overlay, import
@@ -298,6 +302,8 @@ export function parseArgs(args: string[]): ParsedArgs {
298
302
  result.opsSpec = args[++i];
299
303
  } else if (arg === "--dump-outputs") {
300
304
  result.dumpOutputs = args[++i];
305
+ } else if (arg === "--digest-file") {
306
+ result.digestFile = args[++i];
301
307
  } else if (arg === "--seed-outputs") {
302
308
  (result.seedOutputs ??= []).push(args[++i]);
303
309
  } else if (arg === "--detail") {
@@ -359,6 +365,10 @@ export function parseArgs(args: string[]): ParsedArgs {
359
365
  if (!result.kind || result.kind.startsWith("-")) throw new Error("--kind needs a kind file: --kind <path>");
360
366
  } else if (arg === "--current") {
361
367
  result.current = true;
368
+ } else if (arg === "--require") {
369
+ // `chant workspace records|verify --require attested` (#2547)
370
+ result.require = args[++i];
371
+ if (!result.require || result.require.startsWith("-")) throw new Error("--require needs a provenance level: --require attested");
362
372
  } else if (arg === "--ambient") {
363
373
  result.ambient = true;
364
374
  } else if (arg === "--check-live") {
@@ -379,6 +389,7 @@ export function parseArgs(args: string[]): ParsedArgs {
379
389
  result.component = args[++i];
380
390
  } else if (arg === "--digest") {
381
391
  result.digest = args[++i];
392
+ if (result.digest !== undefined) (result.digests ??= []).push(result.digest);
382
393
  } else if (arg === "--git-sha") {
383
394
  result.gitSha = args[++i];
384
395
  } else if (arg === "--run-id") {
@@ -445,6 +456,24 @@ export function parseArgs(args: string[]): ParsedArgs {
445
456
  } else if (arg === "--agent") {
446
457
  // #2508 — record the approval as an agent's rather than a person's.
447
458
  result.agent = true;
459
+ } else if (arg === "--allow-code") {
460
+ // #2550 — `chant workspace upgrade` runs a template's code migrations
461
+ // only when asked to.
462
+ result.allowCode = true;
463
+ } else if (arg === "--root-only") {
464
+ // #2537 — `chant build` and `chant lint` at a declared workspace root
465
+ // run on the root project alone instead of refusing with WSP000.
466
+ result.rootOnly = true;
467
+ } else if (arg === "--generated") {
468
+ // #2641 — `chant workspace check --generated` runs each declared
469
+ // generator and compares its output with the file in the tree.
470
+ result.generated = true;
471
+ } else if (arg === "--member") {
472
+ // #2537 — `chant workspace build|lint|audit|graph --member <name>`.
473
+ // Repeatable, and a comma list works too.
474
+ const value = args[++i];
475
+ if (!value || value.startsWith("-")) throw new Error("--member needs a member or group name: --member <name>");
476
+ result.members = [...(result.members ?? []), ...value.split(",").map((m) => m.trim()).filter(Boolean)];
448
477
  } else if (arg === "--allow-same-origin") {
449
478
  // chant#2384 — record a resolution the same-origin rule would refuse,
450
479
  // deliberately. Flagged on the record, not just accepted quietly.
@@ -488,6 +517,19 @@ export function parseArgs(args: string[]): ParsedArgs {
488
517
  i++;
489
518
  }
490
519
 
520
+ // #2603 — `--promote-to` (#2575) adds a job to the pipeline that generate
521
+ // mode synthesizes; no other command or mode reads it. Checked here, once
522
+ // the whole command line is known, rather than in the build handler, so
523
+ // `chant build --promote-to prod` and `chant run --promote-to prod` both
524
+ // fail instead of running as if the flag were absent. A lexicon-mounted
525
+ // command that takes its own `--promote-to` still gets it: `main` tries the
526
+ // plugin commands before rethrowing a parse error.
527
+ if (result.promoteTo && !(result.command === "build" && result.components && result.generate)) {
528
+ throw new Error(
529
+ "--promote-to needs build --components --generate <lexicon>: it adds a promote job to the generated CI pipeline, and only generate mode emits one.",
530
+ );
531
+ }
532
+
491
533
  return result;
492
534
  }
493
535
 
@@ -506,6 +548,10 @@ Usage:
506
548
 
507
549
  Commands:
508
550
  init Initialize a new chant project
551
+ (--from <repo>@<ref>[#<member>] copies a template
552
+ repository and records its lineage; --param
553
+ <name>=<value> sets a parameter the template's
554
+ chant.template.json declares, repeatable)
509
555
  init lexicon <name> Scaffold a new lexicon plugin project
510
556
  build Build infrastructure from specification files
511
557
  (--components --generate github|gitlab|forgejo:
@@ -513,7 +559,10 @@ Commands:
513
559
  pipeline that triggers each discovered component's
514
560
  own deploy in wave order, instead of a normal
515
561
  lexicon build)
562
+ At a declared workspace root it refuses with WSP000;
563
+ --root-only builds the root project alone
516
564
  lint Check specifications for issues
565
+ (at a declared workspace root: WSP000 unless --root-only)
517
566
  list List discovered entities
518
567
  describe Show the effective config for one component
519
568
  explain Summarize discovered entities (--format markdown|json|okf;
@@ -521,6 +570,8 @@ Commands:
521
570
  concept per entity + index.md; -o <dir> writes the
522
571
  bundle tree, otherwise JSON path→content on stdout)
523
572
  vendor Pull pinned, checksummed patterns into your repo
573
+ (pull [name] | check | migrate; migrate moves
574
+ vendor.json into .chant/workspace.lock.json)
524
575
  import Import external template into TypeScript
525
576
  (--agents re-expresses this machine's agent config as
526
577
  chant code instead of reading a template file)
@@ -639,12 +690,75 @@ Ops:
639
690
  predicts the account. The level reaches the engine
640
691
  verbatim; without the flag nothing is asked (#2377)
641
692
 
642
- Workspace (first-test slice, #2546):
643
- workspace records --kind <kind file> [--current] [--at <rev>] [--json]
693
+ Workspace (level 1, #2524):
694
+ workspace init [dir] Propose a chant.workspace.json from the projects and
695
+ packages already in the repository, print it with the
696
+ directories that would leave the root project, and
697
+ write it only on confirmation (--yes writes without
698
+ asking; --name <name> names the workspace; --verbose
699
+ lists every file leaving the root project)
700
+ workspace ls [dir] List the declaration's members and example groups.
701
+ A member that can't be read is listed with a reason
702
+ code and still exits 0. --at <rev> reads a commit's
703
+ git objects; --json prints the read-contract document
704
+ workspace status <env> [dir] [--compare-to <env>] [--json]
705
+ Each member's latest release in <env>, as digest and
706
+ git SHA, read from its ledger on the local
707
+ chant/lifecycle branch (_members/<member>/ or the flat
708
+ layout). --compare-to <env> shows a second environment
709
+ beside it and marks the members whose digests differ.
710
+ Read only; never fetches. --json prints the
711
+ read-contract document
712
+ workspace records --kind <kind file> [--current] [--at <rev>] [--base <rev>] [--require attested] [--json]
644
713
  Read the records a record kind locates, validated
645
714
  against its schema, with reason codes for invalid
646
715
  ones. --current leaves out superseded records; --at
647
- reads a commit's git objects. Needs no workspace file
716
+ reads a commit's git objects. Needs no workspace file.
717
+ Each record reports its provenance level, judged by
718
+ the signers at --base (default: the target branch);
719
+ --require attested exits 2 if any record is not
720
+ attested
721
+ workspace verify [--base <rev>] [--head <rev>] [--require attested]
722
+ Check the commits in base..head against the signers
723
+ and roles read from base. A change to the signers file
724
+ or .chant/trust.json needs a signature by a signer
725
+ trusted at base. Does nothing without a signers file
726
+ workspace lineage [--json]
727
+ Show each scope in .chant/workspace.lock.json: its
728
+ template and pin, locally edited files and open
729
+ manual steps. Needs no workspace file
730
+ workspace lineage resolve <path>
731
+ Close a manual step once the file is merged by hand
732
+ workspace upgrade [<scope>] [--to <ref>] [--allow-code] [--dry-run] [--output <file>]
733
+ Bring a lineage scope to a newer template version: fetch
734
+ it, migrate and merge per file in a worktree, run build,
735
+ lint and workspace check there, then gate on the digest
736
+ of the patch (chant approve workspace-upgrade <scope>).
737
+ A second run with the approval applies the patch
738
+ workspace check [--at <rev>] [--json] [--format stylish|json|sarif] [--generated]
739
+ Fail on an unreadable lineage lock or an open manual
740
+ step, and, in a declared workspace, on a WSP check of
741
+ the declaration, member ledgers, pipelines or
742
+ generated files. --generated runs declared generators
743
+ and compares their output. Needs no workspace file.
744
+ --at reads a commit's git objects; --format json
745
+ prints the read-contract document
746
+ workspace build [dir] [--member <name>] [-o <dir>] [--dry-run]
747
+ Build every chant member and example project, each with
748
+ its own chant, one process per toolchain. -o <dir>
749
+ writes <dir>/<member>.json; --member narrows the run;
750
+ --dry-run prints which chant runs which project
751
+ workspace lint [dir] [--format stylish|json|sarif] [--member <name>]
752
+ Lint every chant member and example project with its
753
+ own chant; sarif writes one run per member
754
+ workspace audit [dir] [--json] [--member <name>]
755
+ Audit each chant member with its own .chant-audit.json;
756
+ every finding carries a member field
757
+ workspace graph [dir] [--at <rev>] [--member <name>] [-o <file>]
758
+ Compose each chant member's chant graph into one IR,
759
+ with <member>/<id> ids and groups.byMember: the
760
+ read-contract document. --at <rev> runs each member's
761
+ source as it was at that commit
648
762
 
649
763
  Lifecycle (alias: lc):
650
764
  lifecycle snapshot <env> Query API, save metadata to orphan branch
@@ -710,6 +824,10 @@ Component release ledger + status:
710
824
  from its recorded digest (--component <name>
711
825
  [--digest <sha256:...>]; defaults to the release
712
826
  before the current one; --dry-run prints the plan)
827
+ components redeploy <env> Redeploy the release an environment's ledger
828
+ records as current, after a deploy that failed
829
+ partway (--component <name> [--digest <sha256:...>];
830
+ --dry-run prints the plan; gates still apply)
713
831
 
714
832
  Lexicon development:
715
833
  dev generate Generate lexicon artifacts (+ validate + coverage)
@@ -752,7 +870,8 @@ Options:
752
870
  re-evaluates for that environment (build + graph), and
753
871
  drives organizational policy. Must be in chant.config
754
872
  \`environments\` when declared.
755
- -t, --template <name> Init template (e.g. node-pipeline, docker-build)
873
+ -t, --template <name> Init template (e.g. node-pipeline, docker-build);
874
+ records its lineage in .chant/workspace.lock.json
756
875
  --skill <name> Init: install only this skill from the lexicon
757
876
  --skip-mcp Init: scaffold without writing the project's .mcp.json
758
877
  --fix Auto-fix fixable issues (lint command)
@@ -824,18 +943,23 @@ Options:
824
943
  docs). Default: off (also settable via
825
944
  chant.config.ts's build.sandbox: true; #1045)
826
945
  --param <name=value> (build, graph, run --components, components fan-out,
827
- components promote, components rollback) Bind a
946
+ components promote, components rollback,
947
+ components redeploy) Bind a
828
948
  declared build-time parameter (chant.config.ts's buildParams)
829
949
  to a value, for source to read as params.<name>
830
950
  (#1064) instead of process.env — repeatable.
831
951
  Distinct from the AWS lexicon's deploy-time
832
952
  Parameter(): this resolves before synthesis, so it
833
953
  can change which resources are produced at all.
834
- Highest precedence.
954
+ Highest precedence. With init --from, it sets a
955
+ template parameter that the template's
956
+ chant.template.json declares instead (#2627).
835
957
  --params-file <path> (build, graph, run --components, components fan-out,
836
- components promote, components rollback) JSON file
958
+ components promote, components rollback,
959
+ components redeploy) JSON file
837
960
  of { "name": value } build-time parameter values
838
961
  (#1064). Second precedence, after --param.
962
+ init --from refuses it: pass --param instead.
839
963
 
840
964
  Examples:
841
965
  chant build ./infra/
@@ -969,6 +1093,47 @@ async function loadPluginsOrExit(path: string): Promise<import("../lexicon").Lex
969
1093
  return plugins;
970
1094
  }
971
1095
 
1096
+ /** Whether `def` must run without evaluating the project's `chant.config.ts` (chant#2591). */
1097
+ function commandRunsNoConfig(def: CommandDef, args: ParsedArgs): boolean {
1098
+ return typeof def.runsNoConfig === "function" ? def.runsNoConfig(args) : def.runsNoConfig === true;
1099
+ }
1100
+
1101
+ /**
1102
+ * Run one level-0 command line in this process and return its exit code
1103
+ * (#2537). `chant workspace member-run` calls it once per member, from inside
1104
+ * the member's directory, so each member is built, linted, audited or graphed
1105
+ * as `chant <verb> .` would do it there, while members that share a toolchain
1106
+ * share one process. It is main()'s dispatch without the help, the root
1107
+ * refusal and the lexicon command groups: the config is loaded, `--env` is
1108
+ * checked, plugins are loaded when the command needs them, and the handler
1109
+ * runs. A `process.exit` inside (loadPluginsOrExit's, say) is the caller's to
1110
+ * catch.
1111
+ */
1112
+ export async function runCommandInProcess(argv: string[]): Promise<number> {
1113
+ const args = parseArgs(argv);
1114
+ const match = resolveCommand(args, commandRegistry);
1115
+ if (!match) {
1116
+ console.error(formatError({ message: `Unknown command: ${args.command}` }));
1117
+ return 1;
1118
+ }
1119
+ if (args.env) process.env[ENV_VAR] = args.env;
1120
+ let loadedConfig;
1121
+ try {
1122
+ // chant#2618 — `workspace audit` reaches `audit` through here, once per
1123
+ // member. A `runsNoConfig` command skips the load, as it does in main().
1124
+ if (!commandRunsNoConfig(match.def, args)) loadedConfig = await loadChantConfigUpward(resolve(args.path));
1125
+ } catch {
1126
+ // A project with no config is the handler's to report, as in main().
1127
+ }
1128
+ const envErr = unknownEnvError(args.env, loadedConfig?.config.environments);
1129
+ if (envErr) {
1130
+ console.error(formatError({ message: envErr, hint: "Declare it in chant.config `environments`, or omit --env." }));
1131
+ return 1;
1132
+ }
1133
+ const plugins = match.def.requiresPlugins ? await loadPluginsOrExit(match.compound ? "." : args.path) : [];
1134
+ return match.def.handler({ args, plugins, serializers: plugins.map((p) => p.serializer) });
1135
+ }
1136
+
972
1137
  // ── Command registry ──────────────────────────────────────────────
973
1138
 
974
1139
  /**
@@ -989,8 +1154,10 @@ export const commandRegistry: CommandDef[] = [
989
1154
  { name: "describe", handler: runDescribe },
990
1155
  { name: "explain", handler: runExplain },
991
1156
  { name: "search", handler: runSearch },
992
- { name: "import", handler: runImport },
993
- { name: "audit", handler: runAudit },
1157
+ // chant#2591 — `import --agents` and `audit` read chant.config statically
1158
+ // and never evaluate it (chant#2589 for audit, which audits code it must not run).
1159
+ { name: "import", handler: runImport, runsNoConfig: (args) => args.agents === true },
1160
+ { name: "audit", handler: runAudit, runsNoConfig: true },
994
1161
  { name: "migrate", handler: runMigrate },
995
1162
  // Read-only Terraform peelability advisor (#214). Compound so "advise" lands
996
1163
  // in args.path; the estate dir comes from --from. No plugins, no project.
@@ -1009,7 +1176,7 @@ export const commandRegistry: CommandDef[] = [
1009
1176
  // Status read over a tree of carve manifests (#2038): the contract a
1010
1177
  // renderer replaces its own walk-and-guess discovery with. Read-only.
1011
1178
  { name: "carve status", handler: runCarveStatus },
1012
- { name: "init", handler: runInit },
1179
+ { name: "init", handler: runInit, runsNoConfig: true },
1013
1180
  { name: "init lexicon", handler: runInitLexicon },
1014
1181
  { name: "update", handler: runUpdate },
1015
1182
  { name: "doctor", handler: runDoctor },
@@ -1017,7 +1184,7 @@ export const commandRegistry: CommandDef[] = [
1017
1184
  // Dev subcommands
1018
1185
  { name: "dev generate", requiresPlugins: true, handler: runDevGenerate },
1019
1186
  { name: "dev publish", requiresPlugins: true, handler: runDevPublish },
1020
- { name: "dev onboard", handler: runDevOnboard },
1187
+ { name: "dev onboard", handler: runDevOnboard, runsNoConfig: true },
1021
1188
  { name: "dev check-lexicon", handler: runDevCheckLexicon },
1022
1189
  { name: "dev surface-diff", handler: runDevSurfaceDiff },
1023
1190
  { name: "dev pinned-upgrade", handler: runDevPinnedUpgrade },
@@ -1043,6 +1210,23 @@ export const commandRegistry: CommandDef[] = [
1043
1210
  // Workspace reads (#2524). Imported on first use, so a level-0 command never
1044
1211
  // loads anything under workspace/ (#2525 rule 5, pinned by #2526's goldens).
1045
1212
  { name: "workspace records", handler: async (ctx) => (await import("../workspace/records-cli")).runWorkspaceRecords(ctx) },
1213
+ { name: "workspace init", handler: async (ctx) => (await import("../workspace/init")).runWorkspaceInit(ctx) },
1214
+ { name: "workspace ls", handler: async (ctx) => (await import("../workspace/ls")).runWorkspaceLs(ctx) },
1215
+ { name: "workspace status", handler: async (ctx) => (await import("../workspace/status")).runWorkspaceStatus(ctx) },
1216
+ { name: "workspace lineage", handler: async (ctx) => (await import("../workspace/lineage-cli")).runWorkspaceLineage(ctx) },
1217
+ { name: "workspace upgrade", handler: async (ctx) => (await import("../workspace/lineage-upgrade-cli")).runWorkspaceUpgrade(ctx) },
1218
+ // #2641 — workspace check reads member configs statically and never runs one.
1219
+ { name: "workspace check", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/lineage-check")).runWorkspaceCheck(ctx) },
1220
+ // #2537 — per-member commands. Each member runs under its own chant, one
1221
+ // process per toolchain identity; `member-run` is that process's entry.
1222
+ { name: "workspace build", handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "build") },
1223
+ { name: "workspace lint", handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "lint") },
1224
+ // chant#2618 — audit runs no project code, at the workspace level too.
1225
+ { name: "workspace audit", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "audit") },
1226
+ { name: "workspace graph", handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "graph") },
1227
+ // Each unit decides for itself whether its config is loaded (runCommandInProcess).
1228
+ { name: "workspace member-run", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-run")).runWorkspaceMemberRun(ctx, runCommandInProcess) },
1229
+ { name: "workspace verify", handler: async (ctx) => (await import("../workspace/trust/verify-cli")).runWorkspaceVerify(ctx) },
1046
1230
 
1047
1231
  // State subcommands
1048
1232
  { name: "lifecycle snapshot", requiresPlugins: true, handler: runLifecycleSnapshot },
@@ -1067,6 +1251,7 @@ export const commandRegistry: CommandDef[] = [
1067
1251
  { name: "components export", handler: runComponentsExport },
1068
1252
  { name: "components promote", handler: runComponentsPromote },
1069
1253
  { name: "components rollback", handler: runComponentsRollback },
1254
+ { name: "components redeploy", handler: runComponentsRedeploy },
1070
1255
 
1071
1256
  // Local emulators of configured lexicons (#920). Compound so the action word
1072
1257
  // lands in args.path (not consumed as a project dir) and projectPath is forced ".".
@@ -1147,10 +1332,16 @@ async function main(): Promise<void> {
1147
1332
  // subdirectory build/command (`chant build src/<stack> --env prod`) the
1148
1333
  // declared `environments` almost always live in the root `chant.config.ts`,
1149
1334
  // not `args.path` itself.
1335
+ //
1336
+ // chant#2591 — a command marked `runsNoConfig` skips this load: it must not
1337
+ // run the project's `chant.config.ts` (see `CommandDef.runsNoConfig`). Such a
1338
+ // command gets no `--env` check against the declared environments either.
1339
+ const earlyMatch = resolveCommand(args, commandRegistry);
1340
+ const runsNoConfig = earlyMatch != null && commandRunsNoConfig(earlyMatch.def, args);
1150
1341
  const projectPath0 = resolve(args.path === "." ? "." : args.path);
1151
1342
  let loadedConfig;
1152
1343
  try {
1153
- loadedConfig = await loadChantConfigUpward(projectPath0);
1344
+ if (!runsNoConfig) loadedConfig = await loadChantConfigUpward(projectPath0);
1154
1345
  initRuntime();
1155
1346
  } catch {
1156
1347
  // Config may not exist yet (e.g. `chant init`)
@@ -1164,7 +1355,7 @@ async function main(): Promise<void> {
1164
1355
  process.exit(1);
1165
1356
  }
1166
1357
 
1167
- const match = resolveCommand(args, commandRegistry);
1358
+ const match = earlyMatch;
1168
1359
  if (!match) {
1169
1360
  // chant #1078 — not one of core's own commands; check whether a lexicon
1170
1361
  // mounted a command group under this name before giving up. This is the
@@ -1182,6 +1373,28 @@ async function main(): Promise<void> {
1182
1373
  process.exit(1);
1183
1374
  }
1184
1375
 
1376
+ // #2537 (#2524 D0) — at the root of a declared workspace, `build` and
1377
+ // `lint` refuse with WSP000 unless `--root-only` or `rootOnly: true` says
1378
+ // to run on the root project alone. Both lookups only test whether files
1379
+ // exist; the workspace code loads only when this project is a declared root.
1380
+ if (match.def.name === "build" || match.def.name === "lint") {
1381
+ const target = resolve(args.path);
1382
+ const workspace = findWorkspaceRoot(target);
1383
+ if (workspace && findProjectRoot(target) === workspace.dir) {
1384
+ const { guardRootCommand } = await import("../workspace/root-refusal");
1385
+ const refused = guardRootCommand({
1386
+ verb: match.def.name,
1387
+ target,
1388
+ workspaceDir: workspace.dir,
1389
+ rootOnly: args.rootOnly === true || loadedConfig?.config.rootOnly === true,
1390
+ });
1391
+ if (refused !== undefined) {
1392
+ await flushAndExit(refused);
1393
+ return;
1394
+ }
1395
+ }
1396
+ }
1397
+
1185
1398
  // For compound commands (e.g. "run list", "lifecycle plan <env>"), the first
1186
1399
  // positional is a subcommand argument — an environment, op, or lexicon name —
1187
1400
  // not a project path. Plugins always load from the cwd; the handler reads its
@@ -1,29 +1,29 @@
1
- import { importLexiconModule, lexiconModulePath, lexiconNames } from "../lexicon-module";
1
+ import { importLexiconModule, lexiconModulePath, lexiconNames, registerLexiconDeclarations } from "../lexicon-module";
2
+ import { readLexiconDeclarationsStatically, type StaticLexiconRead } from "../config-static";
3
+ export { unknownPathLexiconsNotice } from "../config-static";
2
4
  import { createRequire } from "node:module";
3
5
  import { dirname, join } from "node:path";
4
6
  import { existsSync, readFileSync } from "node:fs";
5
7
  import { isLexiconPlugin, type LexiconPlugin } from "../lexicon";
6
- import { loadChantConfig, loadChantConfigUpward } from "../config";
7
- import { findProjectConfig } from "../project-root";
8
+ import { loadChantConfigUpward } from "../config";
8
9
  import { findInfraFiles, detectLexicons } from "../index";
9
10
  import { checkConflicts, describeConflict } from "./conflict-check";
10
11
 
11
12
  /**
12
- * chant#2578 — load the chant.config nearest `dir` (walking up) so the
13
- * lexicons it declares by path are recorded (../lexicon-module.ts), for a
14
- * command that does not otherwise read the config. With no config there is
15
- * nothing to record. A config that fails to load records nothing either, and
16
- * the command keeps its package behaviour; the commands that need a valid
17
- * config report its errors themselves.
13
+ * chant#2591 — record the lexicons the chant.config nearest `dir` declares by
14
+ * path (../lexicon-module.ts), for a command that does not otherwise read the
15
+ * config: `init --force`, `dev onboard` and `import --agents`.
16
+ *
17
+ * The config is read statically (../config-static.ts) and never evaluated,
18
+ * so these commands run no project code to learn it. When the `lexicons`
19
+ * value cannot be read that way, nothing is recorded, every lexicon keeps its
20
+ * package behaviour, and the returned read carries the reason; the caller
21
+ * prints {@link unknownPathLexiconsNotice} for it.
18
22
  */
19
- export async function recordProjectLexicons(dir: string): Promise<void> {
20
- const { dir: projectDir, configPath } = findProjectConfig(dir);
21
- if (configPath === undefined) return;
22
- try {
23
- await loadChantConfig(projectDir);
24
- } catch {
25
- // See above: an unloadable config changes nothing here.
26
- }
23
+ export function recordProjectLexicons(dir: string): StaticLexiconRead {
24
+ const read = readLexiconDeclarationsStatically(dir);
25
+ if (read.status === "read") registerLexiconDeclarations(read.entries, dirname(read.configPath));
26
+ return read;
27
27
  }
28
28
 
29
29
  /**
@@ -129,6 +129,8 @@ export interface ParsedArgs {
129
129
  * ignore it.
130
130
  */
131
131
  namespace?: string;
132
+ /** `chant workspace upgrade --allow-code` (#2550) — run migrations whose body is the template's own code. */
133
+ allowCode?: boolean;
132
134
  /** `chant lifecycle rollback --dry-run` — compute the rollback delta and print it; open no PR, push nothing, leave no branch. */
133
135
  dryRun?: boolean;
134
136
  /** `chant lifecycle teardown <env> --yes` — execute the planned deletion
@@ -283,6 +285,25 @@ export interface ParsedArgs {
283
285
  kind?: string;
284
286
  /** `chant workspace records --current` (#2546): leave out records a closed record supersedes. */
285
287
  current?: boolean;
288
+ /** `chant workspace records|verify --require attested` (#2547): the provenance level a gate requires. */
289
+ require?: string;
290
+ /**
291
+ * `chant build --root-only` and `chant lint --root-only` (#2537): run on the
292
+ * root project of a declared workspace, members left out, instead of
293
+ * refusing with `WSP000`.
294
+ */
295
+ rootOnly?: boolean;
296
+ /**
297
+ * `chant workspace check --generated` (#2641): run each declared generator
298
+ * and compare its output with the file in the tree. Off by default, since
299
+ * generators run member code.
300
+ */
301
+ generated?: boolean;
302
+ /**
303
+ * `chant workspace build|lint|audit|graph --member <name>` (#2537): run only
304
+ * the named members or example groups. Repeatable, and a comma list works too.
305
+ */
306
+ members?: string[];
286
307
  /**
287
308
  * `chant search "<q>" --ambient --live --env <name>` (#1278) — also report
288
309
  * resources of a kind this estate manages that exist in the account without
@@ -325,6 +346,8 @@ export interface ParsedArgs {
325
346
  component?: string;
326
347
  /** `chant components release record --digest <sha256:...>` (#568) — artifact digest to record, joining this release to the build archive/ledger. Also `chant components export --digest <manifestDigest>` (#929) — a build archive manifest digest to export directly, bypassing env/component resolution. */
327
348
  digest?: string;
349
+ /** Every `--digest` value, in order (#2602). `chant components promote --digest <component>=<sha256:...>` is repeatable, one per component; the other commands read the single {@link digest}. */
350
+ digests?: string[];
328
351
  /** `chant components release record --git-sha <sha>` (#568) — git commit the deploy was built from. */
329
352
  gitSha?: string;
330
353
  /** `chant components release record --run-id <id>` (#568) — orchestrator/CI run identifier. */
@@ -341,6 +364,8 @@ export interface ParsedArgs {
341
364
  noReleaseRecord?: boolean;
342
365
  /** `chant run --components <name> --dump-outputs <file>` — after the run, write the accumulated cross-component/cross-stack outputs (JSON, keyed by component name) to `<file>`, for a downstream job to `--seed-outputs`. */
343
366
  dumpOutputs?: string;
367
+ /** `chant run --components <name> --digest-file <file>` (#2602) — after a successful run, write one `<component>=<digest>` line per release the run recorded to `<file>`, the form `chant components promote --digest` takes, so a generated promote job promotes exactly the release its pipeline run built. Written empty when nothing was recorded. */
368
+ digestFile?: string;
344
369
  /** `chant run --components <name> --seed-outputs <file>` (repeatable) — before the run, load each JSON outputs file (as written by `--dump-outputs`) and seed cross-component/cross-stack resolution with it, so a `stackOutput()`/`@<dep>.publish.*` reference to a component that ran in an earlier job resolves. */
345
370
  seedOutputs?: string[];
346
371
  /** `chant build --fold` (#1022/#1023, epic #1019) — opt-in: fold source modules statically instead of importing/running them; folds resource constructors and composite factory calls, falling back to run per-file for anything the folder can't represent (a cross-file-only reference, a re-export, `export default`, …). Also settable project-wide via `chant.config.ts`'s `build.fold: true`; the flag always wins when set. Default (flag omitted): the existing run path, unchanged. */
@@ -401,6 +426,13 @@ export interface CommandDef {
401
426
  name: string;
402
427
  /** If true, load lexicon plugins before calling handler */
403
428
  requiresPlugins?: boolean;
429
+ /**
430
+ * chant#2591, chant#2589 — the command never evaluates the project's
431
+ * `chant.config.ts`, so `main` does not load it before dispatch either. Such
432
+ * a command reads what it needs from the config statically
433
+ * (../config-static.ts). A function decides per invocation.
434
+ */
435
+ runsNoConfig?: boolean | ((args: ParsedArgs) => boolean);
404
436
  /** Command handler — returns exit code */
405
437
  handler: (ctx: CommandContext) => Promise<number>;
406
438
  }