@intentius/chant 0.100.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 (608) 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/build.d.ts +6 -0
  9. package/dist/build.d.ts.map +1 -1
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/cli/build-options.d.ts +2 -0
  12. package/dist/cli/build-options.d.ts.map +1 -1
  13. package/dist/cli/commands/build.d.ts.map +1 -1
  14. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  15. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  16. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  17. package/dist/cli/commands/import.d.ts +8 -0
  18. package/dist/cli/commands/import.d.ts.map +1 -1
  19. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  20. package/dist/cli/commands/init.d.ts +19 -0
  21. package/dist/cli/commands/init.d.ts.map +1 -1
  22. package/dist/cli/commands/onboard.d.ts +9 -0
  23. package/dist/cli/commands/onboard.d.ts.map +1 -1
  24. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  25. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  26. package/dist/cli/handlers/dev.d.ts.map +1 -1
  27. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  28. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  29. package/dist/cli/handlers/misc.d.ts.map +1 -1
  30. package/dist/cli/handlers/operator.d.ts +9 -0
  31. package/dist/cli/handlers/operator.d.ts.map +1 -1
  32. package/dist/cli/handlers/run.d.ts.map +1 -1
  33. package/dist/cli/lsp/server.d.ts.map +1 -1
  34. package/dist/cli/main.d.ts.map +1 -1
  35. package/dist/cli/mcp/server.d.ts.map +1 -1
  36. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  37. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  38. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  39. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  40. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  41. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  42. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  43. package/dist/cli/mcp/workspace-tools.d.ts +9 -1
  44. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  45. package/dist/cli/registry.d.ts +33 -2
  46. package/dist/cli/registry.d.ts.map +1 -1
  47. package/dist/codegen/fetch.d.ts.map +1 -1
  48. package/dist/codegen/naming.d.ts.map +1 -1
  49. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  50. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  51. package/dist/codegen/registry.d.ts.map +1 -1
  52. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  53. package/dist/components/capability.d.ts.map +1 -1
  54. package/dist/components/driver.d.ts.map +1 -1
  55. package/dist/components/fan-out.d.ts.map +1 -1
  56. package/dist/components/starter-plugin.d.ts.map +1 -1
  57. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  58. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  59. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  60. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  61. package/dist/components/verbs/sign.d.ts.map +1 -1
  62. package/dist/components/verbs/verify.d.ts.map +1 -1
  63. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  64. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  65. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  66. package/dist/composite.d.ts.map +1 -1
  67. package/dist/config.d.ts +30 -7
  68. package/dist/config.d.ts.map +1 -1
  69. package/dist/declarable.d.ts +16 -0
  70. package/dist/declarable.d.ts.map +1 -1
  71. package/dist/discovery/cache.d.ts.map +1 -1
  72. package/dist/discovery/fold-import.d.ts +15 -5
  73. package/dist/discovery/fold-import.d.ts.map +1 -1
  74. package/dist/discovery/param-deps.d.ts +16 -0
  75. package/dist/discovery/param-deps.d.ts.map +1 -1
  76. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  77. package/dist/discovery/specifier-resolve.d.ts +37 -0
  78. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  79. package/dist/errors.d.ts.map +1 -1
  80. package/dist/fold/fold.d.ts +3 -1
  81. package/dist/fold/fold.d.ts.map +1 -1
  82. package/dist/graph-detail.d.ts.map +1 -1
  83. package/dist/graph-ir.d.ts.map +1 -1
  84. package/dist/graph-layout.d.ts.map +1 -1
  85. package/dist/import/base-parser.d.ts.map +1 -1
  86. package/dist/import/embedded.d.ts +7 -0
  87. package/dist/import/embedded.d.ts.map +1 -1
  88. package/dist/import/parser-options.d.ts +14 -0
  89. package/dist/import/parser-options.d.ts.map +1 -0
  90. package/dist/import/parser.d.ts +17 -0
  91. package/dist/import/parser.d.ts.map +1 -1
  92. package/dist/kubectl-context.d.ts.map +1 -1
  93. package/dist/lexicon-output.d.ts.map +1 -1
  94. package/dist/lexicon-schema.d.ts +3 -3
  95. package/dist/lexicon.d.ts +78 -3
  96. package/dist/lexicon.d.ts.map +1 -1
  97. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  98. package/dist/lifecycle/gate-ledger.d.ts +15 -0
  99. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  100. package/dist/lifecycle/git.d.ts.map +1 -1
  101. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  102. package/dist/lifecycle/observe.d.ts.map +1 -1
  103. package/dist/lifecycle/plan-digest.d.ts +26 -5
  104. package/dist/lifecycle/plan-digest.d.ts.map +1 -1
  105. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  106. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  107. package/dist/lifecycle/scenario.d.ts.map +1 -1
  108. package/dist/lifecycle/status.d.ts.map +1 -1
  109. package/dist/lifecycle/work-lease.d.ts +61 -2
  110. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  111. package/dist/lint/config.d.ts +4 -4
  112. package/dist/lint/engine.d.ts +6 -0
  113. package/dist/lint/engine.d.ts.map +1 -1
  114. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  115. package/dist/op/activities/activity-contracts.d.ts +12 -11
  116. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  117. package/dist/op/activities/apply.d.ts +79 -9
  118. package/dist/op/activities/apply.d.ts.map +1 -1
  119. package/dist/op/activities/decide.d.ts.map +1 -1
  120. package/dist/op/activities/index.d.ts +1 -1
  121. package/dist/op/activities/index.d.ts.map +1 -1
  122. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  123. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  124. package/dist/op/activities/propose-upgrade.d.ts +2 -0
  125. package/dist/op/activities/propose-upgrade.d.ts.map +1 -1
  126. package/dist/op/activity-contract.d.ts +1 -1
  127. package/dist/op/activity-failure.d.ts.map +1 -1
  128. package/dist/op/activity-profiles.d.ts.map +1 -1
  129. package/dist/op/builders.d.ts.map +1 -1
  130. package/dist/op/composites/apply-op.d.ts +12 -5
  131. package/dist/op/composites/apply-op.d.ts.map +1 -1
  132. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  133. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  134. package/dist/op/decide-backend.d.ts.map +1 -1
  135. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  136. package/dist/op/emulator-lifecycle.d.ts +21 -2
  137. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  138. package/dist/op/gate-approval.d.ts +5 -1
  139. package/dist/op/gate-approval.d.ts.map +1 -1
  140. package/dist/op/gate-wait.d.ts.map +1 -1
  141. package/dist/op/gate.d.ts +19 -3
  142. package/dist/op/gate.d.ts.map +1 -1
  143. package/dist/op/index.d.ts +3 -1
  144. package/dist/op/index.d.ts.map +1 -1
  145. package/dist/op/local-executor.d.ts +6 -0
  146. package/dist/op/local-executor.d.ts.map +1 -1
  147. package/dist/op/operator.d.ts.map +1 -1
  148. package/dist/op/run-context.d.ts +39 -0
  149. package/dist/op/run-context.d.ts.map +1 -0
  150. package/dist/op/run-live.d.ts.map +1 -1
  151. package/dist/op/runtimes/local.d.ts.map +1 -1
  152. package/dist/op/source-archive.d.ts.map +1 -1
  153. package/dist/op/steward-beside.d.ts.map +1 -1
  154. package/dist/op/steward-points.d.ts.map +1 -1
  155. package/dist/op/steward.d.ts.map +1 -1
  156. package/dist/op/types.d.ts +8 -3
  157. package/dist/op/types.d.ts.map +1 -1
  158. package/dist/op/work-lease-run.d.ts +24 -4
  159. package/dist/op/work-lease-run.d.ts.map +1 -1
  160. package/dist/project-root.d.ts.map +1 -1
  161. package/dist/provenance.d.ts +21 -0
  162. package/dist/provenance.d.ts.map +1 -1
  163. package/dist/pseudo-parameter.d.ts.map +1 -1
  164. package/dist/reconcile.d.ts.map +1 -1
  165. package/dist/secret-materialization.d.ts.map +1 -1
  166. package/dist/serializer.d.ts +8 -0
  167. package/dist/serializer.d.ts.map +1 -1
  168. package/dist/telemetry-attribution.d.ts +77 -0
  169. package/dist/telemetry-attribution.d.ts.map +1 -0
  170. package/dist/terraform/emit-source.d.ts.map +1 -1
  171. package/dist/terraform/parse.d.ts.map +1 -1
  172. package/dist/testing.d.ts.map +1 -1
  173. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  174. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  175. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  176. package/dist/workspace/agent-cli.d.ts +88 -0
  177. package/dist/workspace/agent-cli.d.ts.map +1 -0
  178. package/dist/workspace/box-factory.d.ts +73 -0
  179. package/dist/workspace/box-factory.d.ts.map +1 -0
  180. package/dist/workspace/changes-cli.d.ts.map +1 -1
  181. package/dist/workspace/changes.d.ts +8 -1
  182. package/dist/workspace/changes.d.ts.map +1 -1
  183. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  184. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  185. package/dist/workspace/checks/links.d.ts +1 -0
  186. package/dist/workspace/checks/links.d.ts.map +1 -1
  187. package/dist/workspace/checks/live.d.ts +40 -0
  188. package/dist/workspace/checks/live.d.ts.map +1 -0
  189. package/dist/workspace/checks.d.ts +26 -2
  190. package/dist/workspace/checks.d.ts.map +1 -1
  191. package/dist/workspace/compose-graph.d.ts +73 -0
  192. package/dist/workspace/compose-graph.d.ts.map +1 -1
  193. package/dist/workspace/conformance/index.d.ts +67 -6
  194. package/dist/workspace/conformance/index.d.ts.map +1 -1
  195. package/dist/workspace/conformance/vitest.d.ts +12 -3
  196. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  197. package/dist/workspace/conformance/writer.d.ts +368 -0
  198. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  199. package/dist/workspace/decide.d.ts +1 -1
  200. package/dist/workspace/decide.d.ts.map +1 -1
  201. package/dist/workspace/declaration.d.ts +119 -0
  202. package/dist/workspace/declaration.d.ts.map +1 -1
  203. package/dist/workspace/declaration.schema.json +368 -4
  204. package/dist/workspace/export-cli.d.ts +12 -0
  205. package/dist/workspace/export-cli.d.ts.map +1 -0
  206. package/dist/workspace/export.d.ts +145 -0
  207. package/dist/workspace/export.d.ts.map +1 -0
  208. package/dist/workspace/generated-files.d.ts.map +1 -1
  209. package/dist/workspace/graph-cache.d.ts.map +1 -1
  210. package/dist/workspace/graph-cli.d.ts +2 -0
  211. package/dist/workspace/graph-cli.d.ts.map +1 -1
  212. package/dist/workspace/identity.d.ts +111 -0
  213. package/dist/workspace/identity.d.ts.map +1 -0
  214. package/dist/workspace/import.d.ts +73 -0
  215. package/dist/workspace/import.d.ts.map +1 -0
  216. package/dist/workspace/intent-cli.d.ts +7 -4
  217. package/dist/workspace/intent-cli.d.ts.map +1 -1
  218. package/dist/workspace/intent-record.d.ts +8 -1
  219. package/dist/workspace/intent-record.d.ts.map +1 -1
  220. package/dist/workspace/intent.d.ts +149 -5
  221. package/dist/workspace/intent.d.ts.map +1 -1
  222. package/dist/workspace/kinds.d.ts +24 -6
  223. package/dist/workspace/kinds.d.ts.map +1 -1
  224. package/dist/workspace/lineage-adopt-cli.d.ts +15 -0
  225. package/dist/workspace/lineage-adopt-cli.d.ts.map +1 -0
  226. package/dist/workspace/lineage-adopt.d.ts +106 -0
  227. package/dist/workspace/lineage-adopt.d.ts.map +1 -0
  228. package/dist/workspace/lineage-check.d.ts +9 -2
  229. package/dist/workspace/lineage-check.d.ts.map +1 -1
  230. package/dist/workspace/lineage-cli.d.ts +6 -1
  231. package/dist/workspace/lineage-cli.d.ts.map +1 -1
  232. package/dist/workspace/lineage-hash-index.d.ts +110 -0
  233. package/dist/workspace/lineage-hash-index.d.ts.map +1 -0
  234. package/dist/workspace/lineage-init.d.ts +10 -0
  235. package/dist/workspace/lineage-init.d.ts.map +1 -1
  236. package/dist/workspace/lineage-lock.d.ts +149 -2
  237. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  238. package/dist/workspace/lineage-migrations.d.ts +15 -3
  239. package/dist/workspace/lineage-migrations.d.ts.map +1 -1
  240. package/dist/workspace/lineage-provenance.d.ts +18 -0
  241. package/dist/workspace/lineage-provenance.d.ts.map +1 -0
  242. package/dist/workspace/lineage-upgrade-cli.d.ts +2 -0
  243. package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -1
  244. package/dist/workspace/lineage-upgrade.d.ts +30 -1
  245. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  246. package/dist/workspace/lineage-versions.d.ts +116 -0
  247. package/dist/workspace/lineage-versions.d.ts.map +1 -0
  248. package/dist/workspace/links.d.ts +31 -5
  249. package/dist/workspace/links.d.ts.map +1 -1
  250. package/dist/workspace/ls-generated.d.ts +37 -0
  251. package/dist/workspace/ls-generated.d.ts.map +1 -0
  252. package/dist/workspace/ls.d.ts +4 -0
  253. package/dist/workspace/ls.d.ts.map +1 -1
  254. package/dist/workspace/member-commands.d.ts.map +1 -1
  255. package/dist/workspace/nested-graph.d.ts +56 -0
  256. package/dist/workspace/nested-graph.d.ts.map +1 -0
  257. package/dist/workspace/nesting.d.ts +21 -0
  258. package/dist/workspace/nesting.d.ts.map +1 -0
  259. package/dist/workspace/pin-cli.d.ts +10 -0
  260. package/dist/workspace/pin-cli.d.ts.map +1 -0
  261. package/dist/workspace/pin-integrity.d.ts +51 -0
  262. package/dist/workspace/pin-integrity.d.ts.map +1 -0
  263. package/dist/workspace/points.d.ts.map +1 -1
  264. package/dist/workspace/principal-classes.d.ts +114 -0
  265. package/dist/workspace/principal-classes.d.ts.map +1 -0
  266. package/dist/workspace/reason-codes.d.ts +47 -3
  267. package/dist/workspace/reason-codes.d.ts.map +1 -1
  268. package/dist/workspace/record-assets.d.ts.map +1 -1
  269. package/dist/workspace/record-sessions.d.ts +7 -11
  270. package/dist/workspace/record-sessions.d.ts.map +1 -1
  271. package/dist/workspace/records-checkout.d.ts +54 -0
  272. package/dist/workspace/records-checkout.d.ts.map +1 -0
  273. package/dist/workspace/records-cli.d.ts +57 -2
  274. package/dist/workspace/records-cli.d.ts.map +1 -1
  275. package/dist/workspace/records-close.d.ts +5 -2
  276. package/dist/workspace/records-close.d.ts.map +1 -1
  277. package/dist/workspace/records-since.d.ts.map +1 -1
  278. package/dist/workspace/records-write.d.ts +23 -4
  279. package/dist/workspace/records-write.d.ts.map +1 -1
  280. package/dist/workspace/records.d.ts +58 -5
  281. package/dist/workspace/records.d.ts.map +1 -1
  282. package/dist/workspace/returns.d.ts +129 -0
  283. package/dist/workspace/returns.d.ts.map +1 -0
  284. package/dist/workspace/runs-cli.d.ts +164 -0
  285. package/dist/workspace/runs-cli.d.ts.map +1 -0
  286. package/dist/workspace/runs.d.ts +423 -0
  287. package/dist/workspace/runs.d.ts.map +1 -0
  288. package/dist/workspace/source-block.d.ts +1 -1
  289. package/dist/workspace/source-block.d.ts.map +1 -1
  290. package/dist/workspace/status-gates.d.ts +15 -3
  291. package/dist/workspace/status-gates.d.ts.map +1 -1
  292. package/dist/workspace/status.d.ts +10 -0
  293. package/dist/workspace/status.d.ts.map +1 -1
  294. package/dist/workspace/symbols.d.ts +52 -0
  295. package/dist/workspace/symbols.d.ts.map +1 -0
  296. package/dist/workspace/template-manifest.d.ts +11 -3
  297. package/dist/workspace/template-manifest.d.ts.map +1 -1
  298. package/dist/workspace/trailer-joins.d.ts +46 -0
  299. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  300. package/dist/workspace/trailers.d.ts +89 -0
  301. package/dist/workspace/trailers.d.ts.map +1 -0
  302. package/dist/workspace/trust/attestor.d.ts +8 -0
  303. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  304. package/dist/workspace/trust/dsse.d.ts +58 -0
  305. package/dist/workspace/trust/dsse.d.ts.map +1 -0
  306. package/dist/workspace/trust/evidence-cli.d.ts +66 -0
  307. package/dist/workspace/trust/evidence-cli.d.ts.map +1 -0
  308. package/dist/workspace/trust/evidence.d.ts +93 -0
  309. package/dist/workspace/trust/evidence.d.ts.map +1 -0
  310. package/dist/workspace/trust/policy.d.ts +54 -1
  311. package/dist/workspace/trust/policy.d.ts.map +1 -1
  312. package/dist/workspace/trust/provenance.d.ts +21 -1
  313. package/dist/workspace/trust/provenance.d.ts.map +1 -1
  314. package/dist/workspace/trust/rotation.d.ts +132 -0
  315. package/dist/workspace/trust/rotation.d.ts.map +1 -0
  316. package/dist/workspace/trust/seal.d.ts +33 -0
  317. package/dist/workspace/trust/seal.d.ts.map +1 -1
  318. package/dist/workspace/trust/signers-cli.d.ts +49 -0
  319. package/dist/workspace/trust/signers-cli.d.ts.map +1 -0
  320. package/dist/workspace/trust/ssh-commit.d.ts +12 -0
  321. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
  322. package/dist/workspace/trust/test-repo.d.ts +13 -0
  323. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  324. package/dist/workspace/trust/verify.d.ts +15 -0
  325. package/dist/workspace/trust/verify.d.ts.map +1 -1
  326. package/dist/workspace/work-cli.d.ts +39 -3
  327. package/dist/workspace/work-cli.d.ts.map +1 -1
  328. package/dist/workspace/work-evidence.d.ts +1 -1
  329. package/dist/workspace/work-evidence.d.ts.map +1 -1
  330. package/dist/workspace/work.d.ts +26 -1
  331. package/dist/workspace/work.d.ts.map +1 -1
  332. package/dist/workspace/workspace-principals.schema.json +60 -0
  333. package/dist/workspace/write-scope.d.ts +259 -0
  334. package/dist/workspace/write-scope.d.ts.map +1 -0
  335. package/dist/yaml.d.ts +21 -39
  336. package/dist/yaml.d.ts.map +1 -1
  337. package/package.json +2 -2
  338. package/src/audit/prior-art.ts +15 -0
  339. package/src/build.ts +8 -0
  340. package/src/cli/build-options.ts +4 -1
  341. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  342. package/src/cli/commands/build.ts +2 -0
  343. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  344. package/src/cli/commands/carve-emit.ts +5 -19
  345. package/src/cli/commands/check-lexicon.test.ts +62 -1
  346. package/src/cli/commands/check-lexicon.ts +36 -6
  347. package/src/cli/commands/import-live.test.ts +87 -1
  348. package/src/cli/commands/import-parser-options.test.ts +133 -0
  349. package/src/cli/commands/import.ts +69 -25
  350. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  351. package/src/cli/commands/init.test.ts +8 -1
  352. package/src/cli/commands/init.ts +23 -8
  353. package/src/cli/commands/lint.test.ts +37 -0
  354. package/src/cli/commands/onboard.test.ts +53 -3
  355. package/src/cli/commands/onboard.ts +52 -4
  356. package/src/cli/commands/pinned-upgrade.ts +73 -33
  357. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  358. package/src/cli/handlers/components.ts +2 -2
  359. package/src/cli/handlers/dev.ts +8 -6
  360. package/src/cli/handlers/fan-out.test.ts +6 -6
  361. package/src/cli/handlers/fan-out.ts +2 -1
  362. package/src/cli/handlers/graph.test.ts +42 -0
  363. package/src/cli/handlers/graph.ts +22 -0
  364. package/src/cli/handlers/lifecycle.test.ts +67 -0
  365. package/src/cli/handlers/lifecycle.ts +6 -5
  366. package/src/cli/handlers/misc.ts +2 -0
  367. package/src/cli/handlers/operator.ts +88 -4
  368. package/src/cli/handlers/run.test.ts +111 -0
  369. package/src/cli/handlers/run.ts +85 -24
  370. package/src/cli/handlers/scenario.ts +2 -2
  371. package/src/cli/main.test.ts +33 -0
  372. package/src/cli/main.ts +168 -17
  373. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  374. package/src/cli/mcp/workspace-tools.ts +62 -4
  375. package/src/cli/registry.ts +33 -2
  376. package/src/cli/serve-mcp-workspace.test.ts +1 -1
  377. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  378. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  379. package/src/codegen/pinned-upgrade.test.ts +104 -0
  380. package/src/codegen/pinned-upgrade.ts +250 -56
  381. package/src/codegen/release-wiring.test.ts +5 -1
  382. package/src/codegen/testdata/postgres-tags.json +242 -0
  383. package/src/components/fan-out-output.test.ts +1 -1
  384. package/src/components/fan-out.test.ts +1 -1
  385. package/src/components/promote.test.ts +1 -1
  386. package/src/config.test.ts +21 -0
  387. package/src/config.ts +27 -0
  388. package/src/content-digest.test.ts +2 -2
  389. package/src/declarable.test.ts +21 -0
  390. package/src/declarable.ts +19 -0
  391. package/src/discovery/fold-composite.test.ts +41 -5
  392. package/src/discovery/fold-import.test.ts +129 -0
  393. package/src/discovery/fold-import.ts +643 -131
  394. package/src/discovery/fold-package-composite.test.ts +264 -0
  395. package/src/discovery/fold-specifiers.test.ts +191 -0
  396. package/src/discovery/param-deps.test.ts +66 -1
  397. package/src/discovery/param-deps.ts +45 -0
  398. package/src/discovery/specifier-resolve.ts +344 -0
  399. package/src/fold/fold.test.ts +39 -1
  400. package/src/fold/fold.ts +83 -9
  401. package/src/fold-provenance.test.ts +140 -0
  402. package/src/graph-ir.test.ts +83 -0
  403. package/src/graph-ir.ts +29 -0
  404. package/src/import/embedded.test.ts +20 -0
  405. package/src/import/embedded.ts +13 -0
  406. package/src/import/parser-options.ts +46 -0
  407. package/src/import/parser.ts +20 -0
  408. package/src/lexicon.ts +79 -3
  409. package/src/lifecycle/gate-ledger.test.ts +14 -0
  410. package/src/lifecycle/gate-ledger.ts +18 -1
  411. package/src/lifecycle/observe.test.ts +18 -0
  412. package/src/lifecycle/observe.ts +6 -4
  413. package/src/lifecycle/plan-digest.test.ts +54 -3
  414. package/src/lifecycle/plan-digest.ts +38 -8
  415. package/src/lifecycle/snapshot.ts +2 -2
  416. package/src/lifecycle/work-lease.test.ts +1 -1
  417. package/src/lifecycle/work-lease.ts +93 -2
  418. package/src/lint/engine.test.ts +55 -0
  419. package/src/lint/engine.ts +30 -4
  420. package/src/lint/output-docs.test.ts +59 -56
  421. package/src/op/activities/activity-contracts.ts +1 -0
  422. package/src/op/activities/apply.test.ts +189 -5
  423. package/src/op/activities/apply.ts +230 -8
  424. package/src/op/activities/index.ts +3 -0
  425. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  426. package/src/op/activities/lexicon-upgrade.ts +154 -51
  427. package/src/op/activities/propose-upgrade.ts +8 -5
  428. package/src/op/composites/apply-op.ts +12 -5
  429. package/src/op/composites/composites.test.ts +30 -3
  430. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  431. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  432. package/src/op/emulator-lifecycle.test.ts +23 -0
  433. package/src/op/emulator-lifecycle.ts +52 -14
  434. package/src/op/gate-approval.test.ts +91 -0
  435. package/src/op/gate-approval.ts +5 -1
  436. package/src/op/gate.ts +34 -8
  437. package/src/op/index.ts +3 -1
  438. package/src/op/local-executor.test.ts +15 -0
  439. package/src/op/local-executor.ts +40 -12
  440. package/src/op/local-output.ts +1 -1
  441. package/src/op/operator.ts +4 -0
  442. package/src/op/run-context.test.ts +141 -0
  443. package/src/op/run-context.ts +51 -0
  444. package/src/op/runtimes/local.test.ts +14 -0
  445. package/src/op/runtimes/local.ts +2 -0
  446. package/src/op/steward-beside.ts +2 -0
  447. package/src/op/types.ts +8 -3
  448. package/src/op/work-lease-run.test.ts +47 -0
  449. package/src/op/work-lease-run.ts +73 -11
  450. package/src/provenance.ts +35 -0
  451. package/src/serializer.ts +9 -0
  452. package/src/telemetry-attribution.test.ts +91 -0
  453. package/src/telemetry-attribution.ts +145 -0
  454. package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
  455. package/src/workspace/agent-cli.ts +138 -0
  456. package/src/workspace/agent.schema.json +378 -0
  457. package/src/workspace/behold-kinds.test.ts +1 -1
  458. package/src/workspace/box-factory.test.ts +320 -0
  459. package/src/workspace/box-factory.ts +103 -0
  460. package/src/workspace/changes-cli.ts +5 -0
  461. package/src/workspace/changes.schema.json +171 -1
  462. package/src/workspace/changes.ts +61 -4
  463. package/src/workspace/check-live.test.ts +192 -0
  464. package/src/workspace/check.schema.json +64 -0
  465. package/src/workspace/checks/boxes.test.ts +2 -0
  466. package/src/workspace/checks/links.ts +23 -2
  467. package/src/workspace/checks/live.ts +113 -0
  468. package/src/workspace/checks.test.ts +2 -2
  469. package/src/workspace/checks.ts +49 -8
  470. package/src/workspace/compose-graph.test.ts +47 -0
  471. package/src/workspace/compose-graph.ts +127 -3
  472. package/src/workspace/conformance/__fixture__/decisions/decision.kind.mjs +7 -1
  473. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +5 -0
  474. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +27 -0
  475. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +95 -0
  476. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +132 -0
  477. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +48 -0
  478. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +108 -0
  479. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  480. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  481. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +578 -0
  482. package/src/workspace/conformance/conformance.e2e.test.ts +35 -3
  483. package/src/workspace/conformance/index.mjs +30 -3
  484. package/src/workspace/conformance/index.ts +103 -15
  485. package/src/workspace/conformance/vitest.ts +44 -2
  486. package/src/workspace/conformance/writer-conformance.e2e.test.ts +131 -0
  487. package/src/workspace/conformance/writer.test.ts +156 -0
  488. package/src/workspace/conformance/writer.ts +880 -0
  489. package/src/workspace/decide.ts +7 -1
  490. package/src/workspace/declaration.schema.json +368 -4
  491. package/src/workspace/declaration.ts +270 -1
  492. package/src/workspace/declared-kinds.test.ts +33 -0
  493. package/src/workspace/evidence.schema.json +279 -0
  494. package/src/workspace/export-cli.ts +180 -0
  495. package/src/workspace/export-import.test.ts +282 -0
  496. package/src/workspace/export.ts +486 -0
  497. package/src/workspace/graph-cli.ts +51 -2
  498. package/src/workspace/graph-contract.test.ts +89 -4
  499. package/src/workspace/graph.schema.json +453 -1
  500. package/src/workspace/identity.test.ts +196 -0
  501. package/src/workspace/identity.ts +186 -0
  502. package/src/workspace/import.ts +325 -0
  503. package/src/workspace/intent-cli.ts +64 -10
  504. package/src/workspace/intent-record.schema.json +208 -0
  505. package/src/workspace/intent-record.ts +35 -1
  506. package/src/workspace/intent-why.test.ts +274 -0
  507. package/src/workspace/intent.schema.json +718 -7
  508. package/src/workspace/intent.test.ts +11 -2
  509. package/src/workspace/intent.ts +495 -32
  510. package/src/workspace/kinds.test.ts +5 -5
  511. package/src/workspace/kinds.ts +62 -33
  512. package/src/workspace/lineage-adopt-cli.ts +103 -0
  513. package/src/workspace/lineage-adopt.test.ts +552 -0
  514. package/src/workspace/lineage-adopt.ts +452 -0
  515. package/src/workspace/lineage-check.ts +26 -5
  516. package/src/workspace/lineage-cli.ts +12 -2
  517. package/src/workspace/lineage-hash-index.ts +305 -0
  518. package/src/workspace/lineage-init.test.ts +9 -0
  519. package/src/workspace/lineage-init.ts +29 -9
  520. package/src/workspace/lineage-lock.ts +54 -0
  521. package/src/workspace/lineage-migrations.test.ts +27 -0
  522. package/src/workspace/lineage-migrations.ts +44 -14
  523. package/src/workspace/lineage-provenance.ts +40 -0
  524. package/src/workspace/lineage-upgrade-cli.ts +9 -5
  525. package/src/workspace/lineage-upgrade.test.ts +92 -1
  526. package/src/workspace/lineage-upgrade.ts +111 -16
  527. package/src/workspace/lineage-versions.ts +348 -0
  528. package/src/workspace/links.test.ts +121 -2
  529. package/src/workspace/links.ts +97 -6
  530. package/src/workspace/ls-contract.test.ts +84 -1
  531. package/src/workspace/ls-generated.ts +111 -0
  532. package/src/workspace/ls.schema.json +19 -0
  533. package/src/workspace/ls.ts +8 -1
  534. package/src/workspace/member-commands.ts +3 -1
  535. package/src/workspace/nested-graph.test.ts +176 -0
  536. package/src/workspace/nested-graph.ts +169 -0
  537. package/src/workspace/nesting.ts +37 -0
  538. package/src/workspace/pin-cli.test.ts +71 -0
  539. package/src/workspace/pin-cli.ts +57 -0
  540. package/src/workspace/pin-integrity.test.ts +121 -0
  541. package/src/workspace/pin-integrity.ts +104 -0
  542. package/src/workspace/points-write.schema.json +2 -0
  543. package/src/workspace/principal-classes.test.ts +175 -0
  544. package/src/workspace/principal-classes.ts +307 -0
  545. package/src/workspace/read-contract.test.ts +24 -0
  546. package/src/workspace/reason-codes.test.ts +20 -2
  547. package/src/workspace/reason-codes.ts +53 -3
  548. package/src/workspace/record-sessions.ts +12 -14
  549. package/src/workspace/records-amend.schema.json +6 -0
  550. package/src/workspace/records-checkout.ts +106 -0
  551. package/src/workspace/records-cli.ts +195 -22
  552. package/src/workspace/records-close.schema.json +7 -2
  553. package/src/workspace/records-close.ts +10 -2
  554. package/src/workspace/records-formats.test.ts +13 -5
  555. package/src/workspace/records-new.schema.json +6 -0
  556. package/src/workspace/records-review.schema.json +6 -0
  557. package/src/workspace/records-sessions.test.ts +23 -6
  558. package/src/workspace/records-uncommitted.test.ts +171 -0
  559. package/src/workspace/records-write.test.ts +65 -8
  560. package/src/workspace/records-write.ts +92 -6
  561. package/src/workspace/records.schema.json +127 -4
  562. package/src/workspace/records.ts +123 -5
  563. package/src/workspace/returns.ts +328 -0
  564. package/src/workspace/runs-cli.ts +381 -0
  565. package/src/workspace/runs-write.schema.json +583 -0
  566. package/src/workspace/runs.schema.json +810 -0
  567. package/src/workspace/runs.test.ts +242 -0
  568. package/src/workspace/runs.ts +709 -0
  569. package/src/workspace/signers.schema.json +206 -0
  570. package/src/workspace/status-contract.test.ts +5 -0
  571. package/src/workspace/status-gates.ts +24 -9
  572. package/src/workspace/status.schema.json +127 -2
  573. package/src/workspace/status.ts +21 -1
  574. package/src/workspace/symbols.ts +180 -0
  575. package/src/workspace/template-manifest.ts +22 -4
  576. package/src/workspace/trailer-joins.test.ts +171 -0
  577. package/src/workspace/trailer-joins.ts +82 -0
  578. package/src/workspace/trailers.ts +148 -0
  579. package/src/workspace/trust/attestor.ts +15 -0
  580. package/src/workspace/trust/dsse.ts +134 -0
  581. package/src/workspace/trust/evidence-cli.ts +195 -0
  582. package/src/workspace/trust/evidence.test.ts +241 -0
  583. package/src/workspace/trust/evidence.ts +207 -0
  584. package/src/workspace/trust/policy.ts +110 -3
  585. package/src/workspace/trust/provenance.ts +41 -4
  586. package/src/workspace/trust/record-seal.test.ts +1 -1
  587. package/src/workspace/trust/rotation.test.ts +258 -0
  588. package/src/workspace/trust/rotation.ts +336 -0
  589. package/src/workspace/trust/seal.ts +63 -1
  590. package/src/workspace/trust/signers-cli.ts +178 -0
  591. package/src/workspace/trust/ssh-commit.ts +53 -4
  592. package/src/workspace/trust/test-repo.ts +18 -0
  593. package/src/workspace/trust/trust.test.ts +8 -2
  594. package/src/workspace/trust/verify-cli.ts +1 -0
  595. package/src/workspace/trust/verify.ts +22 -0
  596. package/src/workspace/work-cli.e2e.test.ts +28 -1
  597. package/src/workspace/work-cli.ts +133 -8
  598. package/src/workspace/work-evidence.schema.json +6 -0
  599. package/src/workspace/work-history.schema.json +73 -1
  600. package/src/workspace/work-history.test.ts +48 -5
  601. package/src/workspace/work-kind-fields.test.ts +154 -0
  602. package/src/workspace/work-lease.schema.json +14 -1
  603. package/src/workspace/work.ts +82 -0
  604. package/src/workspace/workspace-principals.schema.json +60 -0
  605. package/src/workspace/write-scope.test.ts +466 -0
  606. package/src/workspace/write-scope.ts +573 -0
  607. package/src/yaml.test.ts +111 -1
  608. package/src/yaml.ts +141 -549
@@ -0,0 +1,206 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://intentius.io/chant/schemas/workspace/signers/v1/signers.schema.json",
4
+ "title": "chant workspace signers output",
5
+ "description": "What `chant workspace signers --json` prints (#2553): the signer set's versions along the base revision's first-parent line, oldest first, each signed by a threshold of the one before, and where the chain breaks when it does. A commit is judged by the version in effect where it entered that line. Version 1 of the read contract. Readers ignore fields they do not know; a field is only ever added within a version. The codes are a closed list, each in the one closed list of `reason-codes.ts`.",
6
+ "oneOf": [
7
+ {
8
+ "$ref": "#/$defs/result"
9
+ },
10
+ {
11
+ "$ref": "#/$defs/failure"
12
+ }
13
+ ],
14
+ "$defs": {
15
+ "result": {
16
+ "type": "object",
17
+ "description": "The history was read. It exits 1 when `broken` is not null.",
18
+ "required": [
19
+ "$schema",
20
+ "contract",
21
+ "chant",
22
+ "base",
23
+ "signersPath",
24
+ "versions",
25
+ "broken"
26
+ ],
27
+ "properties": {
28
+ "$schema": {
29
+ "const": "https://intentius.io/chant/schemas/workspace/signers/v1/signers.schema.json"
30
+ },
31
+ "contract": {
32
+ "const": 1
33
+ },
34
+ "chant": {
35
+ "type": "string",
36
+ "description": "The chant version that printed the document."
37
+ },
38
+ "base": {
39
+ "type": "string",
40
+ "pattern": "^(?:[0-9a-f]{40}|[0-9a-f]{64})$",
41
+ "description": "The full commit id of the base revision the history is read along."
42
+ },
43
+ "signersPath": {
44
+ "type": "string",
45
+ "description": "The signers file, from the repository root. Its rotation file is `<signersPath>.rotation.json`."
46
+ },
47
+ "versions": {
48
+ "type": "array",
49
+ "items": {
50
+ "$ref": "#/$defs/version"
51
+ }
52
+ },
53
+ "broken": {
54
+ "oneOf": [
55
+ {
56
+ "type": "null"
57
+ },
58
+ {
59
+ "$ref": "#/$defs/broken"
60
+ }
61
+ ]
62
+ }
63
+ }
64
+ },
65
+ "version": {
66
+ "type": "object",
67
+ "description": "One version of the signer set, made by one first-parent commit.",
68
+ "required": [
69
+ "version",
70
+ "commit",
71
+ "digest",
72
+ "threshold",
73
+ "principals",
74
+ "signedBy"
75
+ ],
76
+ "properties": {
77
+ "version": {
78
+ "type": "integer",
79
+ "minimum": 0,
80
+ "description": "1 and up. 0 marks the commit that removed the signers file; nothing is in effect after it."
81
+ },
82
+ "commit": {
83
+ "oneOf": [
84
+ {
85
+ "type": "null"
86
+ },
87
+ {
88
+ "type": "string",
89
+ "pattern": "^(?:[0-9a-f]{40}|[0-9a-f]{64})$"
90
+ }
91
+ ],
92
+ "description": "The first-parent commit that made this version."
93
+ },
94
+ "digest": {
95
+ "oneOf": [
96
+ {
97
+ "type": "null"
98
+ },
99
+ {
100
+ "type": "string",
101
+ "pattern": "^sha256:[0-9a-f]{64}$"
102
+ }
103
+ ],
104
+ "description": "sha256 of the signers file, line endings normalised. Null for version 0."
105
+ },
106
+ "threshold": {
107
+ "type": "integer",
108
+ "minimum": 0,
109
+ "description": "How many distinct signers of this version must sign the next one."
110
+ },
111
+ "principals": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string"
115
+ },
116
+ "description": "The principals the version lists, sorted."
117
+ },
118
+ "signedBy": {
119
+ "type": "array",
120
+ "items": {
121
+ "type": "string"
122
+ },
123
+ "description": "The principals of the version before whose signatures counted. Empty for the first version."
124
+ }
125
+ }
126
+ },
127
+ "broken": {
128
+ "type": "object",
129
+ "description": "The version that is not a valid rotation of the one before. Nothing verifies against this base.",
130
+ "required": [
131
+ "commit",
132
+ "code",
133
+ "message"
134
+ ],
135
+ "properties": {
136
+ "commit": {
137
+ "oneOf": [
138
+ {
139
+ "type": "null"
140
+ },
141
+ {
142
+ "type": "string",
143
+ "pattern": "^(?:[0-9a-f]{40}|[0-9a-f]{64})$"
144
+ }
145
+ ]
146
+ },
147
+ "code": {
148
+ "enum": [
149
+ "signers-removed",
150
+ "rotation-unparseable",
151
+ "rotation-invalid",
152
+ "rotation-first-version",
153
+ "rotation-missing",
154
+ "rotation-version-skew",
155
+ "rotation-previous-mismatch",
156
+ "rotation-threshold-unsatisfiable",
157
+ "rotation-threshold-not-met"
158
+ ]
159
+ },
160
+ "message": {
161
+ "type": "string"
162
+ }
163
+ }
164
+ },
165
+ "failure": {
166
+ "type": "object",
167
+ "description": "No history could be read. Exits 1.",
168
+ "required": [
169
+ "$schema",
170
+ "contract",
171
+ "chant",
172
+ "error"
173
+ ],
174
+ "properties": {
175
+ "$schema": {
176
+ "const": "https://intentius.io/chant/schemas/workspace/signers/v1/signers.schema.json"
177
+ },
178
+ "contract": {
179
+ "const": 1
180
+ },
181
+ "chant": {
182
+ "type": "string"
183
+ },
184
+ "error": {
185
+ "type": "object",
186
+ "required": [
187
+ "code",
188
+ "message"
189
+ ],
190
+ "properties": {
191
+ "code": {
192
+ "enum": [
193
+ "not-a-git-repository",
194
+ "revision-unknown",
195
+ "signers-file-missing"
196
+ ]
197
+ },
198
+ "message": {
199
+ "type": "string"
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
206
+ }
@@ -316,6 +316,8 @@ describe("chant workspace status on built workspaces", () => {
316
316
  isolation: null,
317
317
  intent: null,
318
318
  services: [],
319
+ factory: null,
320
+ listing: null,
319
321
  },
320
322
  ]);
321
323
  });
@@ -451,6 +453,7 @@ describe("gate state in chant workspace status --json (#2674)", () => {
451
453
  expiresAt: "2026-12-31T00:00:00.000Z",
452
454
  approvals: [{ principal: "alice", channel: "cli", at: "2026-09-20T01:00:00.000Z" }],
453
455
  needed: 1,
456
+ signed: null,
454
457
  approve: `chant approve web deploy --env staging --plan ${D("1")}`,
455
458
  },
456
459
  {
@@ -463,6 +466,7 @@ describe("gate state in chant workspace status --json (#2674)", () => {
463
466
  expiresAt: "2026-12-31T00:00:00.000Z",
464
467
  approvals: [],
465
468
  needed: 1,
469
+ signed: null,
466
470
  approve: `chant approve web deploy --env prod --plan ${D("2")}`,
467
471
  },
468
472
  {
@@ -476,6 +480,7 @@ describe("gate state in chant workspace status --json (#2674)", () => {
476
480
  // The agent's approval doesn't count toward the quorum.
477
481
  approvals: [{ principal: "bob", channel: "cli", at: "2026-09-20T02:00:00.000Z" }],
478
482
  needed: 2,
483
+ signed: null,
479
484
  approve: `chant approve web review --env staging --plan ${D("4")}`,
480
485
  },
481
486
  ]);
@@ -19,9 +19,10 @@
19
19
  */
20
20
 
21
21
  import { execFileSync } from "node:child_process";
22
+ import { samePlanDigest } from "../lifecycle/plan-digest";
22
23
  import type { GateResolutionRecord, PendingGateRecord } from "../lifecycle/gate-ledger";
23
24
  import { isPendingGateExpired, latestPendingGate, latestResolutionForPlan, parseGateLedger } from "../lifecycle/gate-ledger";
24
- import { tallyGateApprovals } from "../op/gate";
25
+ import { tallyGateApprovals, type GateApprovalRule } from "../op/gate";
25
26
  import type { ReasonCode } from "./reason-codes";
26
27
 
27
28
  /** Why a member's gates can't be listed. Closed: a new code is a contract change. */
@@ -62,10 +63,20 @@ export interface StatusGate {
62
63
  approvals: StatusGateApproval[];
63
64
  /** How many human approvals the gate needs: its quorum's count, 1 without one. */
64
65
  needed: number;
66
+ /**
67
+ * The declaration's rule for the gate (#3163, ws-080): set when
68
+ * `identity.gates` names it, so only an approval sealed by a signer at
69
+ * base (from `class`, when it names one) counts, and `approve` carries
70
+ * `--sign`. Null when any approval counts.
71
+ */
72
+ signed: { class: string | null } | null;
65
73
  /** The command that approves it, run in the member's directory. */
66
74
  approve: string;
67
75
  }
68
76
 
77
+ /** The rule for a gate, by name, as `identity.gates` at base sets it (#3163). Null when it sets none. */
78
+ export type GateRuleLookup = (gate: string) => GateApprovalRule | null;
79
+
69
80
  export interface StatusGateLedger {
70
81
  /** `members` for `_members/<member>/_gates`, `flat` for `_gates`. */
71
82
  layout: "members" | "flat";
@@ -109,15 +120,17 @@ export const defaultGateLedgerReader: GateLedgerReader = async (dir, commit, cwd
109
120
  * plan this read showed and not whatever happens to be pending by the time
110
121
  * someone runs it.
111
122
  */
112
- export function approveCommand(component: string, gate: string, env: string | null, planDigest?: string | null): string {
113
- return `chant approve ${component} ${gate}${env !== null ? ` --env ${env}` : ""}${planDigest ? ` --plan ${planDigest}` : ""}`;
123
+ export function approveCommand(component: string, gate: string, env: string | null, planDigest?: string | null, signed = false): string {
124
+ return `chant approve ${component} ${gate}${env !== null ? ` --env ${env}` : ""}${planDigest ? ` --plan ${planDigest}` : ""}${signed ? " --sign" : ""}`;
114
125
  }
115
126
 
116
127
  const approvalOf = (r: GateResolutionRecord): StatusGateApproval => ({ principal: r.resolvedBy, channel: r.origin ?? null, at: r.timestamp });
117
128
 
118
129
  /** One gate in one environment, decided against its newest pending fact. */
119
- function decide(component: string, standing: PendingGateRecord, resolutions: GateResolutionRecord[], now: string): StatusGate {
130
+ function decide(component: string, standing: PendingGateRecord, all: GateResolutionRecord[], now: string, rule: GateApprovalRule | null): StatusGate {
120
131
  const gate = standing.gate;
132
+ // #3163: under identity.gates, an unsigned approval, or one from outside the class, doesn't count, as a run reads it.
133
+ const resolutions = rule === null ? all : all.filter((r) => r.gate !== gate || rule.refuses(r) === null);
121
134
  const env = standing.environment ?? null;
122
135
  const since = standing.timestamp;
123
136
  const planDigest = standing.planDigest;
@@ -138,7 +151,7 @@ function decide(component: string, standing: PendingGateRecord, resolutions: Gat
138
151
  } else {
139
152
  const at = (r: GateResolutionRecord) => new Date(r.timestamp).getTime();
140
153
  approvals = own
141
- .filter((r) => r.gate === gate && at(r) >= new Date(since).getTime() && (planDigest === undefined || r.planDigest === planDigest))
154
+ .filter((r) => r.gate === gate && at(r) >= new Date(since).getTime() && (planDigest === undefined || samePlanDigest(r.planDigest, planDigest)))
142
155
  .sort((a, b) => at(a) - at(b));
143
156
  approved = approvals.length > 0;
144
157
  mismatched = latestResolutionForPlan(own, gate, since, planDigest).mismatched;
@@ -155,7 +168,8 @@ function decide(component: string, standing: PendingGateRecord, resolutions: Gat
155
168
  expiresAt: standing.expiresAt,
156
169
  approvals: approvals.map(approvalOf),
157
170
  needed,
158
- approve: approveCommand(component, gate, env, planDigest),
171
+ signed: rule === null ? null : { class: rule.requirement.class },
172
+ approve: approveCommand(component, gate, env, planDigest, rule !== null),
159
173
  };
160
174
  }
161
175
 
@@ -166,7 +180,7 @@ function decide(component: string, standing: PendingGateRecord, resolutions: Gat
166
180
  * gate whose other facts have one is left out, as a run leaves it out: such a
167
181
  * line binds no environment, and `chant approve --expire` writes one.
168
182
  */
169
- export function gatesInLedger(component: string, content: string, envs: readonly string[], now: string): { gates: StatusGate[]; malformed: number } {
183
+ export function gatesInLedger(component: string, content: string, envs: readonly string[], now: string, rules: GateRuleLookup = () => null): { gates: StatusGate[]; malformed: number } {
170
184
  const { pending, resolutions, malformed } = parseGateLedger(content);
171
185
  const gates: StatusGate[] = [];
172
186
  for (const gate of [...new Set(pending.map((p) => p.gate))].sort()) {
@@ -180,7 +194,7 @@ export function gatesInLedger(component: string, content: string, envs: readonly
180
194
  byEnv.set(env, [...(byEnv.get(env) ?? []), p]);
181
195
  }
182
196
  for (const env of [...byEnv.keys()].sort((a, b) => envs.indexOf(a ?? "") - envs.indexOf(b ?? ""))) {
183
- gates.push(decide(component, latestPendingGate(byEnv.get(env)!, gate)!, resolutions, now));
197
+ gates.push(decide(component, latestPendingGate(byEnv.get(env)!, gate)!, resolutions, now, rules(gate)));
184
198
  }
185
199
  }
186
200
  return { gates, malformed };
@@ -195,6 +209,7 @@ export async function readMemberGates(
195
209
  cwd: string,
196
210
  now: string,
197
211
  read: GateLedgerReader = defaultGateLedgerReader,
212
+ rules: GateRuleLookup = () => null,
198
213
  ): Promise<{ gates: StatusGate[]; ledger: StatusGateLedger }> {
199
214
  const ledger: StatusGateLedger = { layout, path: dir, shared: false, malformed: 0, reason: null };
200
215
  if (commit === null) {
@@ -212,7 +227,7 @@ export async function readMemberGates(
212
227
  }
213
228
  const gates: StatusGate[] = [];
214
229
  for (const component of [...files.keys()].sort()) {
215
- const read = gatesInLedger(component, files.get(component)!, envs, now);
230
+ const read = gatesInLedger(component, files.get(component)!, envs, now, rules);
216
231
  gates.push(...read.gates);
217
232
  ledger.malformed += read.malformed;
218
233
  }
@@ -31,6 +31,25 @@
31
31
  }
32
32
  }
33
33
  },
34
+ "checkout": {
35
+ "description": "Added in contract 1 by #3160. The branch, head and base of the checkout status ran in. records --uncommitted --json lists the records that working tree holds modified or new against head.",
36
+ "type": "object",
37
+ "required": ["branch", "head", "base", "baseFrom"],
38
+ "properties": {
39
+ "branch": { "type": ["string", "null"], "description": "The checked-out branch's short name, such as chant/work/w-12, or null when HEAD is detached." },
40
+ "head": { "type": ["string", "null"], "pattern": "^[0-9a-f]{40,64}$", "description": "The full commit id HEAD names, or null before the first commit." },
41
+ "base": {
42
+ "type": ["string", "null"],
43
+ "pattern": "^[0-9a-f]{40,64}$",
44
+ "description": "The merge base of head and the target branch tip (origin/HEAD, else main, else master), the commit the branch forked from. Null without a head, a target, or common history."
45
+ },
46
+ "baseFrom": { "enum": ["origin/HEAD", "main", "master", null], "description": "Where the target branch was found; null when there is none." }
47
+ }
48
+ },
49
+ "plantable": {
50
+ "description": "Added in contract 1 by #3146. Whether a host such as a studio's planter can plant the workspace as one box: exactly one member's box block declares services. Not a check: a records-only or infra workspace is valid and simply not plantable.",
51
+ "$ref": "#/$defs/plantable"
52
+ },
34
53
  "workspace": {
35
54
  "type": "object",
36
55
  "required": ["name", "root", "file"],
@@ -470,6 +489,14 @@
470
489
  "type": "object",
471
490
  "required": ["capabilities", "isolation", "intent", "services"],
472
491
  "properties": {
492
+ "factory": {
493
+ "description": "Added in contract 1 by #3146. What the box builds and how (ws-077), with every default filled in, or null when the block declares no factory. At most one member's box has one.",
494
+ "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/factory" }]
495
+ },
496
+ "listing": {
497
+ "description": "Added in contract 1 by #3146. What the box shows of itself on a home site, or null when the block declares no listing.",
498
+ "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/listing" }]
499
+ },
473
500
  "services": {
474
501
  "description": "The services the box block declares (#2880), in declaration order, or empty when it declares none. A reader has them before any converge tick; a steward's ConvergeOp's lastTick carries each one's verdict. cmd is as declared: its ${VAR} references are left for the process that applies it to expand. Added by chant 0.95.0.",
475
502
  "type": "array",
@@ -510,6 +537,91 @@
510
537
  }
511
538
  }
512
539
  },
540
+ "plantable": {
541
+ "type": "object",
542
+ "required": ["plantable", "box", "reason"],
543
+ "properties": {
544
+ "plantable": { "type": "boolean" },
545
+ "box": { "type": ["string", "null"], "description": "The member whose box block declares services, or null when the workspace isn't plantable." },
546
+ "reason": {
547
+ "description": "Why the workspace isn't plantable, or null when it is.",
548
+ "oneOf": [
549
+ { "type": "null" },
550
+ {
551
+ "type": "object",
552
+ "required": ["code", "message"],
553
+ "properties": {
554
+ "code": { "enum": ["box-none", "box-several"] },
555
+ "message": { "type": "string" }
556
+ }
557
+ }
558
+ ]
559
+ }
560
+ }
561
+ },
562
+ "factory": {
563
+ "type": "object",
564
+ "required": ["builds", "check", "checks", "builders", "publish"],
565
+ "properties": {
566
+ "builds": { "type": "array", "minItems": 1, "items": { "type": "string" }, "description": "The members the factory builds, in declaration order. A work item a person asks for constrains member:<the first>." },
567
+ "check": {
568
+ "description": "The verdict command, run from the workspace root, and what it is; null when none is declared.",
569
+ "oneOf": [
570
+ { "type": "null" },
571
+ {
572
+ "type": "object",
573
+ "required": ["run", "kind"],
574
+ "properties": {
575
+ "run": { "type": "string" },
576
+ "kind": { "enum": ["test", "build", "lint", "plan", "conformance"] }
577
+ }
578
+ }
579
+ ]
580
+ },
581
+ "checks": { "type": ["string", "null"], "description": "Where a work item's builder writes its check, from the workspace root, or null for the orchestrator's choice." },
582
+ "builders": { "type": ["string", "null"], "description": "The member that declares the builder agents, or null." },
583
+ "publish": {
584
+ "description": "Where a finished build is published, or null when the factory doesn't publish past the box.",
585
+ "oneOf": [
586
+ { "type": "null" },
587
+ {
588
+ "type": "object",
589
+ "required": ["forge", "repo", "base", "branchPrefix", "head"],
590
+ "properties": {
591
+ "forge": { "const": "github" },
592
+ "repo": { "type": "string", "description": "owner/name: where the pull request is opened." },
593
+ "base": { "type": ["string", "null"], "description": "The branch the pull request targets, or null for the repository's default branch." },
594
+ "branchPrefix": { "type": "string", "description": "What the published branch's name starts with, before the work item's id. chant/work/ unless declared." },
595
+ "head": { "type": ["string", "null"], "description": "owner/name of the fork the branch is pushed to, or null to push to repo." }
596
+ }
597
+ }
598
+ ]
599
+ }
600
+ }
601
+ },
602
+ "listing": {
603
+ "type": "object",
604
+ "required": ["published", "title", "line", "cover"],
605
+ "properties": {
606
+ "published": { "type": "boolean", "description": "Whether the box is listed; true unless declared otherwise." },
607
+ "title": { "type": "string", "description": "Empty when not declared: a reader shows a name of its own." },
608
+ "line": { "type": "string", "description": "Empty when not declared." },
609
+ "cover": {
610
+ "description": "The cover image, or null when none is declared.",
611
+ "oneOf": [
612
+ { "type": "null" },
613
+ {
614
+ "type": "object",
615
+ "required": ["path", "sha256"],
616
+ "properties": {
617
+ "path": { "type": "string", "description": "From the workspace root." },
618
+ "sha256": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$", "description": "The sha256 of the file's bytes in the working tree, or null when it can't be read." }
619
+ }
620
+ }
621
+ ]
622
+ }
623
+ }
624
+ },
513
625
  "isolation": {
514
626
  "type": "object",
515
627
  "required": ["host", "slot", "portRange", "ports", "stateDir", "state", "cookies"],
@@ -571,7 +683,7 @@
571
683
  },
572
684
  "gate": {
573
685
  "type": "object",
574
- "required": ["component", "name", "env", "planDigest", "state", "recordedAt", "expiresAt", "approvals", "needed", "approve"],
686
+ "required": ["component", "name", "env", "planDigest", "state", "recordedAt", "expiresAt", "approvals", "needed", "signed", "approve"],
575
687
  "properties": {
576
688
  "component": { "type": "string", "description": "The ledger file's key: the component, or the op for a gate an Op run reached." },
577
689
  "name": { "type": "string", "description": "The gate's name." },
@@ -600,7 +712,20 @@
600
712
  }
601
713
  },
602
714
  "needed": { "type": "integer", "minimum": 1, "description": "The human approvals the gate needs: its quorum's count, 1 without one." },
603
- "approve": { "type": "string", "description": "The chant approve line for the gate, run in the member's directory: chant approve <component> <gate>, with --env <env> when env is not null and --plan <planDigest> when planDigest is not null (#2832), so the line approves the plan this read showed." }
715
+ "signed": {
716
+ "description": "Added in contract 1 by #3163. The declaration's rule for the gate, read at base (identity.gates, ws-080): only an approval sealed with chant approve --sign by a key the signers file at base lists for its approver counts, and when class is not null, only one whose approver the role grants at base put in that class. Approvals that don't meet it are left out of approvals and state. Null when any approval counts.",
717
+ "oneOf": [
718
+ { "type": "null" },
719
+ {
720
+ "type": "object",
721
+ "required": ["class"],
722
+ "properties": {
723
+ "class": { "type": ["string", "null"], "description": "The principal class the signer must be in, or null for any listed signer." }
724
+ }
725
+ }
726
+ ]
727
+ },
728
+ "approve": { "type": "string", "description": "The chant approve line for the gate, run in the member's directory: chant approve <component> <gate>, with --env <env> when env is not null and --plan <planDigest> when planDigest is not null (#2832), so the line approves the plan this read showed, and --sign when signed is not null (#3163). The caller adds --actor <principal>." }
604
729
  }
605
730
  },
606
731
  "environment": {
@@ -41,11 +41,15 @@ import { readPathSha } from "../lifecycle/git";
41
41
  import { latestPerComponent, readReleaseLedger, type ReleaseRecord } from "../lifecycle/release-ledger";
42
42
  import { readReleasePlan, type ReleasePlan } from "../lifecycle/plan-ledger";
43
43
  import { listWorkLeases, type WorkLeaseState } from "../lifecycle/work-lease";
44
+ import { readCheckoutHead, type CheckoutHead } from "./records-checkout";
44
45
  import { findWorkspaceRoot } from "../project-root";
45
46
  import { resolveBoxes, type ResolvedIsolation } from "./box-isolation";
46
47
  import { resolveBoxIntents, unresolvedIntent, type BoxIntent } from "./box-intent";
48
+ import { factoryView, listingView, plantability, treeBytes, type FactoryView, type ListingView, type Plantable } from "./box-factory";
47
49
  import { declaredRecordKinds, readDeclaration, readerVersion, WorkspaceReadError, type Declaration, type ErrorLocation, type Member } from "./declaration";
48
50
  import type { ReasonCode } from "./reason-codes";
51
+ import { gateAdmissionFrom } from "./identity";
52
+ import { scopeSource } from "./write-scope";
49
53
  import { GATE_REASON_CODES, readMemberGates, type GateLedgerReader, type StatusGate, type StatusGateLedger } from "./status-gates";
50
54
  import { STEWARD_REASON_CODES, readMemberStewards, type StatusSteward, type StewardReasonCode } from "./status-stewards";
51
55
  import { gitTop, workingTree } from "./tree";
@@ -188,6 +192,10 @@ export interface StatusBox {
188
192
  intent: BoxIntent | null;
189
193
  /** The services the block declares (#2880), in file order, so a reader has them before any converge tick. Empty when it declares none. */
190
194
  services: StatusBoxService[];
195
+ /** What the box builds and how, with defaults filled in (#3146, ws-077), or null when the block declares no factory. */
196
+ factory: FactoryView | null;
197
+ /** What the box shows of itself on a home site, with the cover's sha256 (#3146), or null when the block declares no listing. */
198
+ listing: ListingView | null;
191
199
  }
192
200
 
193
201
  /** A declared box service as `status --json` prints it (#2880): every field present, null or false when not declared. */
@@ -234,7 +242,11 @@ export type StatusDocument =
234
242
  env: string;
235
243
  compareTo: string | null;
236
244
  lifecycle: { ref: string; commit: string | null };
245
+ /** The branch, head and base of the checkout read (#3160). `records --uncommitted` lists the records it holds uncommitted. */
246
+ checkout: CheckoutHead;
237
247
  workspace: { name: string; root: string; file: string };
248
+ /** Whether a host can plant the workspace as one box (#3146): exactly one member's box block declares services. */
249
+ plantable: Plantable;
238
250
  members: StatusMember[];
239
251
  /** Every work lease in the workspace's ledgers, active and expired, by member then item (#2732). A released lease has no ref and is not listed. */
240
252
  leases: StatusLease[];
@@ -399,12 +411,16 @@ export async function workspaceStatus(query: StatusQuery): Promise<StatusDocumen
399
411
 
400
412
  const isolation = new Map(resolveBoxes(declaration).map((b) => [b.member.name, b.isolation]));
401
413
  const intents = new Map((await resolveBoxIntents(declaration, found.dir)).map((i) => [i.member, i.record?.intent ?? unresolvedIntent(i.id)]));
414
+ const coverBytes = treeBytes(workingTree(found.dir));
415
+ // #3163: the declaration's identity.gates at base, read once for every member's gates.
416
+ const ruleSource = scopeSource(found.dir);
417
+ const rules = (gate: string) => gateAdmissionFrom(ruleSource, gate);
402
418
  const members: StatusMember[] = [];
403
419
  for (const m of declaration.members) {
404
420
  const environments: StatusEnvironment[] = [];
405
421
  for (const env of envs) environments.push(await readEnvironment(m, env, found.dir, read));
406
422
  const own = await hasMemberLedger(m, found.dir);
407
- const gates = await readMemberGates(own ? `${MEMBERS_DIR}/${m.name}/${GATES_DIR}` : GATES_DIR, own ? "members" : "flat", commit, envs, found.dir, now, query.readGates);
423
+ const gates = await readMemberGates(own ? `${MEMBERS_DIR}/${m.name}/${GATES_DIR}` : GATES_DIR, own ? "members" : "flat", commit, envs, found.dir, now, query.readGates, rules);
408
424
  const stewards = await (query.readStewards ?? readMemberStewards)(resolve(found.dir, m.dir), query.env, now, m.kind, m.box);
409
425
  members.push({
410
426
  name: m.name,
@@ -431,6 +447,8 @@ export async function workspaceStatus(query: StatusQuery): Promise<StatusDocumen
431
447
  health: s.health,
432
448
  optional: s.optional,
433
449
  })),
450
+ factory: factoryView(m.box.factory),
451
+ listing: listingView(m.box.listing, coverBytes),
434
452
  },
435
453
  stewards: stewards.stewards,
436
454
  stewardReasons: stewards.reasons,
@@ -451,7 +469,9 @@ export async function workspaceStatus(query: StatusQuery): Promise<StatusDocumen
451
469
  env: query.env,
452
470
  compareTo: query.compareTo ?? null,
453
471
  lifecycle: { ref: LIFECYCLE_REF, commit },
472
+ checkout: readCheckoutHead(top),
454
473
  workspace: { name: declaration.name, root: rootDir === "" ? "." : rootDir, file: declaration.file },
474
+ plantable: plantability(declaration),
455
475
  members,
456
476
  leases,
457
477
  acceptance,