@intentius/chant 0.101.0 → 0.102.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 (427) hide show
  1. package/dist/agents/checks.d.ts.map +1 -1
  2. package/dist/attrref.d.ts.map +1 -1
  3. package/dist/audit/discover.d.ts.map +1 -1
  4. package/dist/audit/nginx.d.ts.map +1 -1
  5. package/dist/audit/prior-art.d.ts +48 -0
  6. package/dist/audit/prior-art.d.ts.map +1 -1
  7. package/dist/behaviour-kinds.d.ts.map +1 -1
  8. package/dist/builder.d.ts.map +1 -1
  9. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  10. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  11. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  12. package/dist/cli/commands/import.d.ts +8 -0
  13. package/dist/cli/commands/import.d.ts.map +1 -1
  14. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  15. package/dist/cli/commands/init.d.ts +19 -0
  16. package/dist/cli/commands/init.d.ts.map +1 -1
  17. package/dist/cli/commands/onboard.d.ts +9 -0
  18. package/dist/cli/commands/onboard.d.ts.map +1 -1
  19. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  20. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  21. package/dist/cli/handlers/dev.d.ts.map +1 -1
  22. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  23. package/dist/cli/handlers/misc.d.ts.map +1 -1
  24. package/dist/cli/handlers/operator.d.ts +9 -0
  25. package/dist/cli/handlers/operator.d.ts.map +1 -1
  26. package/dist/cli/handlers/run.d.ts.map +1 -1
  27. package/dist/cli/lsp/server.d.ts.map +1 -1
  28. package/dist/cli/main.d.ts.map +1 -1
  29. package/dist/cli/mcp/server.d.ts.map +1 -1
  30. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  31. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  32. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  33. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  34. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  35. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  36. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  37. package/dist/cli/mcp/workspace-tools.d.ts +1 -1
  38. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  39. package/dist/cli/registry.d.ts +11 -2
  40. package/dist/cli/registry.d.ts.map +1 -1
  41. package/dist/codegen/fetch.d.ts.map +1 -1
  42. package/dist/codegen/naming.d.ts.map +1 -1
  43. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  44. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  45. package/dist/codegen/registry.d.ts.map +1 -1
  46. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  47. package/dist/components/capability.d.ts.map +1 -1
  48. package/dist/components/driver.d.ts.map +1 -1
  49. package/dist/components/fan-out.d.ts.map +1 -1
  50. package/dist/components/starter-plugin.d.ts.map +1 -1
  51. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  52. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  53. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  54. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  55. package/dist/components/verbs/sign.d.ts.map +1 -1
  56. package/dist/components/verbs/verify.d.ts.map +1 -1
  57. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  58. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  59. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  60. package/dist/composite.d.ts.map +1 -1
  61. package/dist/config.d.ts +19 -7
  62. package/dist/config.d.ts.map +1 -1
  63. package/dist/declarable.d.ts +16 -0
  64. package/dist/declarable.d.ts.map +1 -1
  65. package/dist/discovery/cache.d.ts.map +1 -1
  66. package/dist/discovery/fold-import.d.ts +15 -5
  67. package/dist/discovery/fold-import.d.ts.map +1 -1
  68. package/dist/discovery/param-deps.d.ts +16 -0
  69. package/dist/discovery/param-deps.d.ts.map +1 -1
  70. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  71. package/dist/discovery/specifier-resolve.d.ts +37 -0
  72. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  73. package/dist/errors.d.ts.map +1 -1
  74. package/dist/fold/fold.d.ts +3 -1
  75. package/dist/fold/fold.d.ts.map +1 -1
  76. package/dist/graph-detail.d.ts.map +1 -1
  77. package/dist/graph-ir.d.ts.map +1 -1
  78. package/dist/graph-layout.d.ts.map +1 -1
  79. package/dist/import/base-parser.d.ts.map +1 -1
  80. package/dist/import/embedded.d.ts +7 -0
  81. package/dist/import/embedded.d.ts.map +1 -1
  82. package/dist/import/parser-options.d.ts +14 -0
  83. package/dist/import/parser-options.d.ts.map +1 -0
  84. package/dist/import/parser.d.ts +17 -0
  85. package/dist/import/parser.d.ts.map +1 -1
  86. package/dist/kubectl-context.d.ts.map +1 -1
  87. package/dist/lexicon-output.d.ts.map +1 -1
  88. package/dist/lexicon-schema.d.ts +3 -3
  89. package/dist/lexicon.d.ts +55 -3
  90. package/dist/lexicon.d.ts.map +1 -1
  91. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  92. package/dist/lifecycle/gate-ledger.d.ts +15 -0
  93. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  94. package/dist/lifecycle/git.d.ts.map +1 -1
  95. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  96. package/dist/lifecycle/observe.d.ts.map +1 -1
  97. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  98. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  99. package/dist/lifecycle/scenario.d.ts.map +1 -1
  100. package/dist/lifecycle/status.d.ts.map +1 -1
  101. package/dist/lifecycle/work-lease.d.ts +61 -2
  102. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  103. package/dist/lint/config.d.ts +8 -8
  104. package/dist/lint/engine.d.ts +6 -0
  105. package/dist/lint/engine.d.ts.map +1 -1
  106. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  107. package/dist/op/activities/activity-contracts.d.ts +11 -11
  108. package/dist/op/activities/apply.d.ts +79 -9
  109. package/dist/op/activities/apply.d.ts.map +1 -1
  110. package/dist/op/activities/decide.d.ts.map +1 -1
  111. package/dist/op/activities/index.d.ts +1 -1
  112. package/dist/op/activities/index.d.ts.map +1 -1
  113. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  114. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  115. package/dist/op/activity-contract.d.ts +1 -1
  116. package/dist/op/activity-failure.d.ts.map +1 -1
  117. package/dist/op/activity-profiles.d.ts.map +1 -1
  118. package/dist/op/builders.d.ts.map +1 -1
  119. package/dist/op/composites/apply-op.d.ts +12 -5
  120. package/dist/op/composites/apply-op.d.ts.map +1 -1
  121. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  122. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  123. package/dist/op/decide-backend.d.ts.map +1 -1
  124. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  125. package/dist/op/emulator-lifecycle.d.ts +21 -2
  126. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  127. package/dist/op/gate-approval.d.ts +5 -1
  128. package/dist/op/gate-approval.d.ts.map +1 -1
  129. package/dist/op/gate-wait.d.ts.map +1 -1
  130. package/dist/op/gate.d.ts +19 -3
  131. package/dist/op/gate.d.ts.map +1 -1
  132. package/dist/op/index.d.ts +2 -0
  133. package/dist/op/index.d.ts.map +1 -1
  134. package/dist/op/local-executor.d.ts +6 -0
  135. package/dist/op/local-executor.d.ts.map +1 -1
  136. package/dist/op/operator.d.ts.map +1 -1
  137. package/dist/op/run-context.d.ts +39 -0
  138. package/dist/op/run-context.d.ts.map +1 -0
  139. package/dist/op/run-live.d.ts.map +1 -1
  140. package/dist/op/runtimes/local.d.ts.map +1 -1
  141. package/dist/op/source-archive.d.ts.map +1 -1
  142. package/dist/op/steward-beside.d.ts.map +1 -1
  143. package/dist/op/steward-points.d.ts.map +1 -1
  144. package/dist/op/steward.d.ts.map +1 -1
  145. package/dist/op/types.d.ts +8 -3
  146. package/dist/op/types.d.ts.map +1 -1
  147. package/dist/op/work-lease-run.d.ts +24 -4
  148. package/dist/op/work-lease-run.d.ts.map +1 -1
  149. package/dist/project-root.d.ts.map +1 -1
  150. package/dist/provenance.d.ts +21 -0
  151. package/dist/provenance.d.ts.map +1 -1
  152. package/dist/pseudo-parameter.d.ts.map +1 -1
  153. package/dist/reconcile.d.ts.map +1 -1
  154. package/dist/secret-materialization.d.ts.map +1 -1
  155. package/dist/terraform/emit-source.d.ts.map +1 -1
  156. package/dist/terraform/parse.d.ts.map +1 -1
  157. package/dist/testing.d.ts.map +1 -1
  158. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  159. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  160. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  161. package/dist/workspace/agent-cli.d.ts +5 -0
  162. package/dist/workspace/agent-cli.d.ts.map +1 -1
  163. package/dist/workspace/box-factory.d.ts +73 -0
  164. package/dist/workspace/box-factory.d.ts.map +1 -0
  165. package/dist/workspace/changes.d.ts.map +1 -1
  166. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  167. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  168. package/dist/workspace/checks.d.ts +5 -0
  169. package/dist/workspace/checks.d.ts.map +1 -1
  170. package/dist/workspace/compose-graph.d.ts +10 -0
  171. package/dist/workspace/compose-graph.d.ts.map +1 -1
  172. package/dist/workspace/conformance/index.d.ts +67 -6
  173. package/dist/workspace/conformance/index.d.ts.map +1 -1
  174. package/dist/workspace/conformance/vitest.d.ts +12 -3
  175. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  176. package/dist/workspace/conformance/writer.d.ts +368 -0
  177. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  178. package/dist/workspace/decide.d.ts +1 -1
  179. package/dist/workspace/decide.d.ts.map +1 -1
  180. package/dist/workspace/declaration.d.ts +91 -4
  181. package/dist/workspace/declaration.d.ts.map +1 -1
  182. package/dist/workspace/declaration.schema.json +234 -5
  183. package/dist/workspace/generated-files.d.ts.map +1 -1
  184. package/dist/workspace/graph-cache.d.ts.map +1 -1
  185. package/dist/workspace/graph-cli.d.ts +2 -0
  186. package/dist/workspace/graph-cli.d.ts.map +1 -1
  187. package/dist/workspace/identity.d.ts +111 -0
  188. package/dist/workspace/identity.d.ts.map +1 -0
  189. package/dist/workspace/intent-cli.d.ts +7 -4
  190. package/dist/workspace/intent-cli.d.ts.map +1 -1
  191. package/dist/workspace/intent-record.d.ts +8 -1
  192. package/dist/workspace/intent-record.d.ts.map +1 -1
  193. package/dist/workspace/intent.d.ts +149 -5
  194. package/dist/workspace/intent.d.ts.map +1 -1
  195. package/dist/workspace/kinds.d.ts +18 -4
  196. package/dist/workspace/kinds.d.ts.map +1 -1
  197. package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
  198. package/dist/workspace/lineage-lock.d.ts +2 -2
  199. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  200. package/dist/workspace/links.d.ts.map +1 -1
  201. package/dist/workspace/points.d.ts.map +1 -1
  202. package/dist/workspace/principal-classes.d.ts +114 -0
  203. package/dist/workspace/principal-classes.d.ts.map +1 -0
  204. package/dist/workspace/reason-codes.d.ts +21 -1
  205. package/dist/workspace/reason-codes.d.ts.map +1 -1
  206. package/dist/workspace/record-assets.d.ts.map +1 -1
  207. package/dist/workspace/records-checkout.d.ts +54 -0
  208. package/dist/workspace/records-checkout.d.ts.map +1 -0
  209. package/dist/workspace/records-cli.d.ts +27 -1
  210. package/dist/workspace/records-cli.d.ts.map +1 -1
  211. package/dist/workspace/records-close.d.ts +1 -1
  212. package/dist/workspace/records-close.d.ts.map +1 -1
  213. package/dist/workspace/records-since.d.ts.map +1 -1
  214. package/dist/workspace/records-write.d.ts +5 -4
  215. package/dist/workspace/records-write.d.ts.map +1 -1
  216. package/dist/workspace/records.d.ts +15 -0
  217. package/dist/workspace/records.d.ts.map +1 -1
  218. package/dist/workspace/runs-cli.d.ts +164 -0
  219. package/dist/workspace/runs-cli.d.ts.map +1 -0
  220. package/dist/workspace/runs.d.ts +423 -0
  221. package/dist/workspace/runs.d.ts.map +1 -0
  222. package/dist/workspace/source-block.d.ts +1 -1
  223. package/dist/workspace/source-block.d.ts.map +1 -1
  224. package/dist/workspace/status-gates.d.ts +15 -3
  225. package/dist/workspace/status-gates.d.ts.map +1 -1
  226. package/dist/workspace/status.d.ts +10 -0
  227. package/dist/workspace/status.d.ts.map +1 -1
  228. package/dist/workspace/symbols.d.ts +52 -0
  229. package/dist/workspace/symbols.d.ts.map +1 -0
  230. package/dist/workspace/trailer-joins.d.ts +46 -0
  231. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  232. package/dist/workspace/trailers.d.ts +89 -0
  233. package/dist/workspace/trailers.d.ts.map +1 -0
  234. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  235. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  236. package/dist/workspace/trust/seal.d.ts +33 -0
  237. package/dist/workspace/trust/seal.d.ts.map +1 -1
  238. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  239. package/dist/workspace/work-cli.d.ts +39 -3
  240. package/dist/workspace/work-cli.d.ts.map +1 -1
  241. package/dist/workspace/work-evidence.d.ts +1 -1
  242. package/dist/workspace/work-evidence.d.ts.map +1 -1
  243. package/dist/workspace/work.d.ts +26 -1
  244. package/dist/workspace/work.d.ts.map +1 -1
  245. package/dist/workspace/workspace-principals.schema.json +60 -0
  246. package/dist/workspace/write-scope.d.ts +79 -19
  247. package/dist/workspace/write-scope.d.ts.map +1 -1
  248. package/dist/yaml.d.ts +21 -39
  249. package/dist/yaml.d.ts.map +1 -1
  250. package/package.json +2 -2
  251. package/src/audit/prior-art.ts +15 -0
  252. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  253. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  254. package/src/cli/commands/carve-emit.ts +5 -19
  255. package/src/cli/commands/check-lexicon.test.ts +62 -1
  256. package/src/cli/commands/check-lexicon.ts +36 -6
  257. package/src/cli/commands/import-live.test.ts +18 -0
  258. package/src/cli/commands/import-parser-options.test.ts +133 -0
  259. package/src/cli/commands/import.ts +21 -3
  260. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  261. package/src/cli/commands/init.test.ts +8 -1
  262. package/src/cli/commands/init.ts +23 -8
  263. package/src/cli/commands/lint.test.ts +37 -0
  264. package/src/cli/commands/onboard.test.ts +53 -3
  265. package/src/cli/commands/onboard.ts +52 -4
  266. package/src/cli/commands/pinned-upgrade.ts +73 -33
  267. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  268. package/src/cli/handlers/components.ts +2 -2
  269. package/src/cli/handlers/dev.ts +8 -6
  270. package/src/cli/handlers/lifecycle.test.ts +67 -0
  271. package/src/cli/handlers/lifecycle.ts +6 -5
  272. package/src/cli/handlers/misc.ts +2 -0
  273. package/src/cli/handlers/operator.ts +87 -3
  274. package/src/cli/handlers/run.test.ts +111 -0
  275. package/src/cli/handlers/run.ts +85 -24
  276. package/src/cli/handlers/scenario.ts +2 -2
  277. package/src/cli/main.test.ts +1 -0
  278. package/src/cli/main.ts +65 -11
  279. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  280. package/src/cli/mcp/workspace-tools.ts +29 -2
  281. package/src/cli/registry.ts +11 -2
  282. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  283. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  284. package/src/codegen/pinned-upgrade.test.ts +104 -0
  285. package/src/codegen/pinned-upgrade.ts +250 -56
  286. package/src/codegen/testdata/postgres-tags.json +242 -0
  287. package/src/config.test.ts +21 -0
  288. package/src/config.ts +15 -0
  289. package/src/declarable.test.ts +21 -0
  290. package/src/declarable.ts +19 -0
  291. package/src/discovery/fold-composite.test.ts +41 -5
  292. package/src/discovery/fold-import.test.ts +129 -0
  293. package/src/discovery/fold-import.ts +643 -131
  294. package/src/discovery/fold-package-composite.test.ts +264 -0
  295. package/src/discovery/fold-specifiers.test.ts +191 -0
  296. package/src/discovery/param-deps.test.ts +66 -1
  297. package/src/discovery/param-deps.ts +45 -0
  298. package/src/discovery/specifier-resolve.ts +344 -0
  299. package/src/fold/fold.test.ts +39 -1
  300. package/src/fold/fold.ts +83 -9
  301. package/src/fold-provenance.test.ts +140 -0
  302. package/src/graph-ir.test.ts +83 -0
  303. package/src/graph-ir.ts +29 -0
  304. package/src/import/embedded.test.ts +20 -0
  305. package/src/import/embedded.ts +13 -0
  306. package/src/import/parser-options.ts +46 -0
  307. package/src/import/parser.ts +20 -0
  308. package/src/lexicon.ts +55 -3
  309. package/src/lifecycle/gate-ledger.ts +16 -0
  310. package/src/lifecycle/observe.test.ts +18 -0
  311. package/src/lifecycle/observe.ts +6 -4
  312. package/src/lifecycle/snapshot.ts +2 -2
  313. package/src/lifecycle/work-lease.test.ts +1 -1
  314. package/src/lifecycle/work-lease.ts +93 -2
  315. package/src/lint/engine.test.ts +55 -0
  316. package/src/lint/engine.ts +30 -4
  317. package/src/lint/output-docs.test.ts +59 -56
  318. package/src/op/activities/apply.test.ts +189 -5
  319. package/src/op/activities/apply.ts +230 -8
  320. package/src/op/activities/index.ts +3 -0
  321. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  322. package/src/op/activities/lexicon-upgrade.ts +154 -51
  323. package/src/op/composites/apply-op.ts +12 -5
  324. package/src/op/composites/composites.test.ts +30 -3
  325. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  326. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  327. package/src/op/emulator-lifecycle.test.ts +23 -0
  328. package/src/op/emulator-lifecycle.ts +52 -14
  329. package/src/op/gate-approval.test.ts +74 -0
  330. package/src/op/gate-approval.ts +5 -1
  331. package/src/op/gate.ts +31 -5
  332. package/src/op/index.ts +2 -0
  333. package/src/op/local-executor.test.ts +15 -0
  334. package/src/op/local-executor.ts +40 -12
  335. package/src/op/local-output.ts +1 -1
  336. package/src/op/operator.ts +4 -0
  337. package/src/op/run-context.test.ts +141 -0
  338. package/src/op/run-context.ts +51 -0
  339. package/src/op/runtimes/local.test.ts +14 -0
  340. package/src/op/runtimes/local.ts +2 -0
  341. package/src/op/steward-beside.ts +2 -0
  342. package/src/op/types.ts +8 -3
  343. package/src/op/work-lease-run.test.ts +47 -0
  344. package/src/op/work-lease-run.ts +73 -11
  345. package/src/provenance.ts +35 -0
  346. package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
  347. package/src/workspace/agent-cli.ts +7 -3
  348. package/src/workspace/agent.schema.json +22 -0
  349. package/src/workspace/box-factory.test.ts +320 -0
  350. package/src/workspace/box-factory.ts +103 -0
  351. package/src/workspace/changes.schema.json +12 -20
  352. package/src/workspace/changes.ts +4 -1
  353. package/src/workspace/checks/boxes.test.ts +2 -0
  354. package/src/workspace/checks.ts +29 -5
  355. package/src/workspace/compose-graph.ts +7 -0
  356. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +27 -0
  357. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +95 -0
  358. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +132 -0
  359. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +48 -0
  360. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +108 -0
  361. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  362. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  363. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +578 -0
  364. package/src/workspace/conformance/conformance.e2e.test.ts +35 -3
  365. package/src/workspace/conformance/index.mjs +30 -3
  366. package/src/workspace/conformance/index.ts +103 -15
  367. package/src/workspace/conformance/vitest.ts +44 -2
  368. package/src/workspace/conformance/writer-conformance.e2e.test.ts +131 -0
  369. package/src/workspace/conformance/writer.test.ts +156 -0
  370. package/src/workspace/conformance/writer.ts +880 -0
  371. package/src/workspace/decide.ts +7 -1
  372. package/src/workspace/declaration.schema.json +234 -5
  373. package/src/workspace/declaration.ts +174 -10
  374. package/src/workspace/graph-cli.ts +5 -2
  375. package/src/workspace/graph.schema.json +247 -0
  376. package/src/workspace/identity.test.ts +196 -0
  377. package/src/workspace/identity.ts +186 -0
  378. package/src/workspace/intent-cli.ts +64 -10
  379. package/src/workspace/intent-record.schema.json +208 -0
  380. package/src/workspace/intent-record.ts +35 -1
  381. package/src/workspace/intent-why.test.ts +274 -0
  382. package/src/workspace/intent.schema.json +718 -7
  383. package/src/workspace/intent.test.ts +11 -2
  384. package/src/workspace/intent.ts +495 -32
  385. package/src/workspace/kinds.ts +44 -37
  386. package/src/workspace/points-write.schema.json +1 -0
  387. package/src/workspace/principal-classes.test.ts +175 -0
  388. package/src/workspace/principal-classes.ts +307 -0
  389. package/src/workspace/reason-codes.test.ts +11 -3
  390. package/src/workspace/reason-codes.ts +24 -1
  391. package/src/workspace/records-amend.schema.json +2 -0
  392. package/src/workspace/records-checkout.ts +106 -0
  393. package/src/workspace/records-cli.ts +103 -11
  394. package/src/workspace/records-close.schema.json +1 -0
  395. package/src/workspace/records-new.schema.json +2 -0
  396. package/src/workspace/records-review.schema.json +2 -0
  397. package/src/workspace/records-uncommitted.test.ts +171 -0
  398. package/src/workspace/records-write.ts +28 -6
  399. package/src/workspace/records.schema.json +72 -1
  400. package/src/workspace/records.ts +27 -0
  401. package/src/workspace/runs-cli.ts +381 -0
  402. package/src/workspace/runs-write.schema.json +583 -0
  403. package/src/workspace/runs.schema.json +810 -0
  404. package/src/workspace/runs.test.ts +242 -0
  405. package/src/workspace/runs.ts +709 -0
  406. package/src/workspace/status-contract.test.ts +5 -0
  407. package/src/workspace/status-gates.ts +22 -8
  408. package/src/workspace/status.schema.json +127 -2
  409. package/src/workspace/status.ts +21 -1
  410. package/src/workspace/symbols.ts +180 -0
  411. package/src/workspace/trailer-joins.test.ts +171 -0
  412. package/src/workspace/trailer-joins.ts +82 -0
  413. package/src/workspace/trailers.ts +148 -0
  414. package/src/workspace/trust/seal.ts +52 -1
  415. package/src/workspace/work-cli.e2e.test.ts +28 -1
  416. package/src/workspace/work-cli.ts +133 -8
  417. package/src/workspace/work-evidence.schema.json +2 -0
  418. package/src/workspace/work-history.schema.json +73 -1
  419. package/src/workspace/work-history.test.ts +48 -5
  420. package/src/workspace/work-kind-fields.test.ts +154 -0
  421. package/src/workspace/work-lease.schema.json +14 -1
  422. package/src/workspace/work.ts +82 -0
  423. package/src/workspace/workspace-principals.schema.json +60 -0
  424. package/src/workspace/write-scope.test.ts +128 -2
  425. package/src/workspace/write-scope.ts +170 -45
  426. package/src/yaml.test.ts +111 -1
  427. package/src/yaml.ts +141 -549
@@ -1,7 +1,7 @@
1
1
  import { lexiconNames } from "../../lexicon-module";
2
- import { resolve, dirname } from "node:path";
2
+ import { resolve, dirname, basename } from "node:path";
3
3
  import { writeFileSync, mkdirSync, readFileSync } from "node:fs";
4
- import { loadChantConfig, resolveAutoReleaseDisabled, type ChantConfig } from "../../config";
4
+ import { loadChantConfig, resolveAutoReleaseDisabled, InvalidChantConfigError, type ChantConfig } from "../../config";
5
5
  import { discoverOps, discoverStewards } from "../../op/discover";
6
6
  import { stewardWorkHolder } from "../../op/work-lease-run";
7
7
  import type { OpConfig } from "../../op/types";
@@ -108,10 +108,12 @@ function refuseDurableComponentSubcommand(what: string, hint: string): number {
108
108
  /**
109
109
  * Resolve the one runtime this invocation talks to.
110
110
  *
111
- * `--on <name>` picks the named lexicon's `opRuntime` (`../../lexicon.ts`);
112
- * without it, core's built-in `local` provider runs the Op in this process.
113
- * Every `chant run` subcommand goes through whichever comes back, so there is
114
- * one dispatch path rather than a branch per runtime.
111
+ * `--on <name>` picks the named lexicon's `opRuntime` (`../../lexicon.ts`).
112
+ * Without it, `run.on` in `chant.config.ts` does (#2523), and without either,
113
+ * core's built-in `local` provider runs the Op in this process. `local`, from
114
+ * either place, names the built-in provider. Every `chant run` subcommand goes
115
+ * through whichever comes back, so there is one dispatch path rather than a
116
+ * branch per runtime.
115
117
  *
116
118
  * A lexicon already loaded into the command context wins the lookup — that is
117
119
  * how a test hands in a stub, and how a command that loaded plugins for its
@@ -121,22 +123,20 @@ function refuseDurableComponentSubcommand(what: string, hint: string): number {
121
123
  *
122
124
  * Returns `undefined` after printing an actionable error — an unconfigured
123
125
  * name is answered with the configured list, a configured lexicon that hosts
124
- * nothing is named outright.
126
+ * nothing is named outright. A `run.on` default gets the same messages as
127
+ * `--on`, labelled `run.on` and the config file instead of `--on`.
125
128
  */
126
129
  async function resolveOpRuntime(ctx: CommandContext): Promise<OpRuntimeProvider | undefined> {
127
- const on = ctx.args.on;
130
+ const choice = await chooseOpRuntime(ctx);
131
+ if (!choice) return undefined;
132
+ const { on, source, configured } = choice;
128
133
  if (!on || on === "local") return createLocalOpRuntime({ projectPath: resolve(".") });
129
134
 
130
- // Read the configured list straight from `chant.config.ts` rather than
131
- // through `resolveProjectLexicons`: `--on` names a *configured* lexicon, and
132
- // that helper's fallback is a source scan of the whole project, which is a
133
- // long wait to be told a name is wrong.
134
- let configured: string[] = [];
135
- try {
136
- configured = lexiconNames((await loadChantConfig(resolve("."))).config.lexicons ?? []);
137
- } catch {
138
- // No/unreadable chant.config.ts — the error below says so by listing nothing.
139
- }
135
+ // How the error names the choice, and how to get the built-in runtime back.
136
+ const label = source === "flag" ? `--on ${on}` : `run.on "${on}" in ${choice.configFile}`;
137
+ const fallback = source === "flag"
138
+ ? "Omit --on to run on the built-in local runtime."
139
+ : `Fix \`run.on\` in ${choice.configFile}, or pass --on local to run on the built-in local runtime.`;
140
140
 
141
141
  let plugin = ctx.plugins.find((p) => p.name === on);
142
142
  if (!plugin && configured.includes(on)) {
@@ -146,18 +146,18 @@ async function resolveOpRuntime(ctx: CommandContext): Promise<OpRuntimeProvider
146
146
  if (!plugin) {
147
147
  const known = [...new Set([...ctx.plugins.map((p) => p.name), ...configured])];
148
148
  console.error(formatError({
149
- message: `--on ${on}: "${on}" is not a configured lexicon`,
149
+ message: `${label}: "${on}" is not a configured lexicon`,
150
150
  hint: known.length > 0
151
- ? `Configured lexicons: ${known.join(", ")}. Omit --on to run on the built-in local runtime.`
152
- : "chant.config.ts configures no lexicons. Omit --on to run on the built-in local runtime.",
151
+ ? `Configured lexicons: ${known.join(", ")}. ${fallback}`
152
+ : `chant.config.ts configures no lexicons. ${fallback}`,
153
153
  }));
154
154
  return undefined;
155
155
  }
156
156
 
157
157
  if (!plugin.opRuntime) {
158
158
  console.error(formatError({
159
- message: `--on ${on}: lexicon "${on}" does not host Op runs`,
160
- hint: "It declares no opRuntime. Omit --on to run on the built-in local runtime.",
159
+ message: `${label}: lexicon "${on}" does not host Op runs`,
160
+ hint: `It declares no opRuntime. ${fallback}`,
161
161
  }));
162
162
  return undefined;
163
163
  }
@@ -165,6 +165,64 @@ async function resolveOpRuntime(ctx: CommandContext): Promise<OpRuntimeProvider
165
165
  return plugin.opRuntime;
166
166
  }
167
167
 
168
+ /** Which runtime name an invocation asked for, and where the name came from. */
169
+ interface OpRuntimeChoice {
170
+ /** The runtime name; `undefined` or `"local"` is the built-in runtime. */
171
+ on: string | undefined;
172
+ /** `flag` for `--on`, `config` for `run.on`, `default` when neither named one. */
173
+ source: "flag" | "config" | "default";
174
+ /** The lexicons `chant.config.ts` configures. */
175
+ configured: string[];
176
+ /** The config file's name, for messages about `run.on`. */
177
+ configFile: string;
178
+ }
179
+
180
+ /**
181
+ * The runtime name `--on`, then `run.on` in `chant.config.ts` (#2523), then
182
+ * the built-in default pick, without loading any lexicon.
183
+ *
184
+ * Reads the configured list straight from `chant.config.ts` rather than
185
+ * through `resolveProjectLexicons`: `--on` names a *configured* lexicon, and
186
+ * that helper's fallback is a source scan of the whole project, which is a
187
+ * long wait to be told a name is wrong.
188
+ *
189
+ * A config that fails to load leaves the flag's choice alone, as before. With
190
+ * no flag, a config whose `run` block is invalid is refused (printed, then
191
+ * `undefined`): running the Op locally would hide that the project asked for
192
+ * another runtime. Any other load failure falls back to the built-in runtime,
193
+ * which is what a project with no `run.on` got before. `quiet` skips printing
194
+ * that refusal, for a caller that only peeks at the choice and leaves the
195
+ * reporting to {@link resolveOpRuntime}.
196
+ */
197
+ async function chooseOpRuntime(ctx: CommandContext, quiet = false): Promise<OpRuntimeChoice | undefined> {
198
+ const flag = ctx.args.on;
199
+ if (flag === "local") return { on: "local", source: "flag", configured: [], configFile: "chant.config.ts" };
200
+
201
+ let configured: string[] = [];
202
+ let configuredOn: string | undefined;
203
+ let configFile = "chant.config.ts";
204
+ try {
205
+ const { config, configPath } = await loadChantConfig(resolve("."));
206
+ configured = lexiconNames(config.lexicons ?? []);
207
+ configuredOn = config.run?.on;
208
+ if (configPath) configFile = basename(configPath);
209
+ } catch (err) {
210
+ if (!flag && err instanceof InvalidChantConfigError && err.key === "run") {
211
+ if (quiet) return undefined;
212
+ console.error(formatError({
213
+ message: err.message,
214
+ hint: "`run.on` names the runtime that hosts this project's Op runs: a configured lexicon with an opRuntime, or \"local\". Fix it, or pass --on to pick the runtime for this run.",
215
+ }));
216
+ return undefined;
217
+ }
218
+ // No/unreadable chant.config.ts: an `--on` error says so by listing nothing.
219
+ }
220
+
221
+ if (flag) return { on: flag, source: "flag", configured, configFile };
222
+ if (configuredOn) return { on: configuredOn, source: "config", configured, configFile };
223
+ return { on: undefined, source: "default", configured, configFile };
224
+ }
225
+
168
226
  /** An ISO-8601 instant trimmed to what a table cell has room for. */
169
227
  function shortInstant(iso: string | undefined): string {
170
228
  return iso ? iso.slice(0, 19).replace("T", " ") : "—";
@@ -395,6 +453,7 @@ export async function runOpApprove(ctx: CommandContext): Promise<number> {
395
453
  note: ctx.args.note,
396
454
  url: ctx.args.url,
397
455
  plan: ctx.args.plan,
456
+ ...(ctx.args.sign !== undefined ? { sign: ctx.args.sign } : {}),
398
457
  });
399
458
  if (!outcome.ok) return 1;
400
459
 
@@ -582,7 +641,9 @@ async function stewardTurnGate(opName: string, ctx: CommandContext): Promise<Ste
582
641
  const form = stewardFormFor(owner, env);
583
642
 
584
643
  if (form === "fountain") {
585
- if (ctx.args.on === "fountain") return { ok: true };
644
+ // `run.on: "fountain"` asks for the steward's thread as much as the flag
645
+ // does (#2523).
646
+ if ((await chooseOpRuntime(ctx, true))?.on === "fountain") return { ok: true };
586
647
  return {
587
648
  ok: false,
588
649
  message: `Op "${opName}" is one of steward "${owner.name}"'s Ops, which runs on fountain in environment "${env}"`,
@@ -15,7 +15,7 @@ import { collectEffectReceipts, isEffectReceipt, type EffectReceiptDeclaration }
15
15
  import { evaluateScenario, type ScenarioBehaviourFixture, type ScenarioVerdict } from "../../lifecycle/scenario-eval";
16
16
  import { validateBehaviourResult } from "../../behaviour-delta";
17
17
  import { collectScenarios, type ScenarioDeclaration, type ScenarioGiven } from "../../lifecycle/scenario";
18
- import { isResourceDeclarable } from "../../declarable";
18
+ import { isObservableDeclarable } from "../../declarable";
19
19
  import { loadChantConfig } from "../../config";
20
20
  import { unknownEnvError } from "../../env";
21
21
  import { collectBuildRootContributors } from "../plugins";
@@ -281,7 +281,7 @@ async function evaluateOneScenario(
281
281
  // and observed like any resource (#1832) — it joins the declared axis so
282
282
  // its lexicon's fixture data can confirm presence, absence, or a hole,
283
283
  // the same as `runLifecyclePlan` (lifecycle.ts:1184).
284
- if (!isResourceDeclarable(entity) && !isEffectReceipt(entity)) continue;
284
+ if (!isObservableDeclarable(entity) && !isEffectReceipt(entity)) continue;
285
285
  if (!declaredByLexicon.has(entity.lexicon)) declaredByLexicon.set(entity.lexicon, new Set());
286
286
  declaredByLexicon.get(entity.lexicon)!.add(name);
287
287
  }
@@ -767,6 +767,7 @@ describe("workspace init and ls (#2534)", () => {
767
767
  "workspace pin",
768
768
  "workspace points",
769
769
  "workspace records",
770
+ "workspace runs",
770
771
  "workspace signers",
771
772
  "workspace status",
772
773
  "workspace upgrade",
package/src/cli/main.ts CHANGED
@@ -102,6 +102,7 @@ const BOOLEAN_FLAGS = new Set([
102
102
  "--durable-requests",
103
103
  "--skip-mcp",
104
104
  "--current",
105
+ "--uncommitted",
105
106
  "--allow-code",
106
107
  "--root-only",
107
108
  "--generated",
@@ -227,6 +228,12 @@ export function parseArgs(args: string[]): ParsedArgs {
227
228
  // `chant import --kustomize <dir>` (#1548): render the overlay, import
228
229
  // the output through the k8s template parser.
229
230
  result.kustomize = args[++i];
231
+ } else if (arg === "--parser-option") {
232
+ // `chant import --parser-option key[=value]` (#2994), repeatable: checked
233
+ // against the lexicon's parserOptions() by the import command.
234
+ const v = args[++i];
235
+ if (!v || v.startsWith("-")) throw new Error("--parser-option needs key or key=value: --parser-option acceptLossyV1");
236
+ (result.parserOption ??= []).push(v);
230
237
  } else if (arg === "--type") {
231
238
  result.selectType = args[++i];
232
239
  } else if (arg === "--name") {
@@ -377,11 +384,11 @@ export function parseArgs(args: string[]): ParsedArgs {
377
384
  // `chant workspace graph --composites` (#2662)
378
385
  result.composites = true;
379
386
  } else if (arg === "--intent") {
380
- // `chant workspace graph --intent <path[:start-end]>` (#2651), or `--intent --record <id>` with no region.
387
+ // `chant workspace graph --intent <path[:start-end]|path#symbol>` (#2651), or `--intent --record <id>` with no region.
381
388
  const value = args[i + 1];
382
389
  if (value !== undefined && !value.startsWith("-")) result.intent = args[++i];
383
390
  else if (args.includes("--record")) result.intent = "";
384
- else throw new Error("--intent needs a region: --intent <path[:start-end]>, or --intent --record <id>");
391
+ else throw new Error("--intent needs a region: --intent <path[:start-end]|path#symbol>, or --intent --record <id>");
385
392
  } else if (arg === "--record") {
386
393
  // `chant workspace graph --intent --record <id>`
387
394
  result.record = args[++i];
@@ -409,6 +416,9 @@ export function parseArgs(args: string[]): ParsedArgs {
409
416
  if (!result.severity || result.severity.startsWith("-")) throw new Error("--severity needs off, warn or fail");
410
417
  } else if (arg === "--current") {
411
418
  result.current = true;
419
+ } else if (arg === "--uncommitted") {
420
+ // `chant workspace records --uncommitted` (#3160)
421
+ result.uncommitted = true;
412
422
  } else if (arg === "--set") {
413
423
  // `chant workspace records amend <id> --set <file|->` (#2670)
414
424
  result.set = args[++i];
@@ -445,6 +455,7 @@ export function parseArgs(args: string[]): ParsedArgs {
445
455
  } else if (arg === "--sign") {
446
456
  // `chant workspace records review <id> --sign [<key file>]` (#2687): seal the verdict.
447
457
  // `records new` and `records amend` take it too, to seal the record's author (#2688).
458
+ // `chant approve <op> <gate> --sign [<key file>]` seals a gate approval (#3163).
448
459
  // With no key file, git's user.signingkey, as `git commit -S` reads it.
449
460
  const next = args[i + 1];
450
461
  result.sign = next !== undefined && !next.startsWith("-") ? args[++i] : true;
@@ -566,6 +577,11 @@ export function parseArgs(args: string[]): ParsedArgs {
566
577
  const value = args[++i];
567
578
  if (!value || value.startsWith("-")) throw new Error(`${arg} needs a value: ${arg} <${arg.slice(2)}>`);
568
579
  result[arg.slice(2) as "holder" | "ttl" | "token" | "outcome"] = value;
580
+ } else if (arg === "--unit" || arg === "--decision") {
581
+ // `chant workspace runs --unit <id> | --decision <id>` (#3033): the runs on one work item, or for one decision.
582
+ const value = args[++i];
583
+ if (!value || value.startsWith("-")) throw new Error(`${arg} needs an id: ${arg} <id>`);
584
+ result[arg.slice(2) as "unit" | "decision"] = value;
569
585
  } else if (arg === "--note") {
570
586
  result.note = args[++i];
571
587
  } else if (arg === "--expire") {
@@ -818,7 +834,11 @@ Ops:
818
834
  and defaults to the PR/MR of the surrounding CI job.
819
835
  The next "chant run <op>" walks through the gate.
820
836
  --expire clears a pending fact without approving it,
821
- so the gate is re-decided from scratch next run
837
+ so the gate is re-decided from scratch next run.
838
+ --sign [<key file>] seals the approval with an ssh
839
+ key; a gate the workspace's identity.gates names
840
+ counts only an approval sealed by a key the signers
841
+ file at base lists for --actor
822
842
 
823
843
  graph Show Op dependency graph (--stacks for cross-stack order,
824
844
  --format ir|mermaid|dot|layout for the lint-gated graph IR,
@@ -858,7 +878,7 @@ Workspace (level 1, #2524):
858
878
  beside it and marks the members whose digests differ.
859
879
  Read only; never fetches. --json prints the
860
880
  read-contract document
861
- workspace records [--kind <kind file>] [--current] [--at <rev>] [--base <rev>] [--require attested] [--json]
881
+ workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--json]
862
882
  Without --kind, every record kind the declaration
863
883
  names. Read the records a record kind locates, validated
864
884
  against its schema, with reason codes for invalid
@@ -868,7 +888,10 @@ Workspace (level 1, #2524):
868
888
  the signers at --base (default: the target branch);
869
889
  --require attested exits 2 if any record is not
870
890
  attested. A pinned file that changed is a warning,
871
- asset-drift or asset-missing
891
+ asset-drift or asset-missing. In the working tree,
892
+ each record says whether it is committed, modified
893
+ or new against HEAD, with the branch and base;
894
+ --uncommitted lists only the modified and new ones
872
895
  workspace records [--kind <kind file>] --since <rev|session id> [--at <rev>] [--json]
873
896
  What changed in the records between <rev> and --at
874
897
  (default: the working tree): new and removed records,
@@ -910,7 +933,7 @@ Workspace (level 1, #2524):
910
933
  closing commit and seal, in one write. Without
911
934
  --kind, the one session kind the declaration names.
912
935
  Prints {path, id, changed, seal, closedRev}
913
- workspace work claim|renew|release <id> --holder <name> [--kind <kind file>] [--ttl <seconds|duration>] [--token <token>] [--outcome <text>] [--note <text>] [--json]
936
+ workspace work claim|renew|release <id> --holder <name> [--kind <kind file>] [--ttl <seconds|duration>] [--token <token>] [--outcome <outcome>] [--note <text>] [--json]
914
937
  Take, heartbeat or give back the lease on a work item:
915
938
  refs/chant/lease/work/<id>, a compare-and-set ref with a
916
939
  fencing token and an expiry, pushed to the remote so
@@ -921,6 +944,28 @@ Workspace (level 1, #2524):
921
944
  A work item's lease history: each claim with its token
922
945
  and holder, and how it ended, released with an outcome
923
946
  or never released (expired or lost). Read-only
947
+ workspace work evidence <id> --holder <name> --token <token> --from <file|-> [--kind <kind file>]
948
+ Attach evidence for one acceptance criterion under the
949
+ lease you hold: the entry (criterion, result, title,
950
+ a url or a path pinned by hash) is appended to the
951
+ item's pins through records amend. Prints the
952
+ work-evidence document and never commits
953
+ workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--json]
954
+ The agent runs in the run ledger on chant/lifecycle, each
955
+ with its model, tokens, cost and the commits it made,
956
+ and totals per work item, decision and principal; a run
957
+ that reports no cost is listed as unpriced, never zero.
958
+ Read-only, never fetches
959
+ workspace runs start --from <file|->
960
+ Record that an agent run started: who it worked for,
961
+ its harness, model, work item and lease. Prints the run
962
+ and its Chant-Run trailer. chant never starts a run
963
+ workspace runs end <run id> [--from <file|->]
964
+ Record how a started run ended: its outcome, tokens,
965
+ cost and price source, the transcript pinned by hash,
966
+ and the commits it made
967
+ workspace runs record --from <file|->
968
+ Record a finished run, its start and end in one write
924
969
  workspace points [--open] [--kind <kind file>] [--at <rev>] [--json]
925
970
  List the decision points the declared answer kinds'
926
971
  points files declare, and the questions asked of them;
@@ -1056,7 +1101,7 @@ Workspace (level 1, #2524):
1056
1101
  Each composite instance the members declare, with the
1057
1102
  components whose contract can deploy it; an instance
1058
1103
  with none lists an empty set
1059
- workspace graph --intent <path[:start-end]> [--at <rev>] [--kind <kind file>...] [--json]
1104
+ workspace graph --intent <path[:start-end]|path#symbol> [--at <rev>] [--kind <kind file>...] [--json]
1060
1105
  The intent graph over one region: the commits that
1061
1106
  touched it, the decisions whose constrains cover it,
1062
1107
  the artifacts they pin, and findings with closed codes.
@@ -1150,8 +1195,13 @@ Lexicon development:
1150
1195
  --check: fail if the committed baseline drifted (never writes);
1151
1196
  --run-examples: also run example build harness;
1152
1197
  --pinned-digest <file>: verify spec digest before regen)
1153
- dev pinned-upgrade <dir> Report if a pinned lexicon (k8s|gcp|docker|gitlab) has a newer
1154
- upstream release; dry-run bump + regen + surface-diff, then revert
1198
+ dev pinned-upgrade <dir> [pin]
1199
+ Report if a lexicon that declares upstreamPin (k8s, k3s, gcp, docker,
1200
+ gitlab, cedar, sql) has a newer upstream release; dry-run bump + regen +
1201
+ surface-diff, then revert. A pin that moves with other constants (sql's
1202
+ image digest) is reported with how to move it, not edited. A lexicon
1203
+ with several pins (sql: clickhouse, postgres-14 .. postgres-18) gets one
1204
+ report per pin; name a pin to check only that one
1155
1205
  (reports only; --force bypasses the spec cache, -f json for JSON)
1156
1206
  dev rolling-upgrade <dir> Report rolling-spec drift (aws, azure, github): regen from
1157
1207
  latest, diff surface vs committed baseline, print delta + PR
@@ -1194,8 +1244,9 @@ Options:
1194
1244
  -h, --help Show this help message
1195
1245
  -V, --version Print the installed chant's version
1196
1246
  --on <lexicon> Which runtime hosts the run: a configured lexicon with
1197
- an opRuntime, or the built-in local runtime when
1198
- omitted (every run subcommand; #2121)
1247
+ an opRuntime, or local. Omitted, run.on in
1248
+ chant.config.ts decides, then the built-in local
1249
+ runtime (every run subcommand; #2121, #2523)
1199
1250
  --local Run an Op with the local in-process executor (default)
1200
1251
  -p, --profile <name> Named connection profile the hosting runtime targets
1201
1252
  (fountain.profiles in chant.config.ts); each runtime's
@@ -1287,6 +1338,7 @@ Examples:
1287
1338
  chant components export prod --component search-service -o ./dist/search-service
1288
1339
  chant import template.json --output ./infra/
1289
1340
  chant import manifest.yaml --lexicon k8s --output ./infra/
1341
+ chant import dash.json --lexicon grafana --parser-option acceptLossyV1
1290
1342
  chant import --from prod --name my-bucket --output src/
1291
1343
  chant lint ./infra/
1292
1344
  chant lint ./infra/ --format sarif
@@ -1552,6 +1604,8 @@ export const commandRegistry: CommandDef[] = [
1552
1604
  { name: "workspace ls", handler: async (ctx) => (await import("../workspace/ls")).runWorkspaceLs(ctx) },
1553
1605
  // #2732 — the work lease: claim, renew and release a work item.
1554
1606
  { name: "workspace work", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/work-cli")).runWorkspaceWork(ctx) },
1607
+ // #3033 — the agent run record: what each run cost and which commits it made. chant records runs and never starts one.
1608
+ { name: "workspace runs", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/runs-cli")).runWorkspaceRuns(ctx) },
1555
1609
  { name: "workspace status", handler: async (ctx) => (await import("../workspace/status")).runWorkspaceStatus(ctx) },
1556
1610
  { name: "workspace lineage", handler: async (ctx) => (await import("../workspace/lineage-cli")).runWorkspaceLineage(ctx) },
1557
1611
  { name: "workspace upgrade", handler: async (ctx) => (await import("../workspace/lineage-upgrade-cli")).runWorkspaceUpgrade(ctx) },
@@ -12,7 +12,7 @@ import { join } from "node:path";
12
12
  import { afterAll, beforeAll, describe, expect, test } from "vitest";
13
13
  import { createConformanceWorkspace, defaultChantCommand, mcpToolCall, type ConformanceWorkspace } from "../../workspace/conformance";
14
14
  import { McpServer } from "./server";
15
- import { workspaceReadTools, workspaceWriteTools } from "./workspace-tools";
15
+ import { readArgv, workspaceReadTools, workspaceWriteTools } from "./workspace-tools";
16
16
 
17
17
  const KIND = "decisions/decision.kind.mjs";
18
18
  const chant = defaultChantCommand();
@@ -85,7 +85,7 @@ describe("which servers have the workspace tools", () => {
85
85
  const { tools } = (await rpc(server(cwd), "tools/list")) as { tools: { name: string }[] };
86
86
  expect(tools.map((t) => t.name)).toEqual(expect.arrayContaining(names));
87
87
  }
88
- expect(names).toEqual(["workspace-ls", "workspace-status", "workspace-graph", "workspace-changes", "workspace-records", "workspace-points", "workspace-agent", "workspace-work-history", "records-new", "records-amend", "records-review", "records-close", "points-answer"]);
88
+ expect(names).toEqual(["workspace-ls", "workspace-status", "workspace-graph", "workspace-changes", "workspace-records", "workspace-points", "workspace-agent", "workspace-work-history", "workspace-runs", "records-new", "records-amend", "records-review", "records-close", "points-answer"]);
89
89
  });
90
90
 
91
91
  test("a server outside any workspace, or given none, does not", async () => {
@@ -161,6 +161,9 @@ describe("reads", () => {
161
161
 
162
162
  test("the conformance suite's argv maps to the tool that answers it", () => {
163
163
  expect(mcpToolCall(["workspace", "records", "--kind", KIND, "--json"])).toEqual({ name: "workspace-records", arguments: { kind: KIND } });
164
+ expect(mcpToolCall(["workspace", "records", "--uncommitted", "--kind", KIND, "--json"])).toEqual({ name: "workspace-records", arguments: { uncommitted: true, kind: KIND } });
165
+ expect(readArgv("workspace-records", { kind: KIND, uncommitted: true })).toEqual(["workspace", "records", "--kind", KIND, "--uncommitted", "--json"]);
166
+ expect(() => readArgv("workspace-records", { uncommitted: true, at: "HEAD" })).toThrow(/takes no at or since/);
164
167
  expect(mcpToolCall(["workspace", "status", "dev", "--json"])).toEqual({ name: "workspace-status", arguments: { env: "dev" } });
165
168
  expect(mcpToolCall(["workspace", "graph", "--intent", "a.mjs:1", "--kind", KIND, "--json"])).toEqual({ name: "workspace-graph", arguments: { intent: "a.mjs:1", kind: [KIND] } });
166
169
  expect(mcpToolCall(["workspace", "graph", "--composites", "--json"])).toEqual({ name: "workspace-graph", arguments: { composites: true } });
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * - The reads (`workspace-ls`, `workspace-status`, `workspace-graph`,
9
9
  * `workspace-changes`, `workspace-records`, `workspace-points`,
10
- * `workspace-work-history`) run `chant workspace <command>
10
+ * `workspace-work-history`, `workspace-runs`) run `chant workspace <command>
11
11
  * ... --json` with the chant this server runs as, in the server's
12
12
  * directory, and return the
13
13
  * document it printed, unchanged, with its reason codes (#2536). Running the
@@ -111,7 +111,7 @@ export const workspaceReadTools: ToolDefinition[] = [
111
111
  items: { type: "string" },
112
112
  description: "Record kind files whose records join the graph (--kind). The plain graph takes one; intent takes several.",
113
113
  },
114
- intent: { type: "string", description: "The region for the intent graph: a workspace path, path:line or path:start-end (--intent)." },
114
+ intent: { type: "string", description: "The region for the intent graph: a workspace path, path:line, path:start-end, or path#symbol for a TypeScript or JavaScript declaration such as src/server.ts#createApp (--intent). The document's why answers why the region is like this." },
115
115
  composites: { type: "boolean", description: "The composites document instead (--composites). Takes no kind or intent." },
116
116
  at: atProp,
117
117
  },
@@ -146,6 +146,10 @@ export const workspaceReadTools: ToolDefinition[] = [
146
146
  properties: {
147
147
  kind: kindProp,
148
148
  current: { type: "boolean", description: "Leave out records a closed record supersedes (--current)." },
149
+ uncommitted: {
150
+ type: "boolean",
151
+ description: "Only the records the working tree holds modified or new against HEAD, with the checkout's branch, head and base (--uncommitted, #3160). Takes no at or since.",
152
+ },
149
153
  since: { type: "string", description: "A revision, or a review session id, to compare with (--since)." },
150
154
  id: { type: "string", description: "Keep only the record with this id in the document's records." },
151
155
  at: atProp,
@@ -189,6 +193,20 @@ export const workspaceReadTools: ToolDefinition[] = [
189
193
  required: ["item"],
190
194
  },
191
195
  },
196
+ {
197
+ name: "workspace-runs",
198
+ description:
199
+ "The agent runs in the workspace's run ledger on chant/lifecycle: chant workspace runs --json (runs.schema.json, #3033). Each run has who it worked for, its harness and model, its tokens and cost with the price source, the transcript pinned by hash and the commits it made, and the totals are per work item, per decision and per principal. A run that reports no cost is listed as unpriced, never counted as zero. Returns the document unchanged.",
200
+ inputSchema: {
201
+ type: "object",
202
+ properties: {
203
+ unit: { type: "string", description: "Only the runs on this work item (--unit)." },
204
+ decision: { type: "string", description: "Only the runs that carried out this decision, by id or <kind>/<id> (--decision)." },
205
+ by: { type: "string", description: "Only the runs made for this principal (--by)." },
206
+ since: { type: "string", description: "Only the runs that made a commit after this revision, or started after it (--since)." },
207
+ },
208
+ },
209
+ },
192
210
  ];
193
211
 
194
212
  export const workspaceWriteTools: ToolDefinition[] = [
@@ -365,6 +383,13 @@ export function readArgv(tool: string, params: Record<string, unknown>): string[
365
383
  const kind = str(params, "kind");
366
384
  return ["workspace", "work", "history", item, ...(kind !== undefined ? ["--kind", kind] : []), "--json"];
367
385
  }
386
+ case "workspace-runs": {
387
+ const flags = (["unit", "decision", "by", "since"] as const).flatMap((f) => {
388
+ const v = str(params, f);
389
+ return v !== undefined ? [`--${f}`, v] : [];
390
+ });
391
+ return ["workspace", "runs", ...flags, "--json"];
392
+ }
368
393
  case "workspace-points": {
369
394
  const kind = str(params, "kind");
370
395
  return ["workspace", "points", ...(bool(params, "open") ? ["--open"] : []), ...(kind !== undefined ? ["--kind", kind] : []), ...atArgs, "--json"];
@@ -372,11 +397,13 @@ export function readArgv(tool: string, params: Record<string, unknown>): string[
372
397
  case "workspace-records": {
373
398
  const kind = str(params, "kind");
374
399
  const since = str(params, "since");
400
+ if (bool(params, "uncommitted") && (at !== undefined || since !== undefined)) throw new ToolInputError("uncommitted reads the working tree against HEAD, and takes no at or since");
375
401
  return [
376
402
  "workspace",
377
403
  "records",
378
404
  ...(kind !== undefined ? ["--kind", kind] : []),
379
405
  ...(bool(params, "current") ? ["--current"] : []),
406
+ ...(bool(params, "uncommitted") ? ["--uncommitted"] : []),
380
407
  ...(since !== undefined ? ["--since", since] : []),
381
408
  ...atArgs,
382
409
  "--json",
@@ -75,6 +75,8 @@ export interface ParsedArgs {
75
75
  migrateFrom?: string;
76
76
  /** `chant import --kustomize <dir>` — render the kustomization, then import (#1548) */
77
77
  kustomize?: string;
78
+ /** `chant import --parser-option key[=value]`, repeatable (#2994): options for the lexicon's template parser */
79
+ parserOption?: string[];
78
80
  /** `chant carve advise --state <path>` — opt-in .tfstate for accurate instance counts */
79
81
  statePath?: string;
80
82
  /** `chant carve emit --select <tf-address>` — the Terraform resource to carve */
@@ -313,7 +315,7 @@ export interface ParsedArgs {
313
315
  noCache?: boolean;
314
316
  /** `chant workspace graph --composites` (#2662): print each composite instance with the components that can deploy it. */
315
317
  composites?: boolean;
316
- /** `chant workspace graph --intent <path[:start-end]>` (#2651): the region the intent graph is over. Empty with `--record`. */
318
+ /** `chant workspace graph --intent <path[:start-end]|path#symbol>` (#2651): the region the intent graph is over. Empty with `--record`. */
317
319
  intent?: string;
318
320
  /** `chant workspace graph --intent --record <id>`: walk one decision record over every entry its constrains lists. */
319
321
  record?: string;
@@ -329,6 +331,8 @@ export interface ParsedArgs {
329
331
  severity?: string;
330
332
  /** `chant workspace records --current` (#2546): leave out records a closed record supersedes. */
331
333
  current?: boolean;
334
+ /** `chant workspace records --uncommitted` (#3160): only the records the working tree holds modified or new against HEAD. */
335
+ uncommitted?: boolean;
332
336
  /** `chant workspace records amend <id> --set <file|->` (#2670): the JSON fields to set. */
333
337
  set?: string;
334
338
  /** `chant workspace records review <id> --verdict <v>` (#2670): agree, dissent or abstain. */
@@ -344,6 +348,7 @@ export interface ParsedArgs {
344
348
  /**
345
349
  * `chant workspace records review <id> --sign [<key file>]` (#2687): the key that seals the verdict, or true for git's user.signingkey.
346
350
  * On `records new` and `records amend`, the key that seals the record's author (#2688).
351
+ * On `chant approve` and `chant run approve`, the key that seals the gate approval (#3163).
347
352
  */
348
353
  sign?: string | true;
349
354
  /** `chant workspace records review <id> --session <id>` (#2670): the review session the verdict was given in. */
@@ -476,6 +481,10 @@ export interface ParsedArgs {
476
481
  * project's only steward.
477
482
  */
478
483
  steward?: string;
484
+ /** `chant workspace runs --unit <id>` (#3033): only the agent runs on this work item. */
485
+ unit?: string;
486
+ /** `chant workspace runs --decision <id>` (#3033): only the agent runs that carried out this decision. */
487
+ decision?: string;
479
488
  /** `chant workspace work claim|renew|release <id> --holder <name>` (#2732): who holds, or releases, the work lease. */
480
489
  holder?: string;
481
490
  /** `chant run <op> --work <id>` (#2748): the work item an Op with a work lease runs under. `chant workspace check --changes --work <id>` (#2773): the work item in hand. */
@@ -484,7 +493,7 @@ export interface ParsedArgs {
484
493
  ttl?: string;
485
494
  /** `chant workspace work renew|release <id> --token <token>` (#2732): the fencing token the caller holds. */
486
495
  token?: string;
487
- /** `chant workspace work release <id> --outcome <text>` (#2732): how the work ended, such as done or not_done. */
496
+ /** `chant workspace work release <id> --outcome <outcome>` (#2732): how the work ended, one of the closed list WORK_LEASE_OUTCOMES (#3147). */
488
497
  outcome?: string;
489
498
  /** `chant operator --once` (#1485) — run a single round and exit, instead of looping until Ctrl-C. Also the offline test/cron-invoker story. */
490
499
  once?: boolean;