@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,175 @@
1
+ /**
2
+ * Principal classes a plugin supplies (#3080, ws-079): the data file, the
3
+ * registry, and how a principal's role grants at base put it in a class.
4
+ */
5
+
6
+ import { mkdirSync, writeFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { afterAll, describe, expect, test } from "vitest";
9
+ import { cleanScratch, scratchDir } from "./__fixtures__/contract-repo";
10
+ import {
11
+ CLASS_NAME,
12
+ classesOf,
13
+ coreClassRegistry,
14
+ loadClassRegistry,
15
+ parseClassData,
16
+ principalClass,
17
+ PRINCIPALS_SCHEMA_ID,
18
+ readPackageClasses,
19
+ treeFiles,
20
+ unknownScopeClasses,
21
+ } from "./principal-classes";
22
+ import { emptyPolicy } from "./trust/policy";
23
+ import type { WorkspaceTree } from "./tree";
24
+
25
+ afterAll(cleanScratch);
26
+
27
+ const data = (classes: unknown[]) => JSON.stringify({ schema: 1, classes });
28
+ const reviewer = { name: "reviewer", description: "people who review decisions", role: "reviewer" };
29
+ const operator = { name: "operator", description: "people who apply infrastructure", role: "ops" };
30
+
31
+ /** A plugin package directory on disk, publishing `classes` at ./workspace-principals. */
32
+ function plugin(root: string, dir: string, classes: unknown[], pkg: Record<string, unknown> = {}): void {
33
+ const abs = join(root, ...dir.split("/"));
34
+ mkdirSync(abs, { recursive: true });
35
+ writeFileSync(join(abs, "package.json"), JSON.stringify({ name: dir.replace(/\//g, "-"), version: "1.0.0", exports: { "./workspace-principals": "./principals.json" }, ...pkg }));
36
+ writeFileSync(join(abs, "principals.json"), data(classes));
37
+ }
38
+
39
+ describe("the principals file", () => {
40
+ test("has a versioned schema id and a name grammar shared with writeScope", () => {
41
+ expect(PRINCIPALS_SCHEMA_ID).toBe("https://intentius.io/chant/schemas/workspace/principals/v1/workspace-principals.schema.json");
42
+ expect(CLASS_NAME.test("reviewer")).toBe(true);
43
+ expect(CLASS_NAME.test("x-reviewer")).toBe(false);
44
+ expect(CLASS_NAME.test("Reviewer")).toBe(false);
45
+ });
46
+
47
+ test("a valid file yields its classes in file order, with the pin as source", () => {
48
+ expect(parseClassData(data([reviewer, operator]), "plugins/review")).toEqual({
49
+ classes: [
50
+ { ...reviewer, source: "plugins/review" },
51
+ { ...operator, source: "plugins/review" },
52
+ ],
53
+ problems: [],
54
+ });
55
+ });
56
+
57
+ test.each([
58
+ ["not JSON", "{", /not JSON/],
59
+ ["a missing role", data([{ name: "reviewer", description: "d" }]), /role/],
60
+ ["an unknown field", data([{ ...reviewer, members: ["app"] }]), /additional properties/],
61
+ ["an x- name", data([{ ...reviewer, name: "x-reviewer" }]), /pattern/],
62
+ ])("refuses %s", (_, text, message) => {
63
+ const read = parseClassData(text, "p");
64
+ expect(read.classes).toEqual([]);
65
+ expect(read.problems.join("\n")).toMatch(message);
66
+ });
67
+
68
+ test("leaves out a core name, a core role, a name twice and a role twice, keeping the rest", () => {
69
+ const read = parseClassData(
70
+ data([
71
+ { name: "human", description: "d", role: "people" },
72
+ { name: "bots", description: "d", role: "agent" },
73
+ reviewer,
74
+ { ...reviewer, role: "other" },
75
+ { name: "checker", description: "d", role: "reviewer" },
76
+ operator,
77
+ ]),
78
+ "p",
79
+ );
80
+ expect(read.classes.map((c) => c.name)).toEqual(["reviewer", "operator"]);
81
+ expect(read.problems).toEqual([
82
+ "p: class human is a core class and can't be supplied by a package",
83
+ "p: class bots names the role agent, which puts a principal in the core agent class",
84
+ "p: class reviewer is listed twice",
85
+ "p: class checker names the role reviewer, which another class in the file names; a role puts a principal in one class",
86
+ ]);
87
+ });
88
+ });
89
+
90
+ describe("reading a package's classes", () => {
91
+ test("a package exporting no ./workspace-principals supplies none, without a problem", () => {
92
+ const root = scratchDir();
93
+ plugin(root, "kinds-only", [reviewer], { exports: { "./workspace-kinds": "./kinds.json" } });
94
+ expect(loadClassRegistry([{ package: null, version: null, path: "kinds-only" }], root)).toMatchObject({ problems: [] });
95
+ });
96
+
97
+ test("the export must name a JSON file inside the package", () => {
98
+ const files = (pkg: object) => (p: string) => (p === "package.json" ? JSON.stringify(pkg) : undefined);
99
+ expect(readPackageClasses(files({ exports: { "./workspace-principals": "./index.js" } }), "p").problems[0]).toMatch(/must name a .json file/);
100
+ expect(readPackageClasses(files({ exports: { "./workspace-principals": "./../x.json" } }), "p").problems[0]).toMatch(/points outside the package/);
101
+ expect(readPackageClasses(files({ exports: { "./workspace-principals": "./gone.json" } }), "p").problems[0]).toMatch(/does not exist/);
102
+ });
103
+
104
+ test("a path pin is read through a tree when one is given, such as the base revision", () => {
105
+ const files: Record<string, string> = {
106
+ "plugins/review/package.json": JSON.stringify({ exports: { "./workspace-principals": "./principals.json" } }),
107
+ "plugins/review/principals.json": data([reviewer]),
108
+ };
109
+ const tree: WorkspaceTree = {
110
+ label: " at base",
111
+ stat: (p) => (p in files ? "file" : undefined),
112
+ list: () => undefined,
113
+ read: (p) => files[p],
114
+ };
115
+ expect(readPackageClasses(treeFiles(tree, "plugins/review"), "plugins/review").classes.map((c) => c.name)).toEqual(["reviewer"]);
116
+ // The working tree is not consulted: nothing exists on disk at this root.
117
+ const loaded = loadClassRegistry([{ package: null, version: null, path: "plugins/review" }], "/nonexistent", { tree });
118
+ expect(loaded.problems).toEqual([]);
119
+ expect(loaded.registry.names()).toEqual(["human", "agent", "runner", "service", "reviewer"]);
120
+ });
121
+
122
+ test("a class name or a role two pins supply is left out, with a problem on the second pin", () => {
123
+ const root = scratchDir();
124
+ plugin(root, "a", [reviewer, operator]);
125
+ plugin(root, "b", [{ ...reviewer, role: "approver" }]);
126
+ plugin(root, "c", [{ name: "applier", description: "d", role: "ops" }]);
127
+ const pins = ["a", "b", "c"].map((path) => ({ package: null, version: null, path }));
128
+ const { registry, problems } = loadClassRegistry(pins, root);
129
+ expect(registry.names()).toEqual(["human", "agent", "runner", "service"]);
130
+ expect(problems).toEqual([
131
+ { pin: 1, message: "class reviewer is supplied by both a and b; a class name has one source" },
132
+ { pin: 2, message: "class applier (c) names the role ops, which class operator (a) names; a role puts a principal in one class" },
133
+ ]);
134
+ });
135
+
136
+ test("a package pin that is not installed is a problem, and a pin naming neither is skipped", () => {
137
+ const root = scratchDir();
138
+ const { problems } = loadClassRegistry(
139
+ [
140
+ { package: "absent", version: "1.0.0", path: null },
141
+ { package: null, version: null, path: null },
142
+ ],
143
+ root,
144
+ );
145
+ expect(problems).toEqual([{ pin: 0, message: "pinned package absent is not installed; install it to read the kinds it supplies" }]);
146
+ });
147
+ });
148
+
149
+ describe("a principal's classes", () => {
150
+ const root = scratchDir();
151
+ plugin(root, "review", [reviewer, operator]);
152
+ const { registry } = loadClassRegistry([{ package: null, version: null, path: "review" }], root);
153
+ const policy = { ...emptyPolicy("x"), roles: { reviewer: ["Rev@example.com", "ci@example.com"], ops: ["rev@example.com"], runner: ["ci@example.com"] } };
154
+
155
+ test("come from role grants at base, core first, then the domain classes in order", () => {
156
+ expect(classesOf(registry, policy, "rev@example.com")).toEqual(["reviewer", "operator"]);
157
+ expect(classesOf(registry, policy, "ci@example.com")).toEqual(["runner", "reviewer"]);
158
+ expect(classesOf(registry, policy, "lex00")).toEqual([]);
159
+ expect(classesOf(registry, policy, null)).toEqual([]);
160
+ });
161
+
162
+ test("write scope judges a principal by the first, and human is the rest", () => {
163
+ expect(principalClass(policy, "rev@example.com", registry)).toBe("reviewer");
164
+ expect(principalClass(policy, "ci@example.com", registry)).toBe("runner");
165
+ expect(principalClass(policy, "lex00", registry)).toBe("human");
166
+ // Without the plugin's classes, a domain principal is a human (the behaviour before #3080).
167
+ expect(principalClass(policy, "rev@example.com")).toBe("human");
168
+ });
169
+
170
+ test("a writeScope key no class has is unknown", () => {
171
+ expect(unknownScopeClasses({ human: {}, reviewer: {}, auditor: {} }, registry)).toEqual(["auditor"]);
172
+ expect(unknownScopeClasses({ reviewer: {} }, coreClassRegistry())).toEqual(["reviewer"]);
173
+ expect(unknownScopeClasses(null, registry)).toEqual([]);
174
+ });
175
+ });
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Principal classes (#2524 D5; #3080, ws-079).
3
+ *
4
+ * A principal class names a set of principals so the declaration can scope
5
+ * what they write. Four are core: `agent`, `runner` and `service`, each the
6
+ * holders of the role of that name in the trust policy at base, and `human`,
7
+ * everyone else. A plugin adds domain classes as data, the way it adds member
8
+ * kinds: a JSON file at its `./workspace-principals` subpath, read through
9
+ * the package's `package.json` and never imported. Each class it supplies
10
+ * names the role whose grant puts a principal in it.
11
+ *
12
+ * A principal's classes are read only from role grants at base, through
13
+ * {@link classesOf}. Core classes are tried first, then the domain classes
14
+ * in pin order and file order; the first that holds is the class write scope
15
+ * judges the principal as, and `human` is the rest. A gate or a record that
16
+ * asks whether a principal is in a class (#3163) asks {@link classesOf},
17
+ * which lists every class the principal's grants put it in.
18
+ *
19
+ * A path-pinned plugin's classes are read from the base revision when the
20
+ * caller has it (write scope does), so a change can't remap a class by
21
+ * editing its own copy of the plugin. A package pin is read from the
22
+ * installed package, which must be at the version the base pins.
23
+ */
24
+
25
+ import { readFileSync } from "node:fs";
26
+ import { createRequire } from "node:module";
27
+ import { join, posix } from "node:path";
28
+ import { kindsExportTarget, pinnedPackageDir, type KindLoadProblem, type PinLike } from "./kinds";
29
+ import { normalisePrincipal } from "./records";
30
+ import schema from "./workspace-principals.schema.json";
31
+ import type { TrustPolicy } from "./trust/policy";
32
+ import { joinPath, type WorkspaceTree } from "./tree";
33
+
34
+ export const PRINCIPALS_SCHEMA_ID = schema.$id;
35
+
36
+ /** The subpath a package publishes its principal classes at. */
37
+ export const PRINCIPALS_SUBPATH = "./workspace-principals";
38
+
39
+ /** The core classes, in the order a principal's roles are tried; `human` holds no role and is the rest. */
40
+ export const CORE_PRINCIPAL_CLASSES = ["human", "agent", "runner", "service"] as const;
41
+ export type CorePrincipalClass = (typeof CORE_PRINCIPAL_CLASSES)[number];
42
+
43
+ /** A class name: a core class, or a domain class a pinned package supplies. */
44
+ export type PrincipalClassName = string;
45
+
46
+ /** The grammar of a class name, as `workspace-principals.schema.json` and the declaration's writeScope keys say it. */
47
+ export const CLASS_NAME = /^(?!x-)[a-z][a-z0-9-]{0,39}$/;
48
+
49
+ export interface PrincipalClass {
50
+ name: string;
51
+ /** One line saying who is in the class. */
52
+ description: string;
53
+ /** The role whose grant at base puts a principal in the class, or null for `human`, the rest. */
54
+ role: string | null;
55
+ /** `core`, or the pin (package name or path) that supplies the class. */
56
+ source: string;
57
+ }
58
+
59
+ export const CORE_CLASSES: readonly PrincipalClass[] = [
60
+ { name: "human", description: "a principal holding none of the roles of another class", role: null, source: "core" },
61
+ { name: "agent", description: "a principal holding the agent role, or a write naming an agent session", role: "agent", source: "core" },
62
+ { name: "runner", description: "a principal holding the runner role, such as a CI job's signing identity", role: "runner", source: "core" },
63
+ { name: "service", description: "a principal holding the service role", role: "service", source: "core" },
64
+ ];
65
+
66
+ const CORE_ROLES = new Set(CORE_CLASSES.map((c) => c.role).filter((r): r is string => r !== null));
67
+
68
+ export interface ClassRegistry {
69
+ get(name: string): PrincipalClass | undefined;
70
+ /** Every class name, core first, for "unknown class" messages. */
71
+ names(): string[];
72
+ /** Every class, core first, then the domain classes in pin order and file order. */
73
+ all(): readonly PrincipalClass[];
74
+ }
75
+
76
+ export function createClassRegistry(extra: readonly PrincipalClass[] = []): ClassRegistry {
77
+ const all = [...CORE_CLASSES, ...extra];
78
+ const byName = new Map(all.map((c) => [c.name, c]));
79
+ return {
80
+ get: (name) => byName.get(name),
81
+ names: () => all.map((c) => c.name),
82
+ all: () => all,
83
+ };
84
+ }
85
+
86
+ /** The four core classes and nothing else: what a workspace whose pins supply no class has. */
87
+ export function coreClassRegistry(): ClassRegistry {
88
+ return createClassRegistry();
89
+ }
90
+
91
+ /**
92
+ * The role grants a class is read from. Every read of roles for a class goes
93
+ * through here, so where the grants live (`.chant/trust.json` today,
94
+ * possibly the declaration, #2547) is decided in one place: the policy.
95
+ */
96
+ export function roleGrants(policy: TrustPolicy): Record<string, string[]> {
97
+ return policy.roles;
98
+ }
99
+
100
+ /**
101
+ * Every class `principal`'s role grants at base put it in, in registry order
102
+ * (core first). Empty for a principal in no class but `human`, and for null.
103
+ * Names compare as {@link normalisePrincipal} folds them.
104
+ */
105
+ export function classesOf(classes: ClassRegistry, policy: TrustPolicy, principal: string | null): string[] {
106
+ if (principal === null) return [];
107
+ const name = normalisePrincipal(principal);
108
+ const grants = roleGrants(policy);
109
+ return classes
110
+ .all()
111
+ .filter((c) => c.role !== null && (grants[c.role] ?? []).some((p) => normalisePrincipal(p) === name))
112
+ .map((c) => c.name);
113
+ }
114
+
115
+ /** The class write scope judges `principal` as: the first class its grants put it in, or `human`. */
116
+ export function principalClass(policy: TrustPolicy, principal: string | null, classes: ClassRegistry = coreClassRegistry()): string {
117
+ return classesOf(classes, policy, principal)[0] ?? "human";
118
+ }
119
+
120
+ // ── Reading a plugin's classes ───────────────────────────────────────────────
121
+
122
+ interface AjvError {
123
+ instancePath: string;
124
+ message?: string;
125
+ }
126
+ type Validate = ((data: unknown) => boolean) & { errors?: AjvError[] | null };
127
+
128
+ let compiled: Validate | undefined;
129
+ function validator(): Validate {
130
+ if (compiled) return compiled;
131
+ const require = createRequire(import.meta.url);
132
+ // ajv is CommonJS; its class is the default export, or that export's own default.
133
+ const mod = require("ajv/dist/2020") as { default?: unknown };
134
+ const Ajv = (mod.default ?? mod) as new (opts: object) => { compile(s: object): Validate };
135
+ compiled = new Ajv({ allErrors: true, strict: true }).compile(schema);
136
+ return compiled;
137
+ }
138
+
139
+ export interface ClassData {
140
+ classes: PrincipalClass[];
141
+ /** Why some of the data can't be used, one line each. Empty when all of it can. */
142
+ problems: string[];
143
+ }
144
+
145
+ /**
146
+ * Check the text of a principals file against
147
+ * `workspace-principals.schema.json` and the rules the schema can't say: no
148
+ * core name or core role, and no name or role twice. `source` names the pin
149
+ * in the classes and in the messages.
150
+ */
151
+ export function parseClassData(text: string, source: string): ClassData {
152
+ let raw: unknown;
153
+ try {
154
+ raw = JSON.parse(text);
155
+ } catch (err) {
156
+ return { classes: [], problems: [`${source}: the principals file is not JSON (${(err as Error).message})`] };
157
+ }
158
+ const validate = validator();
159
+ if (!validate(raw)) {
160
+ const problems = (validate.errors ?? []).map((e) => `${source}: ${e.instancePath || "the principals file"} ${e.message ?? "is invalid"}`);
161
+ return { classes: [], problems: [...new Set(problems)] };
162
+ }
163
+ const problems: string[] = [];
164
+ const classes: PrincipalClass[] = [];
165
+ const names = new Set<string>();
166
+ const roles = new Set<string>();
167
+ for (const c of (raw as { classes: { name: string; description: string; role: string }[] }).classes) {
168
+ if ((CORE_PRINCIPAL_CLASSES as readonly string[]).includes(c.name)) {
169
+ problems.push(`${source}: class ${c.name} is a core class and can't be supplied by a package`);
170
+ continue;
171
+ }
172
+ if (CORE_ROLES.has(c.role)) {
173
+ problems.push(`${source}: class ${c.name} names the role ${c.role}, which puts a principal in the core ${c.role} class`);
174
+ continue;
175
+ }
176
+ if (names.has(c.name)) {
177
+ problems.push(`${source}: class ${c.name} is listed twice`);
178
+ continue;
179
+ }
180
+ if (roles.has(c.role)) {
181
+ problems.push(`${source}: class ${c.name} names the role ${c.role}, which another class in the file names; a role puts a principal in one class`);
182
+ continue;
183
+ }
184
+ names.add(c.name);
185
+ roles.add(c.role);
186
+ classes.push({ name: c.name, description: c.description, role: c.role, source });
187
+ }
188
+ return { classes, problems };
189
+ }
190
+
191
+ /** A package's files, by a `/`-separated path inside it, or undefined when one is not there. */
192
+ export type PackageFiles = (path: string) => string | undefined;
193
+
194
+ /** A package directory on disk. */
195
+ export function diskFiles(dir: string): PackageFiles {
196
+ return (path) => {
197
+ try {
198
+ return readFileSync(join(dir, ...path.split("/")), "utf-8");
199
+ } catch {
200
+ return undefined;
201
+ }
202
+ };
203
+ }
204
+
205
+ /** A package directory at `dir` in `tree`, such as the workspace at the base revision. */
206
+ export function treeFiles(tree: WorkspaceTree, dir: string): PackageFiles {
207
+ return (path) => {
208
+ const full = joinPath(dir, path);
209
+ if (tree.stat(full) !== "file") return undefined;
210
+ try {
211
+ return tree.read(full);
212
+ } catch {
213
+ return undefined;
214
+ }
215
+ };
216
+ }
217
+
218
+ /** Read the classes a package publishes at `./workspace-principals`. Reads files only; imports nothing. A package that publishes none supplies none. */
219
+ export function readPackageClasses(files: PackageFiles, source: string): ClassData {
220
+ const manifest = files("package.json");
221
+ if (manifest === undefined) return { classes: [], problems: [`${source}: no readable package.json`] };
222
+ let pkg: Record<string, unknown>;
223
+ try {
224
+ pkg = JSON.parse(manifest) as Record<string, unknown>;
225
+ } catch {
226
+ return { classes: [], problems: [`${source}: package.json is not JSON`] };
227
+ }
228
+ const target = kindsExportTarget(pkg, PRINCIPALS_SUBPATH);
229
+ if (target === undefined) return { classes: [], problems: [] };
230
+ if (typeof target !== "string") return { classes: [], problems: [`${source}: ${target.problem}`] };
231
+ const inside = posix.normalize(target.slice(2));
232
+ if (inside.startsWith("../") || inside === "..") return { classes: [], problems: [`${source}: exports["${PRINCIPALS_SUBPATH}"] points outside the package`] };
233
+ const text = files(inside);
234
+ if (text === undefined) return { classes: [], problems: [`${source}: exports["${PRINCIPALS_SUBPATH}"] names ${target}, which does not exist`] };
235
+ return parseClassData(text, source);
236
+ }
237
+
238
+ export interface LoadedClasses {
239
+ registry: ClassRegistry;
240
+ problems: KindLoadProblem[];
241
+ }
242
+
243
+ /**
244
+ * The classes a workspace knows: the core four plus every class its pins
245
+ * supply. A package pin is read from the installed package, looked up from
246
+ * `workspaceRoot`, and must be at the pinned version. A path pin is read
247
+ * through `tree` when given (the base revision, for write scope), else from
248
+ * `workspaceRoot` on disk, checked against its integrity digest. A class
249
+ * name, or a role, two pins both supply is a problem, and every class
250
+ * involved is left out, so a writeScope entry for it reads as unknown and
251
+ * fails closed. Never throws.
252
+ */
253
+ export function loadClassRegistry(pins: readonly PinLike[], workspaceRoot: string, opts: { tree?: WorkspaceTree } = {}): LoadedClasses {
254
+ const problems: KindLoadProblem[] = [];
255
+ const extra: PrincipalClass[] = [];
256
+ const byName = new Map<string, string>();
257
+ const byRole = new Map<string, string>();
258
+ const clashing = new Set<string>();
259
+ pins.forEach((pin, i) => {
260
+ let files: PackageFiles;
261
+ let source: string;
262
+ if (pin.path && opts.tree) {
263
+ files = treeFiles(opts.tree, pin.path);
264
+ source = pin.path;
265
+ } else {
266
+ const found = pinnedPackageDir(pin, workspaceRoot);
267
+ if (found === null) return;
268
+ if ("problem" in found) {
269
+ problems.push({ pin: i, message: found.problem });
270
+ return;
271
+ }
272
+ files = diskFiles(found.dir);
273
+ source = found.source;
274
+ }
275
+ const read = readPackageClasses(files, source);
276
+ for (const p of read.problems) problems.push({ pin: i, message: p });
277
+ for (const c of read.classes) {
278
+ const named = byName.get(c.name);
279
+ const roled = byRole.get(c.role!);
280
+ if (named !== undefined || roled !== undefined) {
281
+ clashing.add(c.name);
282
+ if (named !== undefined) {
283
+ problems.push({ pin: i, message: `class ${c.name} is supplied by both ${named} and ${source}; a class name has one source` });
284
+ } else {
285
+ const other = extra.find((e) => e.role === c.role)!;
286
+ clashing.add(other.name);
287
+ problems.push({ pin: i, message: `class ${c.name} (${source}) names the role ${c.role}, which class ${other.name} (${roled}) names; a role puts a principal in one class` });
288
+ }
289
+ continue;
290
+ }
291
+ byName.set(c.name, source);
292
+ byRole.set(c.role!, source);
293
+ extra.push(c);
294
+ }
295
+ });
296
+ // A name or role two pins both supply is left out altogether: neither reading is safe.
297
+ return { registry: createClassRegistry(extra.filter((c) => !clashing.has(c.name))), problems };
298
+ }
299
+
300
+ /**
301
+ * The writeScope keys no class in `classes` has, in file order. A writer
302
+ * judged `human` may be in such a class, since nothing says which role puts
303
+ * a principal in it, so write scope refuses that writer (fail closed).
304
+ */
305
+ export function unknownScopeClasses(writeScope: Record<string, unknown> | null, classes: ClassRegistry): string[] {
306
+ return Object.keys(writeScope ?? {}).filter((name) => classes.get(name) === undefined);
307
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * #3174, ws-096: factory fields are opt-in, and the reference workspace ships
3
+ * three profiles (ideation, app, infra) that `chant workspace init --profile`
4
+ * copies. A records-only workspace, an infra workspace with no factory and an
5
+ * infra workspace whose factory has no app member and no box services all
6
+ * pass `chant workspace check`, and so does a copy of each profile.
7
+ */
8
+
9
+ import { execFileSync, spawnSync } from "node:child_process";
10
+ import { mkdtempSync, readdirSync, readFileSync, realpathSync, rmSync, statSync } from "node:fs";
11
+ import { tmpdir } from "node:os";
12
+ import { join, relative } from "node:path";
13
+ import { afterAll, describe, expect, test } from "vitest";
14
+ import { REPO, repo } from "./__fixtures__/contract-repo";
15
+ import { plantability } from "./box-factory";
16
+ import { runDeclarationChecks } from "./checks";
17
+ import { readDeclaration } from "./declaration";
18
+ import { PROFILES, PROFILES_DIR, profileSource } from "./init";
19
+ import { initFromCommand } from "./lineage-init";
20
+ import { workingTree } from "./tree";
21
+
22
+ const scratch: string[] = [];
23
+ afterAll(() => {
24
+ for (const d of scratch) rmSync(d, { recursive: true, force: true });
25
+ });
26
+
27
+ const REFERENCE = join(REPO, "reference-workspace");
28
+ const CHANT = join(REPO, "packages", "core", "bin", "chant");
29
+
30
+ /** Every file under `dir`, relative to it, sorted. */
31
+ function files(dir: string): string[] {
32
+ const out: string[] = [];
33
+ const walk = (at: string) => {
34
+ for (const name of readdirSync(at)) {
35
+ const p = join(at, name);
36
+ if (statSync(p).isDirectory()) walk(p);
37
+ else out.push(relative(dir, p));
38
+ }
39
+ };
40
+ walk(dir);
41
+ return out.sort();
42
+ }
43
+
44
+ /** The errors `chant workspace check` reports, as `<id>:<entity>: <message>`. */
45
+ async function errors(root: string): Promise<string[]> {
46
+ const report = await runDeclarationChecks(root);
47
+ return report.diagnostics.filter((d) => d.severity === "error").map((d) => `${d.ruleId}:${d.entity ?? ""}: ${d.message}`);
48
+ }
49
+
50
+ /** A copy of a profile, made the way `chant workspace init --profile` makes it, from this checkout. */
51
+ async function copyOf(profile: string): Promise<string> {
52
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), `chant-3174-${profile}-`)));
53
+ scratch.push(dir);
54
+ const made = await initFromCommand({ from: `${REPO}#${PROFILES_DIR}/${profile}`, path: dir, params: profile === "infra" ? {} : { name: "Fern" } });
55
+ expect(made.success, made.error).toBe(true);
56
+ execFileSync("git", ["init", "-q"], { cwd: dir });
57
+ return dir;
58
+ }
59
+
60
+ describe("factory fields are opt-in (#3174)", () => {
61
+ test("a records-only workspace passes check, with no member, box or factory", async () => {
62
+ const root = repo({
63
+ "chant.workspace.json": JSON.stringify({ name: "notes", schema: 1, members: [], records: [{ kind: "decisions/decision.kind.mjs" }] }, null, 2),
64
+ "decisions/decision.kind.mjs": readFileSync(join(REFERENCE, "decisions", "decision.kind.mjs"), "utf-8"),
65
+ "decisions/decision.schema.json": readFileSync(join(REFERENCE, "decisions", "decision.schema.json"), "utf-8"),
66
+ });
67
+ expect(await errors(root)).toEqual([]);
68
+ });
69
+
70
+ test("an infra workspace with no factory passes check", async () => {
71
+ const root = repo({
72
+ "chant.workspace.json": JSON.stringify({ name: "estate", schema: 1, members: [{ name: "network", dir: "network", kind: "chant" }] }, null, 2),
73
+ "network/chant.config.json": '{ "lexicons": ["terraform"] }\n',
74
+ });
75
+ expect(await errors(root)).toEqual([]);
76
+ });
77
+
78
+ test("an infra workspace whose factory builds an estate member, with no app member and no box services, passes check and isn't plantable", async () => {
79
+ const declaration = {
80
+ name: "estate",
81
+ schema: 1,
82
+ members: [{ name: "network", dir: "network", kind: "chant", box: { factory: { builds: ["network"], check: { run: "chant lint", kind: "lint" } } } }],
83
+ };
84
+ const root = repo({ "chant.workspace.json": JSON.stringify(declaration, null, 2), "network/chant.config.json": '{ "lexicons": ["terraform"] }\n' });
85
+ expect(await errors(root)).toEqual([]);
86
+ expect(plantability(readDeclaration(workingTree(root), "")).reason?.code).toBe("box-none");
87
+ });
88
+ });
89
+
90
+ describe("the reference workspace's profiles (#3174)", () => {
91
+ test("are ideation, app and infra, each a template directory with a declaration", () => {
92
+ expect(readdirSync(join(REPO, PROFILES_DIR)).sort()).toEqual([...PROFILES].sort());
93
+ });
94
+
95
+ test("carry the reference workspace's own record kinds and app kind, byte for byte", () => {
96
+ for (const profile of PROFILES) {
97
+ const dir = join(REPO, PROFILES_DIR, profile);
98
+ for (const f of files(dir).filter((p) => /^(decisions|work|answers|kinds)\//.test(p))) {
99
+ expect(readFileSync(join(dir, f), "utf-8"), `${profile}/${f}`).toBe(readFileSync(join(REFERENCE, f), "utf-8"));
100
+ }
101
+ }
102
+ });
103
+
104
+ test("ideation: records and a stub app of the app kind, no box and no factory, and check passes", async () => {
105
+ const root = await copyOf("ideation");
106
+ expect(await errors(root)).toEqual([]);
107
+ const d = readDeclaration(workingTree(root), "");
108
+ expect(d.members.map((m) => `${m.name}:${m.kind}`)).toEqual(["app:app"]);
109
+ expect(d.members.every((m) => m.box === null)).toBe(true);
110
+ expect(d.records.map((r) => r.kind)).toEqual(["decisions/decision.kind.mjs", "work/work.kind.mjs", "answers/answer.kind.mjs"]);
111
+ expect(readFileSync(join(root, "app", "server.mjs"), "utf-8")).toContain('NAME = "Fern"');
112
+ });
113
+
114
+ test("app: the app member runs as the box's service and the factory builds it, and check passes", async () => {
115
+ const root = await copyOf("app");
116
+ expect(await errors(root)).toEqual([]);
117
+ const d = readDeclaration(workingTree(root), "");
118
+ expect(plantability(d)).toMatchObject({ plantable: true, box: "app" });
119
+ expect(d.members[0].box?.factory?.builds).toEqual(["app"]);
120
+ });
121
+
122
+ test("infra: an estate member and a factory, no app member and no box services, and check passes", async () => {
123
+ const root = await copyOf("infra");
124
+ expect(await errors(root)).toEqual([]);
125
+ const d = readDeclaration(workingTree(root), "");
126
+ expect(d.members.map((m) => `${m.name}:${m.kind}`)).toEqual(["network:chant"]);
127
+ expect(d.members[0].box?.factory?.check).toEqual({ run: "cd network && npx chant lint && npx chant build", kind: "lint" });
128
+ expect(d.members[0].box?.services).toEqual([]);
129
+ expect(d.pins).toEqual([]);
130
+ });
131
+ });
132
+
133
+ describe("chant workspace init --profile (#3174)", () => {
134
+ test("reads the profile from the chant repository at this chant's tag, or from --from", () => {
135
+ expect(profileSource("app", undefined, "0.103.0")).toBe("https://github.com/INTENTIUS/chant@chant-v0.103.0#reference-workspace/profiles/app");
136
+ expect(profileSource("infra", "/src/chant", "0.103.0")).toBe("/src/chant#reference-workspace/profiles/infra");
137
+ });
138
+
139
+ test("copies the profile with a lineage lock and names the workspace", () => {
140
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "chant-3174-cli-")));
141
+ scratch.push(dir);
142
+ const run = spawnSync(CHANT, ["workspace", "init", dir, "--profile", "ideation", "--from", REPO, "--name", "fern", "--param", "name=Fern", "--yes"], { encoding: "utf-8" });
143
+ expect(run.status, run.stderr).toBe(0);
144
+ expect(JSON.parse(readFileSync(join(dir, "chant.workspace.json"), "utf-8")).name).toBe("fern");
145
+ expect(readdirSync(join(dir, ".chant"))).toContain("workspace.lock.json");
146
+ });
147
+
148
+ test("names the profiles when given another, and writes nothing without --yes", () => {
149
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "chant-3174-cli-")));
150
+ scratch.push(dir);
151
+ const bad = spawnSync(CHANT, ["workspace", "init", dir, "--profile", "web"], { encoding: "utf-8" });
152
+ expect(bad.status).toBe(1);
153
+ expect(bad.stderr).toMatch(/the profiles are ideation, app, infra/);
154
+ const dry = spawnSync(CHANT, ["workspace", "init", dir, "--profile", "infra", "--from", REPO], { encoding: "utf-8", input: "" });
155
+ expect(dry.status).toBe(0);
156
+ expect(dry.stdout).toMatch(/Nothing written/);
157
+ expect(readdirSync(dir)).toEqual([]);
158
+ });
159
+ });
@@ -215,7 +215,7 @@ describe("every schema against the reference workspace (#2543)", () => {
215
215
  expect(doc.components[0].runtimes).toEqual([{ name: "local", lexicon: null, default: true, command: "chant run --components app" }]);
216
216
  expect(doc.members.find((m) => m.name === "delivery")!.runtimeReasons).toEqual([]);
217
217
  // #2695: the reference config declares no environments, so the app deploys to local only.
218
- expect(doc.components[0].environments).toEqual([{ name: "local", default: true, source: "builtin", command: "chant run --components app" }]);
218
+ expect(doc.components[0].environments).toEqual([{ name: "local", default: true, source: "builtin", site: null, command: "chant run --components app" }]);
219
219
  expect(doc.members.find((m) => m.name === "delivery")!.environmentReasons.map((r) => r.code)).toEqual(["environments-none-declared"]);
220
220
  expect(doc.reasons).toEqual([]);
221
221
  }
@@ -244,7 +244,7 @@ describe("every schema against the reference workspace (#2543)", () => {
244
244
  const doc = await workspacePoints({ cwd: FIXTURE, at });
245
245
  expectValid(doc);
246
246
  if ("error" in doc) throw new Error(doc.error.message);
247
- expect(doc.points.map((p) => p.name)).toEqual(["slice-tier", "ship-skip", "finding-triage", "needs-a-decision"]);
247
+ expect(doc.points.map((p) => p.name)).toEqual(["slice-tier", "understand", "ship-skip", "finding-triage", "needs-a-decision", "intent-origin", "intent-judgment", "intent-disposition", "agent-question"]);
248
248
  const sliceTier = doc.points.find((p) => p.name === "slice-tier")!;
249
249
  expect(sliceTier.criteria).toEqual({
250
250
  small: "A haiku-class builder. The work item fits the small limits.",