@intentius/chant 0.101.0 → 0.104.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (739) hide show
  1. package/dist/agents/checks.d.ts.map +1 -1
  2. package/dist/attrref.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +2 -0
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts.map +1 -1
  6. package/dist/audit/nginx.d.ts.map +1 -1
  7. package/dist/audit/prior-art.d.ts +48 -0
  8. package/dist/audit/prior-art.d.ts.map +1 -1
  9. package/dist/behaviour-kinds.d.ts.map +1 -1
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/change-set.d.ts +232 -0
  12. package/dist/change-set.d.ts.map +1 -0
  13. package/dist/cli/commands/audit.d.ts +7 -0
  14. package/dist/cli/commands/audit.d.ts.map +1 -1
  15. package/dist/cli/commands/build.d.ts.map +1 -1
  16. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  17. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  18. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  19. package/dist/cli/commands/import.d.ts +8 -0
  20. package/dist/cli/commands/import.d.ts.map +1 -1
  21. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  22. package/dist/cli/commands/init.d.ts +19 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -1
  24. package/dist/cli/commands/onboard.d.ts +9 -0
  25. package/dist/cli/commands/onboard.d.ts.map +1 -1
  26. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  27. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  28. package/dist/cli/handlers/build.d.ts.map +1 -1
  29. package/dist/cli/handlers/change-set.d.ts +11 -0
  30. package/dist/cli/handlers/change-set.d.ts.map +1 -0
  31. package/dist/cli/handlers/dev.d.ts.map +1 -1
  32. package/dist/cli/handlers/fan-out.d.ts +33 -0
  33. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  34. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  35. package/dist/cli/handlers/misc.d.ts.map +1 -1
  36. package/dist/cli/handlers/operator.d.ts +16 -0
  37. package/dist/cli/handlers/operator.d.ts.map +1 -1
  38. package/dist/cli/handlers/pr.d.ts +31 -0
  39. package/dist/cli/handlers/pr.d.ts.map +1 -0
  40. package/dist/cli/handlers/run.d.ts.map +1 -1
  41. package/dist/cli/lsp/server.d.ts.map +1 -1
  42. package/dist/cli/main.d.ts.map +1 -1
  43. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  44. package/dist/cli/mcp/server.d.ts.map +1 -1
  45. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  46. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  47. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  48. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  49. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  50. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  51. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  52. package/dist/cli/mcp/workspace-tools.d.ts +4 -3
  53. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  54. package/dist/cli/registry.d.ts +74 -3
  55. package/dist/cli/registry.d.ts.map +1 -1
  56. package/dist/codegen/fetch.d.ts.map +1 -1
  57. package/dist/codegen/naming.d.ts.map +1 -1
  58. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  59. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  60. package/dist/codegen/registry.d.ts.map +1 -1
  61. package/dist/components/auto-release.d.ts +16 -0
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  64. package/dist/components/capability.d.ts +53 -0
  65. package/dist/components/capability.d.ts.map +1 -1
  66. package/dist/components/changed-files.d.ts +31 -0
  67. package/dist/components/changed-files.d.ts.map +1 -0
  68. package/dist/components/cli-support.d.ts +9 -1
  69. package/dist/components/cli-support.d.ts.map +1 -1
  70. package/dist/components/component.d.ts +24 -0
  71. package/dist/components/component.d.ts.map +1 -1
  72. package/dist/components/deploy-units.d.ts.map +1 -1
  73. package/dist/components/driver.d.ts +13 -0
  74. package/dist/components/driver.d.ts.map +1 -1
  75. package/dist/components/fan-out-output.d.ts +6 -0
  76. package/dist/components/fan-out-output.d.ts.map +1 -1
  77. package/dist/components/fan-out-record.d.ts +41 -0
  78. package/dist/components/fan-out-record.d.ts.map +1 -0
  79. package/dist/components/fan-out-run.d.ts +65 -0
  80. package/dist/components/fan-out-run.d.ts.map +1 -1
  81. package/dist/components/fan-out-support.d.ts +2 -0
  82. package/dist/components/fan-out-support.d.ts.map +1 -1
  83. package/dist/components/fan-out.d.ts +6 -0
  84. package/dist/components/fan-out.d.ts.map +1 -1
  85. package/dist/components/gated-wave-pipeline.d.ts +50 -0
  86. package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
  87. package/dist/components/index.d.ts +1 -1
  88. package/dist/components/index.d.ts.map +1 -1
  89. package/dist/components/layers.d.ts +25 -0
  90. package/dist/components/layers.d.ts.map +1 -0
  91. package/dist/components/pr-pipeline.d.ts +61 -0
  92. package/dist/components/pr-pipeline.d.ts.map +1 -0
  93. package/dist/components/pr-run.d.ts +119 -0
  94. package/dist/components/pr-run.d.ts.map +1 -0
  95. package/dist/components/promote.d.ts.map +1 -1
  96. package/dist/components/starter-plugin.d.ts.map +1 -1
  97. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  98. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  99. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  100. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  101. package/dist/components/verbs/shell.d.ts.map +1 -1
  102. package/dist/components/verbs/sign.d.ts.map +1 -1
  103. package/dist/components/verbs/verify.d.ts.map +1 -1
  104. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  105. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  106. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  107. package/dist/components/wave-plan.d.ts +49 -0
  108. package/dist/components/wave-plan.d.ts.map +1 -0
  109. package/dist/composite.d.ts.map +1 -1
  110. package/dist/config.d.ts +19 -7
  111. package/dist/config.d.ts.map +1 -1
  112. package/dist/declarable.d.ts +16 -0
  113. package/dist/declarable.d.ts.map +1 -1
  114. package/dist/discovery/cache.d.ts.map +1 -1
  115. package/dist/discovery/fold-import.d.ts +15 -5
  116. package/dist/discovery/fold-import.d.ts.map +1 -1
  117. package/dist/discovery/param-deps.d.ts +16 -0
  118. package/dist/discovery/param-deps.d.ts.map +1 -1
  119. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  120. package/dist/discovery/specifier-resolve.d.ts +37 -0
  121. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  122. package/dist/errors.d.ts.map +1 -1
  123. package/dist/fold/fold.d.ts +3 -1
  124. package/dist/fold/fold.d.ts.map +1 -1
  125. package/dist/gated-waves.d.ts +147 -0
  126. package/dist/gated-waves.d.ts.map +1 -0
  127. package/dist/graph-detail.d.ts.map +1 -1
  128. package/dist/graph-ir.d.ts.map +1 -1
  129. package/dist/graph-layout.d.ts.map +1 -1
  130. package/dist/import/base-parser.d.ts.map +1 -1
  131. package/dist/import/embedded.d.ts +7 -0
  132. package/dist/import/embedded.d.ts.map +1 -1
  133. package/dist/import/parser-options.d.ts +14 -0
  134. package/dist/import/parser-options.d.ts.map +1 -0
  135. package/dist/import/parser.d.ts +17 -0
  136. package/dist/import/parser.d.ts.map +1 -1
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/kubectl-context.d.ts.map +1 -1
  140. package/dist/lexicon-output.d.ts.map +1 -1
  141. package/dist/lexicon-schema.d.ts +3 -3
  142. package/dist/lexicon.d.ts +103 -3
  143. package/dist/lexicon.d.ts.map +1 -1
  144. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  145. package/dist/lifecycle/gate-ledger.d.ts +22 -0
  146. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  147. package/dist/lifecycle/git.d.ts +46 -1
  148. package/dist/lifecycle/git.d.ts.map +1 -1
  149. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  150. package/dist/lifecycle/observe.d.ts.map +1 -1
  151. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  152. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  153. package/dist/lifecycle/scenario.d.ts.map +1 -1
  154. package/dist/lifecycle/status.d.ts.map +1 -1
  155. package/dist/lifecycle/work-lease.d.ts +61 -2
  156. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  157. package/dist/lint/config.d.ts +8 -8
  158. package/dist/lint/engine.d.ts +6 -0
  159. package/dist/lint/engine.d.ts.map +1 -1
  160. package/dist/lint/post-synth.d.ts +18 -0
  161. package/dist/lint/post-synth.d.ts.map +1 -1
  162. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  163. package/dist/op/activities/activity-contracts.d.ts +137 -11
  164. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  165. package/dist/op/activities/apply.d.ts +79 -9
  166. package/dist/op/activities/apply.d.ts.map +1 -1
  167. package/dist/op/activities/change-set.d.ts +62 -0
  168. package/dist/op/activities/change-set.d.ts.map +1 -0
  169. package/dist/op/activities/decide.d.ts +2 -0
  170. package/dist/op/activities/decide.d.ts.map +1 -1
  171. package/dist/op/activities/factory.d.ts +137 -0
  172. package/dist/op/activities/factory.d.ts.map +1 -0
  173. package/dist/op/activities/index.d.ts +5 -1
  174. package/dist/op/activities/index.d.ts.map +1 -1
  175. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  176. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  177. package/dist/op/activity-contract.d.ts +1 -1
  178. package/dist/op/activity-contract.d.ts.map +1 -1
  179. package/dist/op/activity-failure.d.ts.map +1 -1
  180. package/dist/op/activity-profiles.d.ts.map +1 -1
  181. package/dist/op/builders.d.ts +11 -0
  182. package/dist/op/builders.d.ts.map +1 -1
  183. package/dist/op/composites/apply-op.d.ts +12 -5
  184. package/dist/op/composites/apply-op.d.ts.map +1 -1
  185. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  186. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  187. package/dist/op/decide-backend.d.ts +5 -1
  188. package/dist/op/decide-backend.d.ts.map +1 -1
  189. package/dist/op/decide-read-inputs.d.ts +4 -2
  190. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  191. package/dist/op/emulator-lifecycle.d.ts +21 -2
  192. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  193. package/dist/op/factory.d.ts +83 -0
  194. package/dist/op/factory.d.ts.map +1 -0
  195. package/dist/op/gate-approval.d.ts +5 -1
  196. package/dist/op/gate-approval.d.ts.map +1 -1
  197. package/dist/op/gate-wait.d.ts.map +1 -1
  198. package/dist/op/gate.d.ts +19 -3
  199. package/dist/op/gate.d.ts.map +1 -1
  200. package/dist/op/index.d.ts +6 -1
  201. package/dist/op/index.d.ts.map +1 -1
  202. package/dist/op/local-executor.d.ts +6 -0
  203. package/dist/op/local-executor.d.ts.map +1 -1
  204. package/dist/op/op-ir.d.ts +2 -0
  205. package/dist/op/op-ir.d.ts.map +1 -1
  206. package/dist/op/op-verb-class.d.ts.map +1 -1
  207. package/dist/op/operator.d.ts.map +1 -1
  208. package/dist/op/run-context.d.ts +39 -0
  209. package/dist/op/run-context.d.ts.map +1 -0
  210. package/dist/op/run-live.d.ts.map +1 -1
  211. package/dist/op/runtimes/local.d.ts.map +1 -1
  212. package/dist/op/source-archive.d.ts.map +1 -1
  213. package/dist/op/steward-beside.d.ts.map +1 -1
  214. package/dist/op/steward-points.d.ts.map +1 -1
  215. package/dist/op/steward.d.ts.map +1 -1
  216. package/dist/op/types.d.ts +16 -3
  217. package/dist/op/types.d.ts.map +1 -1
  218. package/dist/op/work-lease-run.d.ts +24 -4
  219. package/dist/op/work-lease-run.d.ts.map +1 -1
  220. package/dist/plan-summary.d.ts +207 -0
  221. package/dist/plan-summary.d.ts.map +1 -0
  222. package/dist/pr-forge.d.ts +105 -0
  223. package/dist/pr-forge.d.ts.map +1 -0
  224. package/dist/pr-loop.d.ts +178 -0
  225. package/dist/pr-loop.d.ts.map +1 -0
  226. package/dist/project-root.d.ts.map +1 -1
  227. package/dist/provenance.d.ts +21 -0
  228. package/dist/provenance.d.ts.map +1 -1
  229. package/dist/pseudo-parameter.d.ts.map +1 -1
  230. package/dist/reconcile.d.ts.map +1 -1
  231. package/dist/secret-materialization.d.ts.map +1 -1
  232. package/dist/telemetry-attribution.d.ts +31 -0
  233. package/dist/telemetry-attribution.d.ts.map +1 -1
  234. package/dist/terraform/emit-source.d.ts.map +1 -1
  235. package/dist/terraform/hcl2json.d.ts +45 -0
  236. package/dist/terraform/hcl2json.d.ts.map +1 -0
  237. package/dist/terraform/parse.d.ts +4 -40
  238. package/dist/terraform/parse.d.ts.map +1 -1
  239. package/dist/testing.d.ts.map +1 -1
  240. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  241. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  242. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  243. package/dist/workspace/agent-cli.d.ts +5 -0
  244. package/dist/workspace/agent-cli.d.ts.map +1 -1
  245. package/dist/workspace/box-cli.d.ts +12 -0
  246. package/dist/workspace/box-cli.d.ts.map +1 -0
  247. package/dist/workspace/box-factory.d.ts +97 -0
  248. package/dist/workspace/box-factory.d.ts.map +1 -0
  249. package/dist/workspace/box-listing.d.ts +85 -0
  250. package/dist/workspace/box-listing.d.ts.map +1 -0
  251. package/dist/workspace/box-publish.d.ts +147 -0
  252. package/dist/workspace/box-publish.d.ts.map +1 -0
  253. package/dist/workspace/broker-protocol.d.ts +190 -0
  254. package/dist/workspace/broker-protocol.d.ts.map +1 -0
  255. package/dist/workspace/changes.d.ts.map +1 -1
  256. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  257. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  258. package/dist/workspace/checks.d.ts +5 -0
  259. package/dist/workspace/checks.d.ts.map +1 -1
  260. package/dist/workspace/compose-graph.d.ts +10 -0
  261. package/dist/workspace/compose-graph.d.ts.map +1 -1
  262. package/dist/workspace/composites.d.ts +2 -2
  263. package/dist/workspace/composites.d.ts.map +1 -1
  264. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
  265. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
  266. package/dist/workspace/conformance/broker.d.ts +202 -0
  267. package/dist/workspace/conformance/broker.d.ts.map +1 -0
  268. package/dist/workspace/conformance/index.d.ts +68 -6
  269. package/dist/workspace/conformance/index.d.ts.map +1 -1
  270. package/dist/workspace/conformance/vitest.d.ts +19 -3
  271. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  272. package/dist/workspace/conformance/writer.d.ts +462 -0
  273. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  274. package/dist/workspace/decide.d.ts +126 -12
  275. package/dist/workspace/decide.d.ts.map +1 -1
  276. package/dist/workspace/decision-points.schema.json +11 -4
  277. package/dist/workspace/declaration.d.ts +156 -4
  278. package/dist/workspace/declaration.d.ts.map +1 -1
  279. package/dist/workspace/declaration.schema.json +383 -5
  280. package/dist/workspace/environments.d.ts +36 -10
  281. package/dist/workspace/environments.d.ts.map +1 -1
  282. package/dist/workspace/factory-rules.d.ts +180 -0
  283. package/dist/workspace/factory-rules.d.ts.map +1 -0
  284. package/dist/workspace/generated-files.d.ts.map +1 -1
  285. package/dist/workspace/graph-cache.d.ts.map +1 -1
  286. package/dist/workspace/graph-cli.d.ts +2 -0
  287. package/dist/workspace/graph-cli.d.ts.map +1 -1
  288. package/dist/workspace/identity.d.ts +111 -0
  289. package/dist/workspace/identity.d.ts.map +1 -0
  290. package/dist/workspace/init.d.ts +21 -0
  291. package/dist/workspace/init.d.ts.map +1 -1
  292. package/dist/workspace/intent-cli.d.ts +7 -4
  293. package/dist/workspace/intent-cli.d.ts.map +1 -1
  294. package/dist/workspace/intent-record.d.ts +36 -2
  295. package/dist/workspace/intent-record.d.ts.map +1 -1
  296. package/dist/workspace/intent.d.ts +249 -8
  297. package/dist/workspace/intent.d.ts.map +1 -1
  298. package/dist/workspace/json-edit.d.ts +24 -0
  299. package/dist/workspace/json-edit.d.ts.map +1 -0
  300. package/dist/workspace/jsonc.d.ts +11 -0
  301. package/dist/workspace/jsonc.d.ts.map +1 -1
  302. package/dist/workspace/kinds.d.ts +66 -4
  303. package/dist/workspace/kinds.d.ts.map +1 -1
  304. package/dist/workspace/lexicon-symbols.d.ts +29 -0
  305. package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
  306. package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
  307. package/dist/workspace/lineage-lock.d.ts +2 -2
  308. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  309. package/dist/workspace/lineage-upgrade.d.ts +31 -2
  310. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  311. package/dist/workspace/links.d.ts.map +1 -1
  312. package/dist/workspace/point-answer.schema.json +42 -2
  313. package/dist/workspace/points-cli.d.ts +10 -3
  314. package/dist/workspace/points-cli.d.ts.map +1 -1
  315. package/dist/workspace/points.d.ts +66 -5
  316. package/dist/workspace/points.d.ts.map +1 -1
  317. package/dist/workspace/principal-classes.d.ts +114 -0
  318. package/dist/workspace/principal-classes.d.ts.map +1 -0
  319. package/dist/workspace/reason-codes.d.ts +53 -4
  320. package/dist/workspace/reason-codes.d.ts.map +1 -1
  321. package/dist/workspace/record-assets.d.ts.map +1 -1
  322. package/dist/workspace/record-sessions.d.ts +5 -7
  323. package/dist/workspace/record-sessions.d.ts.map +1 -1
  324. package/dist/workspace/records-checkout.d.ts +54 -0
  325. package/dist/workspace/records-checkout.d.ts.map +1 -0
  326. package/dist/workspace/records-cli.d.ts +34 -1
  327. package/dist/workspace/records-cli.d.ts.map +1 -1
  328. package/dist/workspace/records-close.d.ts +7 -3
  329. package/dist/workspace/records-close.d.ts.map +1 -1
  330. package/dist/workspace/records-since.d.ts.map +1 -1
  331. package/dist/workspace/records-write.d.ts +68 -7
  332. package/dist/workspace/records-write.d.ts.map +1 -1
  333. package/dist/workspace/records.d.ts +43 -9
  334. package/dist/workspace/records.d.ts.map +1 -1
  335. package/dist/workspace/runs-cli.d.ts +296 -0
  336. package/dist/workspace/runs-cli.d.ts.map +1 -0
  337. package/dist/workspace/runs.d.ts +544 -0
  338. package/dist/workspace/runs.d.ts.map +1 -0
  339. package/dist/workspace/session-kinds.d.ts +1 -1
  340. package/dist/workspace/session-kinds.d.ts.map +1 -1
  341. package/dist/workspace/source-block.d.ts +1 -1
  342. package/dist/workspace/source-block.d.ts.map +1 -1
  343. package/dist/workspace/squash.d.ts +80 -0
  344. package/dist/workspace/squash.d.ts.map +1 -0
  345. package/dist/workspace/status-gates.d.ts +17 -3
  346. package/dist/workspace/status-gates.d.ts.map +1 -1
  347. package/dist/workspace/status.d.ts +64 -0
  348. package/dist/workspace/status.d.ts.map +1 -1
  349. package/dist/workspace/symbols.d.ts +63 -0
  350. package/dist/workspace/symbols.d.ts.map +1 -0
  351. package/dist/workspace/trailer-joins.d.ts +46 -0
  352. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  353. package/dist/workspace/trailers.d.ts +89 -0
  354. package/dist/workspace/trailers.d.ts.map +1 -0
  355. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  356. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  357. package/dist/workspace/trust/run-commits.d.ts +46 -0
  358. package/dist/workspace/trust/run-commits.d.ts.map +1 -0
  359. package/dist/workspace/trust/run-statement.d.ts +128 -0
  360. package/dist/workspace/trust/run-statement.d.ts.map +1 -0
  361. package/dist/workspace/trust/seal.d.ts +38 -0
  362. package/dist/workspace/trust/seal.d.ts.map +1 -1
  363. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  364. package/dist/workspace/trust/verify-cli.d.ts +1 -1
  365. package/dist/workspace/trust/verify.d.ts +16 -2
  366. package/dist/workspace/trust/verify.d.ts.map +1 -1
  367. package/dist/workspace/wip-cli.d.ts +21 -0
  368. package/dist/workspace/wip-cli.d.ts.map +1 -0
  369. package/dist/workspace/wip.d.ts +268 -0
  370. package/dist/workspace/wip.d.ts.map +1 -0
  371. package/dist/workspace/work-cli.d.ts +39 -3
  372. package/dist/workspace/work-cli.d.ts.map +1 -1
  373. package/dist/workspace/work-evidence.d.ts +1 -1
  374. package/dist/workspace/work-evidence.d.ts.map +1 -1
  375. package/dist/workspace/work-size.d.ts +55 -0
  376. package/dist/workspace/work-size.d.ts.map +1 -0
  377. package/dist/workspace/work.d.ts +26 -1
  378. package/dist/workspace/work.d.ts.map +1 -1
  379. package/dist/workspace/workspace-kinds.schema.json +122 -0
  380. package/dist/workspace/workspace-principals.schema.json +60 -0
  381. package/dist/workspace/write-lock-cli.d.ts +60 -0
  382. package/dist/workspace/write-lock-cli.d.ts.map +1 -0
  383. package/dist/workspace/write-lock.d.ts +152 -0
  384. package/dist/workspace/write-lock.d.ts.map +1 -0
  385. package/dist/workspace/write-scope.d.ts +83 -19
  386. package/dist/workspace/write-scope.d.ts.map +1 -1
  387. package/dist/yaml.d.ts +21 -39
  388. package/dist/yaml.d.ts.map +1 -1
  389. package/package.json +7 -2
  390. package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
  391. package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
  392. package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
  393. package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
  394. package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
  395. package/src/__fixtures__/change-set/warden.plan.json +44 -0
  396. package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
  397. package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
  398. package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
  399. package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
  400. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
  401. package/src/audit/core.test.ts +15 -0
  402. package/src/audit/core.ts +8 -2
  403. package/src/audit/discover.test.ts +11 -0
  404. package/src/audit/discover.ts +7 -2
  405. package/src/audit/prior-art.ts +15 -0
  406. package/src/change-set-bundle.test.ts +57 -0
  407. package/src/change-set.test.ts +215 -0
  408. package/src/change-set.ts +445 -0
  409. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  410. package/src/cli/commands/audit-opt-in.test.ts +54 -0
  411. package/src/cli/commands/audit.ts +29 -2
  412. package/src/cli/commands/build.test.ts +19 -0
  413. package/src/cli/commands/build.ts +3 -2
  414. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  415. package/src/cli/commands/carve-emit.ts +5 -19
  416. package/src/cli/commands/check-lexicon.test.ts +62 -1
  417. package/src/cli/commands/check-lexicon.ts +36 -6
  418. package/src/cli/commands/import-live.test.ts +18 -0
  419. package/src/cli/commands/import-parser-options.test.ts +133 -0
  420. package/src/cli/commands/import.ts +21 -3
  421. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  422. package/src/cli/commands/init.test.ts +8 -1
  423. package/src/cli/commands/init.ts +23 -8
  424. package/src/cli/commands/lint.test.ts +37 -0
  425. package/src/cli/commands/onboard.test.ts +53 -3
  426. package/src/cli/commands/onboard.ts +52 -4
  427. package/src/cli/commands/pinned-upgrade.ts +73 -33
  428. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  429. package/src/cli/handlers/build.ts +13 -1
  430. package/src/cli/handlers/change-set.test.ts +56 -0
  431. package/src/cli/handlers/change-set.ts +44 -0
  432. package/src/cli/handlers/components.ts +2 -2
  433. package/src/cli/handlers/dev.ts +8 -6
  434. package/src/cli/handlers/fan-out.test.ts +221 -2
  435. package/src/cli/handlers/fan-out.ts +165 -75
  436. package/src/cli/handlers/graph.ts +3 -0
  437. package/src/cli/handlers/lifecycle.test.ts +67 -0
  438. package/src/cli/handlers/lifecycle.ts +6 -5
  439. package/src/cli/handlers/misc.ts +2 -0
  440. package/src/cli/handlers/operator.test.ts +21 -0
  441. package/src/cli/handlers/operator.ts +121 -6
  442. package/src/cli/handlers/pr.ts +373 -0
  443. package/src/cli/handlers/run.test.ts +111 -0
  444. package/src/cli/handlers/run.ts +86 -24
  445. package/src/cli/handlers/scenario.ts +2 -2
  446. package/src/cli/main.test.ts +21 -0
  447. package/src/cli/main.ts +246 -30
  448. package/src/cli/mcp/never-over-mcp.test.ts +101 -0
  449. package/src/cli/mcp/op-tools.ts +24 -2
  450. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  451. package/src/cli/mcp/workspace-tools.ts +62 -7
  452. package/src/cli/registry.ts +74 -3
  453. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  454. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  455. package/src/codegen/pinned-upgrade.test.ts +104 -0
  456. package/src/codegen/pinned-upgrade.ts +250 -56
  457. package/src/codegen/testdata/postgres-tags.json +242 -0
  458. package/src/components/auto-release.ts +1 -1
  459. package/src/components/capability.ts +55 -0
  460. package/src/components/changed-files.ts +66 -0
  461. package/src/components/cli-support.ts +28 -5
  462. package/src/components/component.schema.json +17 -0
  463. package/src/components/component.ts +25 -0
  464. package/src/components/deploy-units.ts +3 -0
  465. package/src/components/driver.test.ts +52 -0
  466. package/src/components/driver.ts +31 -13
  467. package/src/components/fan-out-output.ts +42 -1
  468. package/src/components/fan-out-record.ts +69 -0
  469. package/src/components/fan-out-run.test.ts +17 -0
  470. package/src/components/fan-out-run.ts +304 -1
  471. package/src/components/fan-out-support.ts +3 -0
  472. package/src/components/fan-out-waves.test.ts +375 -0
  473. package/src/components/fan-out.ts +18 -17
  474. package/src/components/gated-wave-pipeline.ts +82 -0
  475. package/src/components/index.ts +1 -0
  476. package/src/components/layers.ts +30 -0
  477. package/src/components/pr-pipeline.ts +91 -0
  478. package/src/components/pr-run.test.ts +205 -0
  479. package/src/components/pr-run.ts +280 -0
  480. package/src/components/promote.ts +5 -0
  481. package/src/components/verbs/shell.test.ts +11 -0
  482. package/src/components/verbs/shell.ts +7 -3
  483. package/src/components/wave-plan.ts +124 -0
  484. package/src/config.test.ts +21 -0
  485. package/src/config.ts +15 -0
  486. package/src/declarable.test.ts +21 -0
  487. package/src/declarable.ts +19 -0
  488. package/src/discovery/fold-composite.test.ts +41 -5
  489. package/src/discovery/fold-import.test.ts +129 -0
  490. package/src/discovery/fold-import.ts +643 -131
  491. package/src/discovery/fold-package-composite.test.ts +264 -0
  492. package/src/discovery/fold-specifiers.test.ts +191 -0
  493. package/src/discovery/param-deps.test.ts +66 -1
  494. package/src/discovery/param-deps.ts +45 -0
  495. package/src/discovery/sandbox/bundle.ts +1 -1
  496. package/src/discovery/specifier-resolve.ts +344 -0
  497. package/src/fold/fold.test.ts +39 -1
  498. package/src/fold/fold.ts +83 -9
  499. package/src/fold-provenance.test.ts +140 -0
  500. package/src/gated-waves-bundle.test.ts +62 -0
  501. package/src/gated-waves.test.ts +118 -0
  502. package/src/gated-waves.ts +240 -0
  503. package/src/graph-ir.test.ts +83 -0
  504. package/src/graph-ir.ts +29 -0
  505. package/src/import/embedded.test.ts +20 -0
  506. package/src/import/embedded.ts +13 -0
  507. package/src/import/parser-options.ts +46 -0
  508. package/src/import/parser.ts +20 -0
  509. package/src/index.ts +1 -0
  510. package/src/lexicon.ts +106 -3
  511. package/src/lifecycle/gate-ledger.ts +23 -0
  512. package/src/lifecycle/git.ts +102 -16
  513. package/src/lifecycle/observe.test.ts +18 -0
  514. package/src/lifecycle/observe.ts +6 -4
  515. package/src/lifecycle/snapshot.ts +2 -2
  516. package/src/lifecycle/work-lease.test.ts +1 -1
  517. package/src/lifecycle/work-lease.ts +93 -2
  518. package/src/lint/engine.test.ts +55 -0
  519. package/src/lint/engine.ts +30 -4
  520. package/src/lint/output-docs.test.ts +59 -56
  521. package/src/lint/post-synth.test.ts +19 -0
  522. package/src/lint/post-synth.ts +19 -1
  523. package/src/meta/declared-imports.test.ts +1 -1
  524. package/src/op/activities/activity-contracts.ts +84 -0
  525. package/src/op/activities/apply.test.ts +189 -5
  526. package/src/op/activities/apply.ts +230 -8
  527. package/src/op/activities/change-set.ts +114 -0
  528. package/src/op/activities/decide.ts +3 -0
  529. package/src/op/activities/factory.ts +675 -0
  530. package/src/op/activities/index.ts +9 -0
  531. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  532. package/src/op/activities/lexicon-upgrade.ts +154 -51
  533. package/src/op/activity-contract.test.ts +21 -1
  534. package/src/op/activity-contract.ts +19 -9
  535. package/src/op/builders.ts +23 -0
  536. package/src/op/composites/apply-op.ts +12 -5
  537. package/src/op/composites/composites.test.ts +30 -3
  538. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  539. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  540. package/src/op/decide-backend.ts +5 -1
  541. package/src/op/decide-read-inputs.ts +33 -5
  542. package/src/op/emulator-lifecycle.test.ts +23 -0
  543. package/src/op/emulator-lifecycle.ts +52 -14
  544. package/src/op/factory.e2e.test.ts +232 -0
  545. package/src/op/factory.ts +118 -0
  546. package/src/op/gate-approval.test.ts +74 -0
  547. package/src/op/gate-approval.ts +5 -1
  548. package/src/op/gate.ts +31 -5
  549. package/src/op/index.ts +11 -1
  550. package/src/op/local-executor.test.ts +15 -0
  551. package/src/op/local-executor.ts +40 -12
  552. package/src/op/local-output.ts +1 -1
  553. package/src/op/op-ir.test.ts +9 -0
  554. package/src/op/op-ir.ts +4 -0
  555. package/src/op/op-verb-class.ts +3 -0
  556. package/src/op/operator.ts +4 -0
  557. package/src/op/run-context.test.ts +141 -0
  558. package/src/op/run-context.ts +51 -0
  559. package/src/op/runtimes/local.test.ts +14 -0
  560. package/src/op/runtimes/local.ts +2 -0
  561. package/src/op/steward-beside.ts +2 -0
  562. package/src/op/types.ts +16 -3
  563. package/src/op/work-lease-run.test.ts +47 -0
  564. package/src/op/work-lease-run.ts +76 -11
  565. package/src/plan-summary.test.ts +263 -0
  566. package/src/plan-summary.ts +845 -0
  567. package/src/pr-forge.test.ts +237 -0
  568. package/src/pr-forge.ts +332 -0
  569. package/src/pr-loop-bundle.test.ts +46 -0
  570. package/src/pr-loop.test.ts +171 -0
  571. package/src/pr-loop.ts +324 -0
  572. package/src/provenance.ts +35 -0
  573. package/src/telemetry-attribution.test.ts +23 -1
  574. package/src/telemetry-attribution.ts +51 -0
  575. package/src/terraform/hcl2json.test.ts +21 -0
  576. package/src/terraform/hcl2json.ts +81 -0
  577. package/src/terraform/parse.ts +11 -74
  578. package/src/workspace/agent-cli.ts +7 -3
  579. package/src/workspace/agent.schema.json +22 -0
  580. package/src/workspace/app-kind.test.ts +196 -0
  581. package/src/workspace/box-cli.ts +113 -0
  582. package/src/workspace/box-factory.test.ts +323 -0
  583. package/src/workspace/box-factory.ts +136 -0
  584. package/src/workspace/box-listing-write.schema.json +204 -0
  585. package/src/workspace/box-listing.test.ts +234 -0
  586. package/src/workspace/box-listing.ts +324 -0
  587. package/src/workspace/box-publish.schema.json +498 -0
  588. package/src/workspace/box-publish.test.ts +204 -0
  589. package/src/workspace/box-publish.ts +420 -0
  590. package/src/workspace/box-ship.test.ts +96 -0
  591. package/src/workspace/broker-protocol.schema.json +186 -0
  592. package/src/workspace/broker-protocol.test.ts +122 -0
  593. package/src/workspace/broker-protocol.ts +317 -0
  594. package/src/workspace/builder-tiers.test.ts +146 -0
  595. package/src/workspace/change-set.schema.json +460 -0
  596. package/src/workspace/changes.schema.json +12 -20
  597. package/src/workspace/changes.ts +4 -1
  598. package/src/workspace/chant-migrations.e2e.test.ts +17 -5
  599. package/src/workspace/checks/boxes.test.ts +5 -0
  600. package/src/workspace/checks.ts +39 -8
  601. package/src/workspace/component-environments.test.ts +105 -0
  602. package/src/workspace/compose-graph.ts +7 -0
  603. package/src/workspace/composites.schema.json +23 -4
  604. package/src/workspace/composites.test.ts +8 -8
  605. package/src/workspace/composites.ts +13 -2
  606. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
  607. package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
  608. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  609. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  610. package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  611. package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  612. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  613. package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  614. package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  615. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  616. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  617. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  618. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  619. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  620. package/src/workspace/conformance/broker.test.ts +122 -0
  621. package/src/workspace/conformance/broker.ts +792 -0
  622. package/src/workspace/conformance/conformance.e2e.test.ts +36 -3
  623. package/src/workspace/conformance/index.mjs +51 -3
  624. package/src/workspace/conformance/index.ts +107 -15
  625. package/src/workspace/conformance/vitest.ts +76 -2
  626. package/src/workspace/conformance/writer-conformance.e2e.test.ts +177 -0
  627. package/src/workspace/conformance/writer.test.ts +186 -0
  628. package/src/workspace/conformance/writer.ts +1191 -0
  629. package/src/workspace/decide.test.ts +208 -4
  630. package/src/workspace/decide.ts +433 -73
  631. package/src/workspace/decision-points.schema.json +11 -4
  632. package/src/workspace/declaration.schema.json +383 -5
  633. package/src/workspace/declaration.ts +315 -10
  634. package/src/workspace/environments.ts +66 -14
  635. package/src/workspace/factory-rules.test.ts +62 -0
  636. package/src/workspace/factory-rules.ts +218 -0
  637. package/src/workspace/graph-cli.ts +6 -3
  638. package/src/workspace/graph.schema.json +314 -0
  639. package/src/workspace/identity.test.ts +219 -0
  640. package/src/workspace/identity.ts +186 -0
  641. package/src/workspace/init.ts +82 -2
  642. package/src/workspace/intent-cli.ts +84 -13
  643. package/src/workspace/intent-patch-id.test.ts +162 -0
  644. package/src/workspace/intent-record.schema.json +336 -1
  645. package/src/workspace/intent-record.ts +96 -16
  646. package/src/workspace/intent-reviews.test.ts +76 -0
  647. package/src/workspace/intent-squash.test.ts +213 -0
  648. package/src/workspace/intent-why.test.ts +274 -0
  649. package/src/workspace/intent.schema.json +950 -9
  650. package/src/workspace/intent.test.ts +11 -2
  651. package/src/workspace/intent.ts +722 -65
  652. package/src/workspace/json-edit.test.ts +121 -0
  653. package/src/workspace/json-edit.ts +142 -0
  654. package/src/workspace/jsonc.ts +20 -0
  655. package/src/workspace/kinds.ts +201 -39
  656. package/src/workspace/lexicon-symbols.test.ts +148 -0
  657. package/src/workspace/lexicon-symbols.ts +125 -0
  658. package/src/workspace/lineage-upgrade.test.ts +63 -0
  659. package/src/workspace/lineage-upgrade.ts +146 -5
  660. package/src/workspace/plan-summary.schema.json +155 -0
  661. package/src/workspace/point-answer.schema.json +42 -2
  662. package/src/workspace/points-cli.ts +42 -16
  663. package/src/workspace/points-write.schema.json +163 -4
  664. package/src/workspace/points.schema.json +157 -2
  665. package/src/workspace/points.test.ts +13 -1
  666. package/src/workspace/points.ts +118 -12
  667. package/src/workspace/pr-report.schema.json +95 -0
  668. package/src/workspace/principal-classes.test.ts +175 -0
  669. package/src/workspace/principal-classes.ts +307 -0
  670. package/src/workspace/profiles.test.ts +159 -0
  671. package/src/workspace/read-contract.test.ts +2 -2
  672. package/src/workspace/reason-codes.test.ts +23 -3
  673. package/src/workspace/reason-codes.ts +61 -4
  674. package/src/workspace/record-sessions.ts +9 -8
  675. package/src/workspace/records-amend.schema.json +80 -0
  676. package/src/workspace/records-checkout.ts +106 -0
  677. package/src/workspace/records-cli.ts +123 -17
  678. package/src/workspace/records-close.schema.json +79 -0
  679. package/src/workspace/records-close.ts +31 -7
  680. package/src/workspace/records-concurrent.e2e.test.ts +135 -0
  681. package/src/workspace/records-concurrent.test.ts +145 -0
  682. package/src/workspace/records-formats.test.ts +46 -10
  683. package/src/workspace/records-new.schema.json +9 -0
  684. package/src/workspace/records-review.schema.json +80 -0
  685. package/src/workspace/records-sessions-write.test.ts +69 -0
  686. package/src/workspace/records-sessions.test.ts +22 -0
  687. package/src/workspace/records-uncommitted.test.ts +171 -0
  688. package/src/workspace/records-write.ts +219 -30
  689. package/src/workspace/records.schema.json +88 -1
  690. package/src/workspace/records.ts +76 -8
  691. package/src/workspace/reference-kinds/app/package.json +10 -0
  692. package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  693. package/src/workspace/run-statement.schema.json +622 -0
  694. package/src/workspace/runs-cli.ts +710 -0
  695. package/src/workspace/runs-statement.test.ts +239 -0
  696. package/src/workspace/runs-write.schema.json +994 -0
  697. package/src/workspace/runs.schema.json +1257 -0
  698. package/src/workspace/runs.test.ts +281 -0
  699. package/src/workspace/runs.ts +970 -0
  700. package/src/workspace/session-kinds.ts +3 -3
  701. package/src/workspace/squash.ts +198 -0
  702. package/src/workspace/status-contract.test.ts +10 -2
  703. package/src/workspace/status-gates.ts +25 -9
  704. package/src/workspace/status.schema.json +252 -4
  705. package/src/workspace/status.ts +110 -1
  706. package/src/workspace/symbols.ts +191 -0
  707. package/src/workspace/trailer-joins.test.ts +171 -0
  708. package/src/workspace/trailer-joins.ts +82 -0
  709. package/src/workspace/trailers.ts +148 -0
  710. package/src/workspace/trust/run-commits.ts +115 -0
  711. package/src/workspace/trust/run-statement.ts +226 -0
  712. package/src/workspace/trust/seal.ts +58 -1
  713. package/src/workspace/trust/verify-cli.ts +6 -5
  714. package/src/workspace/trust/verify.ts +39 -6
  715. package/src/workspace/wip-cli.ts +97 -0
  716. package/src/workspace/wip-write.schema.json +504 -0
  717. package/src/workspace/wip.schema.json +334 -0
  718. package/src/workspace/wip.test.ts +294 -0
  719. package/src/workspace/wip.ts +753 -0
  720. package/src/workspace/work-cli.e2e.test.ts +28 -1
  721. package/src/workspace/work-cli.ts +136 -8
  722. package/src/workspace/work-evidence.schema.json +5 -0
  723. package/src/workspace/work-history.schema.json +73 -1
  724. package/src/workspace/work-history.test.ts +48 -5
  725. package/src/workspace/work-kind-fields.test.ts +154 -0
  726. package/src/workspace/work-lease.schema.json +14 -1
  727. package/src/workspace/work-size.test.ts +77 -0
  728. package/src/workspace/work-size.ts +93 -0
  729. package/src/workspace/work.ts +82 -0
  730. package/src/workspace/workspace-kinds.schema.json +122 -0
  731. package/src/workspace/workspace-principals.schema.json +60 -0
  732. package/src/workspace/write-lock-cli.ts +131 -0
  733. package/src/workspace/write-lock.schema.json +172 -0
  734. package/src/workspace/write-lock.test.ts +189 -0
  735. package/src/workspace/write-lock.ts +474 -0
  736. package/src/workspace/write-scope.test.ts +144 -3
  737. package/src/workspace/write-scope.ts +192 -45
  738. package/src/yaml.test.ts +111 -1
  739. package/src/yaml.ts +141 -549
@@ -0,0 +1,710 @@
1
+ /**
2
+ * `chant workspace runs` (#3033, ws-076): read and write the agent run
3
+ * record.
4
+ *
5
+ * - `runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>]
6
+ * --json` reads every run in the ledger with the commits it made, and
7
+ * totals tokens and cost per work item, per decision and per principal,
8
+ * naming the runs that report no cost instead of counting them as zero
9
+ * (`runs.schema.json`, a read-contract output).
10
+ * - `runs start --from <file|->`, `runs end <id> --from <file|->` and `runs
11
+ * record --from <file|->` append a run's start, its end, or both, to
12
+ * `_agent-runs/<id>.jsonl` on `chant/lifecycle` (`runs-write.schema.json`).
13
+ * - `runs sign <id> --key <runner key.pem> | --envelope <file|->` appends a
14
+ * statement over an ended run, signed by a runner or steward key the trust
15
+ * policy at base lists, or signed elsewhere and checked here (#3192).
16
+ * `runs statement <id> --signer <principal>` prints the statement for a
17
+ * signer that holds its key elsewhere, and `runs verify [<id>] [--require
18
+ * signed]` judges every stored statement (`run-statement.schema.json`).
19
+ *
20
+ * chant records runs and never starts one: whatever ran the agent writes the
21
+ * record. Reads never fetch, except a pull request ref `--follow-squash`
22
+ * needs (#3035).
23
+ */
24
+
25
+ import { readFileSync } from "node:fs";
26
+ import { dirname, resolve } from "node:path";
27
+ import { formatError } from "../cli/format";
28
+ import type { CommandContext } from "../cli/registry";
29
+ import { declaredRecordKinds, readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError } from "./declaration";
30
+ import { declaredKindFile } from "./declared-kinds";
31
+ import type { ReasonCode } from "./reason-codes";
32
+ import { loadRecordKind, RecordReadError } from "./records";
33
+ import { queryRecords } from "./records-cli";
34
+ import {
35
+ appendRunStatement,
36
+ commitsByRunTrailer,
37
+ endRun,
38
+ foldRun,
39
+ joinPatchIdCommits,
40
+ joinSquashCommits,
41
+ joinTrailerCommits,
42
+ LEDGER_BRANCH,
43
+ readRuns,
44
+ recordRun,
45
+ RunWriteError,
46
+ startRun,
47
+ type RunLedgerWrite,
48
+ type RunView,
49
+ type RunWriteContext,
50
+ } from "./runs";
51
+ import { RUN_TRAILER } from "./trailers";
52
+ import { locateWorkspace } from "./which-chant";
53
+ import { idList } from "./work";
54
+ import { AGENT_ENV } from "./write-scope";
55
+ import { execFileSync } from "node:child_process";
56
+ import { IN_TOTO_PAYLOAD_TYPE, loadRunnerKey, type DsseEnvelope } from "./trust/dsse";
57
+ import { policyAtBase, resolveBase, type BaseSource } from "./trust/provenance";
58
+ import type { TrustPolicy } from "./trust/policy";
59
+ import { attestRun, buildRunStatement, runStatementPayload, signRunStatement, verifyRunStatement, type RunAttestation, type RunStatement } from "./trust/run-statement";
60
+
61
+ /** The version of the `runs` documents this chant writes: read contract 1. */
62
+ export const RUNS_CONTRACT_VERSION = 1;
63
+
64
+ /** `$id` of the JSON Schema for `runs --json`, shipped beside this file. */
65
+ export const RUNS_OUTPUT_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/runs/v1/runs.schema.json";
66
+
67
+ /** `$id` of the JSON Schema for what `runs start|end|record|sign` print. */
68
+ export const RUNS_WRITE_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/runs-write/v1/runs-write.schema.json";
69
+
70
+ /** `$id` of the JSON Schema for what `runs statement` and `runs verify` print (#3192). */
71
+ export const RUN_STATEMENT_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/run-statement/v1/run-statement.schema.json";
72
+
73
+ const USAGE = [
74
+ "chant workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--follow-squash] [--json]",
75
+ "chant workspace runs start --from <file|->",
76
+ "chant workspace runs end <run id> [--from <file|->]",
77
+ "chant workspace runs record --from <file|->",
78
+ "chant workspace runs sign <run id> (--key <runner key.pem> | --envelope <file|->) [--base <rev>]",
79
+ "chant workspace runs statement <run id> --signer <principal>",
80
+ "chant workspace runs verify [<run id>] [--require signed] [--base <rev>] [--json]",
81
+ ].join("\n");
82
+
83
+ /** Why `runs` read nothing. Closed. */
84
+ export const RUNS_ERROR_CODES = [...WORKSPACE_ERROR_CODES] as const satisfies readonly ReasonCode[];
85
+ export type RunsErrorCode = (typeof RUNS_ERROR_CODES)[number];
86
+
87
+ /** Why part of the read is missing. The read still succeeds. Closed. */
88
+ export const RUNS_REASON_CODES = ["runs-no-ledger", "runs-ledger-malformed", "kind-unreadable", "squash-unfollowed"] as const satisfies readonly ReasonCode[];
89
+ export type RunsReasonCode = (typeof RUNS_REASON_CODES)[number];
90
+
91
+ /** Why a run write was refused or could not run. Closed. */
92
+ export const RUNS_WRITE_ERROR_CODES = [
93
+ ...WORKSPACE_ERROR_CODES,
94
+ "write-usage-invalid",
95
+ "write-input-invalid",
96
+ "run-exists",
97
+ "run-unknown",
98
+ "run-ended",
99
+ // runs sign (#3192)
100
+ "run-not-ended",
101
+ "trust-policy-unreadable",
102
+ "runner-key-invalid",
103
+ "runner-key-is-signer",
104
+ "runner-key-unlisted",
105
+ "envelope-unreadable",
106
+ "envelope-invalid",
107
+ "envelope-untrusted",
108
+ "run-statement-invalid",
109
+ "run-statement-signer-mismatch",
110
+ "run-statement-mismatch",
111
+ ] as const satisfies readonly ReasonCode[];
112
+ export type RunsWriteErrorCode = (typeof RUNS_WRITE_ERROR_CODES)[number];
113
+
114
+ /** Why `runs statement` or `runs verify` printed nothing to judge. Closed. */
115
+ export const RUN_STATEMENT_ERROR_CODES = [...WORKSPACE_ERROR_CODES, "write-usage-invalid", "run-unknown", "run-not-ended"] as const satisfies readonly ReasonCode[];
116
+ export type RunStatementErrorCode = (typeof RUN_STATEMENT_ERROR_CODES)[number];
117
+
118
+ // ── Totals ───────────────────────────────────────────────────────────────────
119
+
120
+ /** Tokens and cost summed over some runs. */
121
+ export interface RunTotals {
122
+ runs: number;
123
+ /** Runs with no end recorded yet. */
124
+ running: number;
125
+ /** Summed over the runs that report usage; a count a run leaves out adds nothing. */
126
+ tokens: { input: number; output: number; cacheRead: number; cacheWrite: number };
127
+ /** One sum per currency, since amounts in two currencies don't add. */
128
+ cost: { currency: string; amount: number }[];
129
+ /** The runs that report no cost, running ones included: left out of `cost`, never counted as zero. */
130
+ unpriced: string[];
131
+ /** The runs that report no usage: left out of `tokens`. */
132
+ unreported: string[];
133
+ }
134
+
135
+ const round = (n: number) => Math.round(n * 1e6) / 1e6;
136
+
137
+ export function totalRuns(runs: RunView[]): RunTotals {
138
+ const t: RunTotals = { runs: runs.length, running: 0, tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, cost: [], unpriced: [], unreported: [] };
139
+ for (const r of runs) {
140
+ if (r.state === "running") t.running++;
141
+ if (r.usage) {
142
+ t.tokens.input += r.usage.inputTokens ?? 0;
143
+ t.tokens.output += r.usage.outputTokens ?? 0;
144
+ t.tokens.cacheRead += r.usage.cacheReadTokens ?? 0;
145
+ t.tokens.cacheWrite += r.usage.cacheWriteTokens ?? 0;
146
+ } else t.unreported.push(r.id);
147
+ if (r.cost) {
148
+ const sum = t.cost.find((c) => c.currency === r.cost!.currency);
149
+ if (sum) sum.amount = round(sum.amount + r.cost.amount);
150
+ else t.cost.push({ currency: r.cost.currency, amount: round(r.cost.amount) });
151
+ } else t.unpriced.push(r.id);
152
+ }
153
+ t.cost.sort((a, b) => (a.currency < b.currency ? -1 : a.currency > b.currency ? 1 : 0));
154
+ return t;
155
+ }
156
+
157
+ /** Group runs by a key each run gives zero or more of, in first-seen order. */
158
+ function groupBy<K extends string | null>(runs: RunView[], keys: (r: RunView) => K[]): Map<K, RunView[]> {
159
+ const out = new Map<K, RunView[]>();
160
+ for (const r of runs) for (const k of keys(r)) (out.get(k) ?? out.set(k, []).get(k)!).push(r);
161
+ return out;
162
+ }
163
+
164
+ // ── The read ─────────────────────────────────────────────────────────────────
165
+
166
+ export interface RunsQuery {
167
+ cwd: string;
168
+ /** Only the runs on this work item. */
169
+ unit?: string;
170
+ /** Only the runs that carried out this decision: its id, or `<kind>/<id>`. */
171
+ decision?: string;
172
+ /** Only the runs made for this principal. */
173
+ by?: string;
174
+ /** Only the runs that made a commit after `since` on HEAD, or started after its commit date. */
175
+ since?: string;
176
+ /** The revision whose trust policy judges the run statements (#3192). Default: origin/HEAD, then main, then master. */
177
+ base?: string;
178
+ /** Follow squash merges on HEAD to their pull requests' original commits, fetching missing pull request refs (#3035). */
179
+ followSquash?: boolean;
180
+ }
181
+
182
+ export interface RunsReason {
183
+ code: RunsReasonCode;
184
+ message: string;
185
+ }
186
+
187
+ /** The trust policy at base, as far as run statements need it (#3192). */
188
+ export interface RunsTrust {
189
+ base: string | null;
190
+ baseFrom: BaseSource | null;
191
+ /** The runner and steward keys at base, by principal and class. */
192
+ runners: { principal: string; class: "runner" | "service" }[];
193
+ /** Why the policy at base can't be read. Nothing verifies then. */
194
+ problems: string[];
195
+ }
196
+
197
+ /** The policy at base for run statements, and its summary. */
198
+ export function runsTrust(top: string, base?: string): { policy: TrustPolicy; trust: RunsTrust } {
199
+ const resolved = resolveBase(top, base);
200
+ const policy = policyAtBase(top, resolved);
201
+ return {
202
+ policy,
203
+ trust: { base: resolved.commit, baseFrom: resolved.from, runners: policy.runners.map((r) => ({ principal: r.principal, class: r.class })), problems: policy.problems },
204
+ };
205
+ }
206
+
207
+ /** Judge each run's statements in place against the runners at base. */
208
+ export function attestRuns(runs: Iterable<RunView>, policy: TrustPolicy): void {
209
+ for (const r of runs) r.attestation = attestRun(r, policy.problems.length > 0 ? [] : policy.runners);
210
+ }
211
+
212
+ /** What `runs --json` prints. */
213
+ export type RunsDocument =
214
+ | {
215
+ $schema: string;
216
+ contract: number;
217
+ chant: string;
218
+ workspace: { name: string; root: string };
219
+ ledger: { branch: string; dir: string; commit: string | null };
220
+ /** The options given. `followSquash` was added within contract 1 (#3035). */
221
+ filter: { unit: string | null; decision: string | null; by: string | null; since: string | null; followSquash?: boolean };
222
+ /** The trust policy the run statements are judged by (#3192). */
223
+ trust: RunsTrust;
224
+ /** Newest first, by when each started. Each carries its `attestation`. */
225
+ runs: RunView[];
226
+ totals: {
227
+ all: RunTotals;
228
+ byUnit: (RunTotals & { unit: string | null })[];
229
+ byDecision: (RunTotals & { decision: string })[];
230
+ byPrincipal: (RunTotals & { principal: string | null })[];
231
+ };
232
+ malformed: number;
233
+ reasons: RunsReason[];
234
+ }
235
+ | { $schema: string; contract: number; chant: string; error: { code: RunsErrorCode; message: string } };
236
+
237
+ /**
238
+ * The decisions each run carried out, as `<kind>/<id>`: the ones its work
239
+ * item implements, read through the declared work kinds, and the records it
240
+ * names of a kind a work kind calls its decision kind. Fills `decisions` in
241
+ * place.
242
+ */
243
+ export async function resolveRunDecisions(runs: RunView[], rootOnDisk: string, declared: string[], reasons: RunsReason[]): Promise<void> {
244
+ const implementsOf = new Map<string, Set<string>>();
245
+ const decisionKinds = new Set<string>();
246
+ for (const file of declared) {
247
+ try {
248
+ const loaded = await loadRecordKind(file, rootOnDisk);
249
+ const work = loaded.kind.work;
250
+ if (!work) continue;
251
+ const decisionKind = (await loadRecordKind(resolve(dirname(loaded.file), work.decisions), rootOnDisk)).kind.name;
252
+ decisionKinds.add(decisionKind);
253
+ const doc = await queryRecords({ kind: loaded.file, cwd: rootOnDisk, workGaps: false });
254
+ if ("error" in doc) throw new RecordReadError(doc.error.code as never, doc.error.message);
255
+ for (const v of doc.records) {
256
+ if (v.id === null) continue;
257
+ const set = implementsOf.get(v.id) ?? implementsOf.set(v.id, new Set()).get(v.id)!;
258
+ for (const d of idList(v.data, work.implements)) set.add(`${decisionKind}/${d}`);
259
+ }
260
+ } catch (err) {
261
+ if (!(err instanceof RecordReadError)) throw err;
262
+ reasons.push({ code: "kind-unreadable", message: `${file}: ${err.message}; the decisions its work items implement are left out` });
263
+ }
264
+ }
265
+ if (decisionKinds.size === 0) decisionKinds.add("decision");
266
+ for (const r of runs) {
267
+ const out = new Set<string>(r.unit ? (implementsOf.get(r.unit.id) ?? []) : []);
268
+ for (const ref of r.records) if (decisionKinds.has(ref.kind)) out.add(`${ref.kind}/${ref.id}`);
269
+ r.decisions = [...out].sort();
270
+ }
271
+ }
272
+
273
+ function tryGit(top: string, args: string[]): string | undefined {
274
+ try {
275
+ return execFileSync("git", args, { cwd: top, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer: 256 * 1024 * 1024 });
276
+ } catch {
277
+ return undefined;
278
+ }
279
+ }
280
+
281
+ /** Read the run ledger and build the document. Never throws a {@link WorkspaceReadError}. */
282
+ export async function workspaceRuns(query: RunsQuery): Promise<RunsDocument> {
283
+ const head = { $schema: RUNS_OUTPUT_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION, chant: readerVersion() };
284
+ try {
285
+ const located = locateWorkspace(query.cwd);
286
+ const declaration = readDeclaration(located.tree, "", { rootChant: true });
287
+ const top = located.top;
288
+ if (!top) throw new WorkspaceReadError("not-a-git-repository", "agent runs are kept on the chant/lifecycle branch, and this directory is not in a git repository");
289
+ const reasons: RunsReason[] = [];
290
+ const { tip, dir, runs, malformed } = await readRuns(top, located.rootOnDisk);
291
+ if (!tip) reasons.push({ code: "runs-no-ledger", message: `this checkout has no ${LEDGER_BRANCH} branch, so there are no agent runs to read; fetch it first if the remote has one` });
292
+ if (malformed > 0) reasons.push({ code: "runs-ledger-malformed", message: `${malformed} ${malformed === 1 ? "line" : "lines"} of ${dir} on ${LEDGER_BRANCH} ${malformed === 1 ? "is" : "are"} not a run event and ${malformed === 1 ? "was" : "were"} left out` });
293
+ const byTrailer = commitsByRunTrailer(top);
294
+ joinTrailerCommits(runs, byTrailer, top);
295
+ // A commit that lost its trailer joins by content (#3036).
296
+ joinPatchIdCommits(runs, byTrailer, top);
297
+ // A squash merge joins the runs its pull request's commits join, when asked (#3035).
298
+ if (query.followSquash) {
299
+ for (const f of joinSquashCommits(runs, top)) {
300
+ if (f.problem) reasons.push({ code: "squash-unfollowed", message: `${f.sha.slice(0, 8)} squashes pull request #${f.pullRequest}, and ${f.problem}, so the runs of its original commits are not joined to it` });
301
+ }
302
+ }
303
+ const { policy, trust } = runsTrust(top, query.base);
304
+ attestRuns(runs.values(), policy);
305
+ const all = [...runs.values()];
306
+ await resolveRunDecisions(all, located.rootOnDisk, declaredRecordKinds(declaration).map((d) => declaredKindFile(d, located.rootOnDisk)), reasons);
307
+
308
+ let since: { commits: Set<string>; date: number } | undefined;
309
+ if (query.since !== undefined) {
310
+ const sha = tryGit(top, ["rev-parse", "--verify", "--quiet", `${query.since}^{commit}`])?.trim();
311
+ if (!sha) throw new WorkspaceReadError("revision-unknown", `--since ${query.since} names no commit in this repository`);
312
+ const commits = new Set((tryGit(top, ["rev-list", `${sha}..HEAD`]) ?? "").split("\n").map((s) => s.trim()).filter(Boolean));
313
+ since = { commits, date: Number(tryGit(top, ["show", "-s", "--format=%ct", sha])?.trim() ?? "0") * 1000 };
314
+ }
315
+ const wantDecision = query.decision;
316
+ const selected = all
317
+ .filter((r) => query.unit === undefined || r.unit?.id === query.unit)
318
+ .filter((r) => wantDecision === undefined || r.decisions.some((d) => d === wantDecision || d.slice(d.indexOf("/") + 1) === wantDecision))
319
+ .filter((r) => query.by === undefined || r.by === query.by)
320
+ .filter((r) => !since || r.commits.some((c) => since!.commits.has(c.sha)) || Date.parse(r.startedAt) > since.date)
321
+ .sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : a.id < b.id ? 1 : -1));
322
+
323
+ const byUnit = [...groupBy(selected, (r) => [r.unit?.id ?? null])].map(([unit, rs]) => ({ unit, ...totalRuns(rs) }));
324
+ const byDecision = [...groupBy(selected, (r) => r.decisions)].map(([decision, rs]) => ({ decision: decision as string, ...totalRuns(rs) }));
325
+ const byPrincipal = [...groupBy(selected, (r) => [r.by])].map(([principal, rs]) => ({ principal, ...totalRuns(rs) }));
326
+ return {
327
+ ...head,
328
+ workspace: { name: declaration.name, root: located.root },
329
+ ledger: { branch: LEDGER_BRANCH, dir, commit: tip },
330
+ filter: { unit: query.unit ?? null, decision: query.decision ?? null, by: query.by ?? null, since: query.since ?? null, followSquash: query.followSquash === true },
331
+ trust,
332
+ runs: selected,
333
+ totals: { all: totalRuns(selected), byUnit, byDecision, byPrincipal },
334
+ malformed,
335
+ reasons,
336
+ };
337
+ } catch (err) {
338
+ if (err instanceof WorkspaceReadError) return { ...head, error: { code: err.code as RunsErrorCode, message: err.describe() } };
339
+ throw err;
340
+ }
341
+ }
342
+
343
+ // ── The writes ───────────────────────────────────────────────────────────────
344
+
345
+ export type RunsVerb = "start" | "end" | "record" | "sign";
346
+
347
+ /** What `runs start|end|record` print. */
348
+ export type RunsWriteDocument =
349
+ | {
350
+ $schema: string;
351
+ contract: number;
352
+ verb: RunsVerb;
353
+ /** The run as the ledger now holds it. */
354
+ run: RunView;
355
+ /** The line a commit the run makes carries, `Chant-Run: <id>` (#3149). */
356
+ trailer: string;
357
+ ledger: RunLedgerWrite;
358
+ /** For `sign`: who signed the statement it stored, and the envelope (#3192). */
359
+ statement?: { signer: string; class: "runner" | "service"; keyid: string; envelope: DsseEnvelope };
360
+ }
361
+ | { $schema: string; contract: number; verb: RunsVerb | null; error: { code: RunsWriteErrorCode; message: string } };
362
+
363
+ export interface RunsWriteRequest {
364
+ verb: RunsVerb;
365
+ /** The run id, for `end`. */
366
+ id?: string;
367
+ /** The JSON fields, as text. */
368
+ fields: string;
369
+ cwd: string;
370
+ /** The agent session in `CHANT_AGENT`, the default for `agent`. */
371
+ agent?: string;
372
+ now?: () => Date;
373
+ }
374
+
375
+ /** Run one write and build the document it prints. */
376
+ export async function runsWrite(req: RunsWriteRequest): Promise<RunsWriteDocument> {
377
+ const head = { $schema: RUNS_WRITE_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION };
378
+ const fail = (code: RunsWriteErrorCode, message: string): RunsWriteDocument => ({ ...head, verb: req.verb, error: { code, message } });
379
+ let fields: unknown;
380
+ try {
381
+ fields = req.fields.trim() === "" ? {} : JSON.parse(req.fields);
382
+ } catch (err) {
383
+ return fail("write-input-invalid", `the fields are not JSON: ${err instanceof Error ? err.message : String(err)}`);
384
+ }
385
+ if (fields === null || typeof fields !== "object" || Array.isArray(fields)) return fail("write-input-invalid", "the fields are a JSON object");
386
+ if (req.verb !== "end" && req.agent && (fields as Record<string, unknown>).agent === undefined) fields = { ...(fields as object), agent: req.agent };
387
+ try {
388
+ const located = locateWorkspace(req.cwd);
389
+ const declaration = readDeclaration(located.tree, "", { rootChant: true });
390
+ if (!located.top) return fail("not-a-git-repository", "agent runs are kept on the chant/lifecycle branch, and this directory is not in a git repository");
391
+ const ctx: RunWriteContext = { top: located.top, rootOnDisk: located.rootOnDisk, cwd: req.cwd, now: req.now };
392
+ const result = req.verb === "start" ? await startRun(fields, ctx) : req.verb === "end" ? await endRun(req.id ?? "", fields, ctx) : await recordRun(fields, ctx);
393
+ const run = foldRun(result.id, result.ledger.path, result.lines)!;
394
+ await resolveRunDecisions([run], located.rootOnDisk, declaredRecordKinds(declaration).map((d) => declaredKindFile(d, located.rootOnDisk)), []);
395
+ return { ...head, verb: req.verb, run, trailer: `${RUN_TRAILER}: ${run.id}`, ledger: result.ledger };
396
+ } catch (err) {
397
+ if (err instanceof RunWriteError) return fail(err.code, err.message);
398
+ if (err instanceof WorkspaceReadError) return fail(err.code as RunsWriteErrorCode, err.describe());
399
+ throw err;
400
+ }
401
+ }
402
+
403
+ // ── Run statements (#3192) ──────────────────────────────────────────────────
404
+
405
+ /** A run as the ledger holds it now, with the commits its trailer joins. */
406
+ async function currentRun(top: string, rootOnDisk: string, id: string): Promise<RunView | undefined> {
407
+ const { runs } = await readRuns(top, rootOnDisk);
408
+ joinTrailerCommits(runs, commitsByRunTrailer(top), top);
409
+ return runs.get(id);
410
+ }
411
+
412
+ export interface RunsSignRequest {
413
+ id: string;
414
+ cwd: string;
415
+ /** A runner key in PEM: chant builds the statement and signs it. */
416
+ keyPem?: string;
417
+ /** An envelope signed elsewhere, as text: chant checks it and stores it. */
418
+ envelope?: string;
419
+ base?: string;
420
+ now?: () => Date;
421
+ }
422
+
423
+ /**
424
+ * `runs sign <id>`: store a statement over an ended run, signed here with
425
+ * `keyPem` or signed elsewhere and given as `envelope`. Either way it must
426
+ * verify against a runner key at base and agree with the run's record before
427
+ * anything is written.
428
+ */
429
+ export async function runsSign(req: RunsSignRequest): Promise<RunsWriteDocument> {
430
+ const head = { $schema: RUNS_WRITE_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION };
431
+ const fail = (code: RunsWriteErrorCode, message: string): RunsWriteDocument => ({ ...head, verb: "sign", error: { code, message } });
432
+ try {
433
+ const located = locateWorkspace(req.cwd);
434
+ const declaration = readDeclaration(located.tree, "", { rootChant: true });
435
+ const top = located.top;
436
+ if (!top) return fail("not-a-git-repository", "agent runs are kept on the chant/lifecycle branch, and this directory is not in a git repository");
437
+ const run = await currentRun(top, located.rootOnDisk, req.id);
438
+ if (!run) return fail("run-unknown", `the ledger has no agent run ${req.id}`);
439
+ if (!run.record) return fail("run-not-ended", `agent run ${req.id} has not ended; a statement is signed over a run's whole record, so record its end first`);
440
+ const { policy } = runsTrust(top, req.base);
441
+ if (policy.problems.length > 0) return fail("trust-policy-unreadable", `the policy at base cannot be read: ${policy.problems.join("; ")}`);
442
+
443
+ let envelope: DsseEnvelope;
444
+ if (req.keyPem !== undefined) {
445
+ let runner;
446
+ try {
447
+ runner = loadRunnerKey(req.keyPem);
448
+ } catch (err) {
449
+ return fail("runner-key-invalid", `the key is not an Ed25519 private key in PEM: ${err instanceof Error ? err.message : String(err)}`);
450
+ }
451
+ if (policy.signers.some((s) => s.key === runner.publicKey)) {
452
+ return fail("runner-key-is-signer", `this is a signer's key in ${policy.signersPath}. A run statement is signed by a runner or steward identity, never by a person's key`);
453
+ }
454
+ const listed = policy.runners.find((r) => r.key === runner.publicKey);
455
+ if (!listed) return fail("runner-key-unlisted", `the policy at base lists no runner with this key. Add it to .chant/trust.json "runners" first:\n ${runner.publicKey}`);
456
+ envelope = signRunStatement(buildRunStatement(run, listed.principal), runner.key, runner.publicKey);
457
+ } else {
458
+ try {
459
+ envelope = JSON.parse(req.envelope ?? "") as DsseEnvelope;
460
+ } catch (err) {
461
+ return fail("envelope-unreadable", `--envelope could not be read as JSON: ${err instanceof Error ? err.message : String(err)}`);
462
+ }
463
+ }
464
+ const verdict = verifyRunStatement(envelope, policy.runners, run);
465
+ if (verdict.status !== "verified") return fail(verdict.code, verdict.reason);
466
+
467
+ const ctx: RunWriteContext = { top, rootOnDisk: located.rootOnDisk, cwd: req.cwd, now: req.now };
468
+ const result = await appendRunStatement(run.id, envelope, run.record.sha256, ctx);
469
+ const view = foldRun(result.id, result.ledger.path, result.lines)!;
470
+ const joined = new Map([[view.id, view]]);
471
+ joinTrailerCommits(joined, commitsByRunTrailer(top), top);
472
+ await resolveRunDecisions([view], located.rootOnDisk, declaredRecordKinds(declaration).map((d) => declaredKindFile(d, located.rootOnDisk)), []);
473
+ attestRuns([view], policy);
474
+ return {
475
+ ...head,
476
+ verb: "sign",
477
+ run: view,
478
+ trailer: `${RUN_TRAILER}: ${view.id}`,
479
+ ledger: result.ledger,
480
+ statement: { signer: verdict.signer, class: verdict.class, keyid: verdict.keyid, envelope },
481
+ };
482
+ } catch (err) {
483
+ if (err instanceof RunWriteError) return fail(err.code, err.message);
484
+ if (err instanceof WorkspaceReadError) return fail(err.code as RunsWriteErrorCode, err.describe());
485
+ throw err;
486
+ }
487
+ }
488
+
489
+ /** What `runs statement` and `runs verify` print. */
490
+ export type RunStatementDocument =
491
+ | {
492
+ $schema: string;
493
+ contract: number;
494
+ chant: string;
495
+ verb: "statement";
496
+ run: string;
497
+ /** The DSSE payload type to sign under. */
498
+ payloadType: string;
499
+ /** Base64 of the payload bytes to sign: the statement's canonical JSON. */
500
+ payload: string;
501
+ statement: RunStatement;
502
+ }
503
+ | {
504
+ $schema: string;
505
+ contract: number;
506
+ chant: string;
507
+ verb: "verify";
508
+ trust: RunsTrust;
509
+ require: "signed" | null;
510
+ runs: { id: string; state: "running" | "ended"; record: { sha256: string } | null; attestation: RunAttestation }[];
511
+ summary: { runs: number; signed: number; unsigned: number; failed: number; running: number };
512
+ /** Why `--require signed` fails. Empty without it: the report alone never fails (studio-035 d). */
513
+ failures: string[];
514
+ ok: boolean;
515
+ }
516
+ | { $schema: string; contract: number; chant: string; verb: "statement" | "verify" | null; error: { code: RunStatementErrorCode; message: string } };
517
+
518
+ function statementHead() {
519
+ return { $schema: RUN_STATEMENT_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION, chant: readerVersion() };
520
+ }
521
+
522
+ /** `runs statement <id> --signer <principal>`: the statement a signer holding its key elsewhere signs. */
523
+ export async function runStatement(id: string, signer: string, cwd: string): Promise<RunStatementDocument> {
524
+ const fail = (code: RunStatementErrorCode, message: string): RunStatementDocument => ({ ...statementHead(), verb: "statement", error: { code, message } });
525
+ try {
526
+ const located = locateWorkspace(cwd);
527
+ readDeclaration(located.tree, "", { rootChant: true });
528
+ if (!located.top) return fail("not-a-git-repository", "agent runs are kept on the chant/lifecycle branch, and this directory is not in a git repository");
529
+ const run = await currentRun(located.top, located.rootOnDisk, id);
530
+ if (!run) return fail("run-unknown", `the ledger has no agent run ${id}`);
531
+ if (!run.record) return fail("run-not-ended", `agent run ${id} has not ended; a statement is signed over a run's whole record`);
532
+ const statement = buildRunStatement(run, signer);
533
+ return { ...statementHead(), verb: "statement", run: id, payloadType: IN_TOTO_PAYLOAD_TYPE, payload: runStatementPayload(statement).toString("base64"), statement };
534
+ } catch (err) {
535
+ if (err instanceof WorkspaceReadError) return fail(err.code as RunStatementErrorCode, err.describe());
536
+ throw err;
537
+ }
538
+ }
539
+
540
+ /**
541
+ * `runs verify [<id>] [--require signed]`: judge each run's statements
542
+ * against the runner keys at base. Report only unless `--require signed`
543
+ * asks every ended run, or the one named, to be signed.
544
+ */
545
+ export async function runsVerify(query: { cwd: string; id?: string; require?: "signed"; base?: string }): Promise<RunStatementDocument> {
546
+ const fail = (code: RunStatementErrorCode, message: string): RunStatementDocument => ({ ...statementHead(), verb: "verify", error: { code, message } });
547
+ try {
548
+ const located = locateWorkspace(query.cwd);
549
+ readDeclaration(located.tree, "", { rootChant: true });
550
+ const top = located.top;
551
+ if (!top) return fail("not-a-git-repository", "agent runs are kept on the chant/lifecycle branch, and this directory is not in a git repository");
552
+ const { runs } = await readRuns(top, located.rootOnDisk);
553
+ joinTrailerCommits(runs, commitsByRunTrailer(top), top);
554
+ if (query.id !== undefined && !runs.has(query.id)) return fail("run-unknown", `the ledger has no agent run ${query.id}`);
555
+ const { policy, trust } = runsTrust(top, query.base);
556
+ const selected = [...runs.values()]
557
+ .filter((r) => query.id === undefined || r.id === query.id)
558
+ .sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : a.id < b.id ? 1 : -1));
559
+ attestRuns(selected, policy);
560
+ const out = selected.map((r) => ({ id: r.id, state: r.state, record: r.record, attestation: r.attestation! }));
561
+ const failures: string[] = [];
562
+ if (query.require === "signed") {
563
+ for (const r of out) {
564
+ if (r.state === "running" || r.attestation.status === "signed") continue;
565
+ failures.push(`${r.id} is ${r.attestation.status}, and --require signed was given: ${r.attestation.reason}`);
566
+ }
567
+ }
568
+ const count = (f: (r: (typeof out)[number]) => boolean) => out.filter(f).length;
569
+ return {
570
+ ...statementHead(),
571
+ verb: "verify",
572
+ trust,
573
+ require: query.require ?? null,
574
+ runs: out,
575
+ summary: {
576
+ runs: out.length,
577
+ signed: count((r) => r.attestation.status === "signed"),
578
+ unsigned: count((r) => r.attestation.status === "unsigned"),
579
+ failed: count((r) => r.attestation.status !== "signed" && r.attestation.status !== "unsigned"),
580
+ running: count((r) => r.state === "running"),
581
+ },
582
+ failures,
583
+ ok: failures.length === 0,
584
+ };
585
+ } catch (err) {
586
+ if (err instanceof WorkspaceReadError) return fail(err.code as RunStatementErrorCode, err.describe());
587
+ throw err;
588
+ }
589
+ }
590
+
591
+ // ── Text ─────────────────────────────────────────────────────────────────────
592
+
593
+ function money(t: RunTotals): string {
594
+ const priced = t.cost.map((c) => `${c.amount} ${c.currency}`).join(" + ") || "no cost reported";
595
+ return `${priced}${t.unpriced.length > 0 ? `, ${t.unpriced.length} unpriced` : ""}`;
596
+ }
597
+
598
+ /** The read as lines for a person. */
599
+ export function formatRuns(doc: Extract<RunsDocument, { runs: unknown }>): string {
600
+ const out: string[] = [];
601
+ for (const r of doc.runs) {
602
+ const model = [r.harness.name, r.model].filter(Boolean).join("/");
603
+ const tokens = r.usage ? `${r.usage.inputTokens ?? "?"} in, ${r.usage.outputTokens ?? "?"} out` : "no usage";
604
+ const cost = r.cost ? `${r.cost.amount} ${r.cost.currency} (${r.cost.source})` : "unpriced";
605
+ const signed = r.attestation ? (r.attestation.status === "signed" ? ` signed by ${r.attestation.signer}` : r.attestation.status === "unsigned" ? "" : ` statement ${r.attestation.status}`) : "";
606
+ out.push(`${r.id} ${r.state}${r.outcome ? ` ${r.outcome}` : ""} ${r.startedAt} ${model}${r.by ? ` for ${r.by}` : ""}${r.unit ? ` on ${r.unit.id}` : ""} ${tokens} ${cost} ${r.commits.length} commit${r.commits.length === 1 ? "" : "s"}${signed}`);
607
+ }
608
+ if (doc.runs.length === 0) out.push("no agent runs");
609
+ const t = doc.totals.all;
610
+ out.push(`${t.runs} run${t.runs === 1 ? "" : "s"} (${t.running} running): ${t.tokens.input} tokens in, ${t.tokens.output} out; ${money(t)}`);
611
+ for (const r of doc.reasons) out.push(`reason ${r.code}: ${r.message}`);
612
+ return out.join("\n");
613
+ }
614
+
615
+ // ── The command ──────────────────────────────────────────────────────────────
616
+
617
+ function readFields(value: string | undefined, cwd: string): string {
618
+ if (value === undefined) return "";
619
+ return readFileSync(value === "-" ? 0 : resolve(cwd, value), "utf-8");
620
+ }
621
+
622
+ export async function runWorkspaceRuns(ctx: CommandContext): Promise<number> {
623
+ const { args } = ctx;
624
+ const cwd = process.cwd();
625
+ const verb = args.extraPositional;
626
+ if (verb === "sign" || verb === "statement" || verb === "verify") return runStatementVerb(ctx, verb, cwd);
627
+ if (verb === "start" || verb === "end" || verb === "record") {
628
+ const print = (doc: RunsWriteDocument): number => {
629
+ console.log(JSON.stringify(doc, null, 2));
630
+ return "error" in doc ? 1 : 0;
631
+ };
632
+ const usage = (message: string) => print({ $schema: RUNS_WRITE_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION, verb, error: { code: "write-usage-invalid", message } });
633
+ for (const [flag, v] of [["--unit", args.unit], ["--decision", args.decision], ["--by", args.by], ["--since", args.since], ["--follow-squash", args.followSquash]] as const) {
634
+ if (v !== undefined) return usage(`runs ${verb} takes its fields with --from, not ${flag}`);
635
+ }
636
+ if (verb === "end" && !args.extraPositional2) return usage("runs end needs the run id: runs end <run id>");
637
+ if (verb !== "end" && args.extraPositional2) return usage(`runs ${verb} takes no run id; put an id in the fields to choose one`);
638
+ if (verb !== "end" && args.migrateFrom === undefined) return usage(`runs ${verb} needs --from <file|->: the run's fields as JSON`);
639
+ let fields: string;
640
+ try {
641
+ fields = readFields(args.migrateFrom, cwd);
642
+ } catch (err) {
643
+ return print({ $schema: RUNS_WRITE_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION, verb, error: { code: "write-input-invalid", message: `--from ${args.migrateFrom} could not be read: ${err instanceof Error ? err.message : String(err)}` } });
644
+ }
645
+ return print(await runsWrite({ verb, id: args.extraPositional2, fields, cwd, agent: process.env[AGENT_ENV] || undefined }));
646
+ }
647
+ if (verb !== undefined) {
648
+ console.error(formatError({ message: `chant workspace runs takes start, end, record, sign, statement or verify, or no verb to read, not ${verb}`, hint: USAGE }));
649
+ return 1;
650
+ }
651
+ if (args.migrateFrom !== undefined) {
652
+ console.error(formatError({ message: "runs is a read and takes no --from; write with runs start, end or record", hint: USAGE }));
653
+ return 1;
654
+ }
655
+ const doc = await workspaceRuns({ cwd, unit: args.unit, decision: args.decision, by: args.by, since: args.since, base: args.base, followSquash: args.followSquash });
656
+ if (args.json) console.log(JSON.stringify(doc, null, 2));
657
+ else if ("error" in doc) console.error(formatError({ message: `${doc.error.code}: ${doc.error.message}`, hint: USAGE }));
658
+ else console.log(formatRuns(doc));
659
+ return "error" in doc ? 1 : 0;
660
+ }
661
+
662
+ async function runStatementVerb(ctx: CommandContext, verb: "sign" | "statement" | "verify", cwd: string): Promise<number> {
663
+ const { args } = ctx;
664
+ const id = args.extraPositional2;
665
+ if (verb === "sign") {
666
+ const print = (doc: RunsWriteDocument): number => {
667
+ console.log(JSON.stringify(doc, null, 2));
668
+ return "error" in doc ? 1 : 0;
669
+ };
670
+ const usage = (message: string) => print({ $schema: RUNS_WRITE_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION, verb, error: { code: "write-usage-invalid", message } });
671
+ if (!id) return usage("runs sign needs the run id: runs sign <run id> --key <runner key.pem>");
672
+ if ((args.key === undefined) === (args.envelope === undefined)) return usage("runs sign takes --key <runner key.pem> to sign here, or --envelope <file|-> for a statement signed elsewhere, not both");
673
+ let keyPem: string | undefined;
674
+ let envelope: string | undefined;
675
+ try {
676
+ if (args.key !== undefined) keyPem = readFileSync(resolve(cwd, args.key), "utf-8");
677
+ else envelope = readFields(args.envelope, cwd);
678
+ } catch (err) {
679
+ const which = args.key !== undefined ? "runner-key-invalid" : "envelope-unreadable";
680
+ return print({ $schema: RUNS_WRITE_SCHEMA_ID, contract: RUNS_CONTRACT_VERSION, verb, error: { code: which, message: `${args.key ?? args.envelope} could not be read: ${err instanceof Error ? err.message : String(err)}` } });
681
+ }
682
+ return print(await runsSign({ id, cwd, keyPem, envelope, base: args.base }));
683
+ }
684
+ const print = (doc: RunStatementDocument): number => {
685
+ if (args.json || verb === "statement" || "error" in doc) console.log(JSON.stringify(doc, null, 2));
686
+ else console.log(formatRunsVerify(doc as Extract<RunStatementDocument, { verb: "verify"; runs: unknown }>));
687
+ return "error" in doc || ("ok" in doc && !doc.ok) ? 1 : 0;
688
+ };
689
+ const usage = (message: string) => print({ ...statementHead(), verb, error: { code: "write-usage-invalid", message } });
690
+ if (verb === "statement") {
691
+ if (!id) return usage("runs statement needs the run id: runs statement <run id> --signer <principal>");
692
+ if (!args.signer) return usage("runs statement needs --signer <principal>: the runner principal whose key will sign it, as .chant/trust.json lists it");
693
+ return print(await runStatement(id, args.signer, cwd));
694
+ }
695
+ if (args.require !== undefined && args.require !== "signed") return usage(`runs verify --require takes one level, signed, not ${JSON.stringify(args.require)}`);
696
+ return print(await runsVerify({ cwd, id, require: args.require === "signed" ? "signed" : undefined, base: args.base }));
697
+ }
698
+
699
+ /** `runs verify` as lines for a person. */
700
+ export function formatRunsVerify(doc: Extract<RunStatementDocument, { verb: "verify"; runs: unknown }>): string {
701
+ const out: string[] = [];
702
+ const t = doc.trust;
703
+ out.push(`trust at base ${t.base?.slice(0, 8) ?? "none"}: ${t.runners.length} runner key${t.runners.length === 1 ? "" : "s"}${t.runners.length ? ` (${t.runners.map((r) => `${r.principal} ${r.class}`).join(", ")})` : ""}`);
704
+ for (const p of t.problems) out.push(` ${p}`);
705
+ for (const r of doc.runs) out.push(` ${r.id} ${r.state === "running" ? "running" : r.attestation.status}${r.attestation.signer ? ` by ${r.attestation.signer}` : ""} ${r.attestation.reason}`);
706
+ const s = doc.summary;
707
+ out.push(`${s.runs} run${s.runs === 1 ? "" : "s"}: ${s.signed} signed, ${s.unsigned} unsigned, ${s.failed} with a statement that does not verify, ${s.running} running`);
708
+ for (const f of doc.failures) out.push(`failure ${f}`);
709
+ return out.join("\n");
710
+ }