@intentius/chant 0.124.12 → 0.124.14

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 (928) hide show
  1. package/bin/chant +11 -0
  2. package/dist/agents/checks.js +326 -0
  3. package/dist/agents/discover.js +885 -0
  4. package/dist/agents/importer.js +17 -0
  5. package/dist/agents/index.js +12 -0
  6. package/dist/agents/types.js +19 -0
  7. package/dist/apply.js +151 -0
  8. package/dist/attrref.js +70 -0
  9. package/dist/audit/catalog.js +350 -0
  10. package/dist/audit/core.js +252 -0
  11. package/dist/audit/discover.js +633 -0
  12. package/dist/audit/fetch.js +666 -0
  13. package/dist/audit/lineage.js +91 -0
  14. package/dist/audit/nginx.js +366 -0
  15. package/dist/audit/prior-art.js +132 -0
  16. package/dist/audit/proof.js +321 -0
  17. package/dist/audit/report-html.js +194 -0
  18. package/dist/audit/report-model.js +198 -0
  19. package/dist/audit/report.js +102 -0
  20. package/dist/audit/rules-doc.js +144 -0
  21. package/dist/audit/secrets.js +405 -0
  22. package/dist/audit/terraform-state.js +140 -0
  23. package/dist/audit/wrangler.js +262 -0
  24. package/dist/behaviour-delta.js +401 -0
  25. package/dist/behaviour-engine.js +357 -0
  26. package/dist/behaviour-graph.js +83 -0
  27. package/dist/behaviour-http.js +188 -0
  28. package/dist/behaviour-kinds.js +172 -0
  29. package/dist/behaviour-overlay.js +50 -0
  30. package/dist/behaviour-predict.js +188 -0
  31. package/dist/behaviour-request.js +194 -0
  32. package/dist/behaviour.js +1325 -0
  33. package/dist/build-params.js +108 -0
  34. package/dist/build.js +668 -0
  35. package/dist/builder.js +44 -0
  36. package/dist/cdk/advise.js +30 -0
  37. package/dist/cdk/assembly.js +122 -0
  38. package/dist/cdk/graph.js +444 -0
  39. package/dist/cdk/tier-map.js +64 -0
  40. package/dist/cdk/types.js +24 -0
  41. package/dist/change-set.js +312 -0
  42. package/dist/child-project.js +21 -0
  43. package/dist/claimed-fields.js +135 -0
  44. package/dist/cli/build-options.js +70 -0
  45. package/dist/cli/build-params-cli.js +139 -0
  46. package/dist/cli/command-group.js +123 -0
  47. package/dist/cli/commands/audit-agents.js +326 -0
  48. package/dist/cli/commands/audit.js +571 -0
  49. package/dist/cli/commands/build.js +920 -0
  50. package/dist/cli/commands/carve-apply.js +153 -0
  51. package/dist/cli/commands/carve-bridge.js +201 -0
  52. package/dist/cli/commands/carve-emit.js +332 -0
  53. package/dist/cli/commands/carve-status.js +119 -0
  54. package/dist/cli/commands/carve.js +204 -0
  55. package/dist/cli/commands/check-lexicon-docs.js +79 -0
  56. package/dist/cli/commands/check-lexicon-examples.js +177 -0
  57. package/dist/cli/commands/check-lexicon-intrinsics.js +291 -0
  58. package/dist/cli/commands/check-lexicon-mcp.js +82 -0
  59. package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
  60. package/dist/cli/commands/check-lexicon-plugin.js +104 -0
  61. package/dist/cli/commands/check-lexicon.js +766 -0
  62. package/dist/cli/commands/describe.js +85 -0
  63. package/dist/cli/commands/diff.js +175 -0
  64. package/dist/cli/commands/doctor.js +350 -0
  65. package/dist/cli/commands/import-agents.js +155 -0
  66. package/dist/cli/commands/import.js +670 -0
  67. package/dist/cli/commands/init-lexicon/templates/codegen.js +194 -0
  68. package/dist/cli/commands/init-lexicon/templates/docs.js +100 -0
  69. package/dist/cli/commands/init-lexicon/templates/examples.js +29 -0
  70. package/dist/cli/commands/init-lexicon/templates/lint.js +34 -0
  71. package/dist/cli/commands/init-lexicon/templates/lsp.js +37 -0
  72. package/dist/cli/commands/init-lexicon/templates/plugin.js +108 -0
  73. package/dist/cli/commands/init-lexicon/templates/project.js +240 -0
  74. package/dist/cli/commands/init-lexicon/templates/spec.js +56 -0
  75. package/dist/cli/commands/init-lexicon/templates/tests.js +66 -0
  76. package/dist/cli/commands/init-lexicon.js +172 -0
  77. package/dist/cli/commands/init.js +381 -0
  78. package/dist/cli/commands/lexicon-rolling-upgrade.js +145 -0
  79. package/dist/cli/commands/lexicon-surface-diff.js +145 -0
  80. package/dist/cli/commands/licenses.js +125 -0
  81. package/dist/cli/commands/lint.d.ts.map +1 -1
  82. package/dist/cli/commands/lint.js +948 -0
  83. package/dist/cli/commands/list.js +63 -0
  84. package/dist/cli/commands/migrate.d.ts.map +1 -1
  85. package/dist/cli/commands/migrate.js +423 -0
  86. package/dist/cli/commands/onboard.js +403 -0
  87. package/dist/cli/commands/pinned-upgrade.js +191 -0
  88. package/dist/cli/commands/update.js +194 -0
  89. package/dist/cli/commands/vendor.js +217 -0
  90. package/dist/cli/conflict-check.js +104 -0
  91. package/dist/cli/debug.js +8 -0
  92. package/dist/cli/format.js +104 -0
  93. package/dist/cli/handlers/build.js +267 -0
  94. package/dist/cli/handlers/carve-apply.js +30 -0
  95. package/dist/cli/handlers/carve-bridge.js +28 -0
  96. package/dist/cli/handlers/carve-emit.js +50 -0
  97. package/dist/cli/handlers/carve-status.js +26 -0
  98. package/dist/cli/handlers/carve.js +40 -0
  99. package/dist/cli/handlers/change-set.js +46 -0
  100. package/dist/cli/handlers/components.js +730 -0
  101. package/dist/cli/handlers/dev.js +113 -0
  102. package/dist/cli/handlers/emulator.js +233 -0
  103. package/dist/cli/handlers/explain.js +54 -0
  104. package/dist/cli/handlers/fan-out.js +422 -0
  105. package/dist/cli/handlers/gate-resume.js +275 -0
  106. package/dist/cli/handlers/generate.js +84 -0
  107. package/dist/cli/handlers/graph.js +969 -0
  108. package/dist/cli/handlers/init.js +102 -0
  109. package/dist/cli/handlers/lifecycle.js +1727 -0
  110. package/dist/cli/handlers/lint.js +62 -0
  111. package/dist/cli/handlers/migrate.js +48 -0
  112. package/dist/cli/handlers/misc.js +391 -0
  113. package/dist/cli/handlers/operator.js +1162 -0
  114. package/dist/cli/handlers/override-approve.js +102 -0
  115. package/dist/cli/handlers/pr.js +503 -0
  116. package/dist/cli/handlers/promote.js +342 -0
  117. package/dist/cli/handlers/run-generate.js +206 -0
  118. package/dist/cli/handlers/run-wave.js +66 -0
  119. package/dist/cli/handlers/run.js +1191 -0
  120. package/dist/cli/handlers/scenario.js +325 -0
  121. package/dist/cli/handlers/search.js +924 -0
  122. package/dist/cli/handlers/serve.js +32 -0
  123. package/dist/cli/handlers/vendor.js +154 -0
  124. package/dist/cli/index.js +3 -0
  125. package/dist/cli/is-entry-point.js +23 -0
  126. package/dist/cli/lsp/capabilities.js +28 -0
  127. package/dist/cli/lsp/diagnostics.js +34 -0
  128. package/dist/cli/lsp/server.js +329 -0
  129. package/dist/cli/main.d.ts.map +1 -1
  130. package/dist/cli/main.js +2540 -0
  131. package/dist/cli/mcp/lifecycle-tools.js +80 -0
  132. package/dist/cli/mcp/op-tools.js +306 -0
  133. package/dist/cli/mcp/resource-handlers.js +258 -0
  134. package/dist/cli/mcp/resources/context.js +85 -0
  135. package/dist/cli/mcp/server.js +353 -0
  136. package/dist/cli/mcp/tools/build.js +111 -0
  137. package/dist/cli/mcp/tools/composites.js +95 -0
  138. package/dist/cli/mcp/tools/explain.js +166 -0
  139. package/dist/cli/mcp/tools/import.js +49 -0
  140. package/dist/cli/mcp/tools/lint.js +41 -0
  141. package/dist/cli/mcp/tools/scaffold.js +111 -0
  142. package/dist/cli/mcp/tools/search.js +112 -0
  143. package/dist/cli/mcp/types.js +1 -0
  144. package/dist/cli/mcp/workspace-plugins.js +91 -0
  145. package/dist/cli/mcp/workspace-tools.d.ts +1 -1
  146. package/dist/cli/mcp/workspace-tools.js +564 -0
  147. package/dist/cli/mcp-config.js +70 -0
  148. package/dist/cli/plugins.js +313 -0
  149. package/dist/cli/registry.js +23 -0
  150. package/dist/cli/reporters/stylish.js +329 -0
  151. package/dist/cli/version.js +15 -0
  152. package/dist/cli/watch.js +79 -0
  153. package/dist/codegen/bound-property-types.js +82 -0
  154. package/dist/codegen/coverage.js +119 -0
  155. package/dist/codegen/docs-file-markers.js +60 -0
  156. package/dist/codegen/docs-pages.js +115 -0
  157. package/dist/codegen/docs-rule-scanning.js +164 -0
  158. package/dist/codegen/docs-rules.js +76 -0
  159. package/dist/codegen/docs-sections.js +117 -0
  160. package/dist/codegen/docs-sidebar.js +65 -0
  161. package/dist/codegen/docs-types.js +4 -0
  162. package/dist/codegen/docs.js +356 -0
  163. package/dist/codegen/fetch.js +340 -0
  164. package/dist/codegen/generate-post-synth-barrel.js +63 -0
  165. package/dist/codegen/generate-registry.js +71 -0
  166. package/dist/codegen/generate-runtime-index.js +56 -0
  167. package/dist/codegen/generate-typescript.js +119 -0
  168. package/dist/codegen/generate.js +115 -0
  169. package/dist/codegen/json-patch.js +141 -0
  170. package/dist/codegen/json-schema-to-ts.js +344 -0
  171. package/dist/codegen/json-schema.js +246 -0
  172. package/dist/codegen/lexicon-regen.js +412 -0
  173. package/dist/codegen/naming.js +217 -0
  174. package/dist/codegen/okf-lexicon.js +245 -0
  175. package/dist/codegen/package.js +150 -0
  176. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  177. package/dist/codegen/pinned-upgrade.js +494 -0
  178. package/dist/codegen/registry.js +60 -0
  179. package/dist/codegen/rehype-base-url.mjs +68 -0
  180. package/dist/codegen/rolling-upgrade.js +217 -0
  181. package/dist/codegen/surface-snapshot.js +537 -0
  182. package/dist/codegen/testdata/postgres-tags.json +242 -0
  183. package/dist/codegen/topo-sort.js +36 -0
  184. package/dist/codegen/typecheck.js +115 -0
  185. package/dist/codegen/validate.js +200 -0
  186. package/dist/codegen/version-bump.js +35 -0
  187. package/dist/components/auto-release.js +143 -0
  188. package/dist/components/builders.js +47 -0
  189. package/dist/components/capability-plugin-loader.js +175 -0
  190. package/dist/components/capability-plugin-schema.js +46 -0
  191. package/dist/components/capability-plugin.js +99 -0
  192. package/dist/components/capability.js +60 -0
  193. package/dist/components/changed-files.js +72 -0
  194. package/dist/components/cli-support.js +427 -0
  195. package/dist/components/component.js +120 -0
  196. package/dist/components/component.schema.json +271 -0
  197. package/dist/components/config-defaults.js +130 -0
  198. package/dist/components/deploy-units.js +60 -0
  199. package/dist/components/discover.d.ts.map +1 -1
  200. package/dist/components/discover.js +189 -0
  201. package/dist/components/driver-output.js +86 -0
  202. package/dist/components/driver.js +728 -0
  203. package/dist/components/fan-out-output.js +165 -0
  204. package/dist/components/fan-out-record.js +94 -0
  205. package/dist/components/fan-out-run.js +373 -0
  206. package/dist/components/fan-out-support.js +60 -0
  207. package/dist/components/fan-out.js +273 -0
  208. package/dist/components/gate-plan.js +41 -0
  209. package/dist/components/gated-wave-pipeline.js +46 -0
  210. package/dist/components/index.js +24 -0
  211. package/dist/components/layers.js +28 -0
  212. package/dist/components/manifest-persistence.js +108 -0
  213. package/dist/components/pilots/alb-ecs.pilot.js +59 -0
  214. package/dist/components/pilots/dynamodb.pilot.js +51 -0
  215. package/dist/components/pilots/jar-emr.pilot.js +65 -0
  216. package/dist/components/pilots/lambda.pilot.js +52 -0
  217. package/dist/components/pilots/neo4j-fanout.pilot.js +68 -0
  218. package/dist/components/pilots/project.js +12 -0
  219. package/dist/components/pr-pipeline.js +134 -0
  220. package/dist/components/pr-run.js +363 -0
  221. package/dist/components/presets/ecs-fargate.js +72 -0
  222. package/dist/components/presets/index.js +28 -0
  223. package/dist/components/presets/lambda.js +34 -0
  224. package/dist/components/presets/single-host-compose.js +41 -0
  225. package/dist/components/promote.js +549 -0
  226. package/dist/components/registry.js +34 -0
  227. package/dist/components/run-progress.js +33 -0
  228. package/dist/components/sandbox/driver.d.ts.map +1 -1
  229. package/dist/components/sandbox/driver.js +93 -0
  230. package/dist/components/sandbox/run.js +115 -0
  231. package/dist/components/starter-plugin.js +104 -0
  232. package/dist/components/verbs/__tests__/mock-cloud-executor.js +68 -0
  233. package/dist/components/verbs/__tests__/mock-process-runner.js +45 -0
  234. package/dist/components/verbs/__tests__/mock-sbom-generator.js +56 -0
  235. package/dist/components/verbs/bom-writer.js +287 -0
  236. package/dist/components/verbs/build-archive.js +188 -0
  237. package/dist/components/verbs/build.js +142 -0
  238. package/dist/components/verbs/cloud-executor.js +110 -0
  239. package/dist/components/verbs/component-bom.js +125 -0
  240. package/dist/components/verbs/ensure-secret.js +50 -0
  241. package/dist/components/verbs/index.js +61 -0
  242. package/dist/components/verbs/license-policy.js +75 -0
  243. package/dist/components/verbs/lockfile-sbom-generator.js +191 -0
  244. package/dist/components/verbs/process-runner.js +78 -0
  245. package/dist/components/verbs/r2-sync.js +93 -0
  246. package/dist/components/verbs/reproducibility.js +62 -0
  247. package/dist/components/verbs/run-agent.js +577 -0
  248. package/dist/components/verbs/sbom-generator.js +119 -0
  249. package/dist/components/verbs/sbom.js +97 -0
  250. package/dist/components/verbs/shell.js +32 -0
  251. package/dist/components/verbs/sign.js +221 -0
  252. package/dist/components/verbs/stub.js +28 -0
  253. package/dist/components/verbs/tool-sbom-generator.js +154 -0
  254. package/dist/components/verbs/verify.js +112 -0
  255. package/dist/components/verbs/vex.js +131 -0
  256. package/dist/components/verbs/vuln-gate.js +152 -0
  257. package/dist/components/verbs/vuln-scan.js +288 -0
  258. package/dist/components/verbs/wait-verify.js +106 -0
  259. package/dist/components/verbs/wrangler.js +179 -0
  260. package/dist/components/wave-plan.js +102 -0
  261. package/dist/composite.js +305 -0
  262. package/dist/config-import.d.ts.map +1 -1
  263. package/dist/config-import.js +22 -0
  264. package/dist/config-sandbox.js +122 -0
  265. package/dist/config-static.js +206 -0
  266. package/dist/config.js +605 -0
  267. package/dist/content-digest.js +23 -0
  268. package/dist/declarable.js +114 -0
  269. package/dist/deep-observation.js +437 -0
  270. package/dist/detectLexicon.js +54 -0
  271. package/dist/discovery/cache.js +70 -0
  272. package/dist/discovery/collect.js +208 -0
  273. package/dist/discovery/cycles.js +95 -0
  274. package/dist/discovery/entity-wire-codec.js +391 -0
  275. package/dist/discovery/entity-wire.js +42 -0
  276. package/dist/discovery/files.js +121 -0
  277. package/dist/discovery/fold-import.d.ts.map +1 -1
  278. package/dist/discovery/fold-import.js +4178 -0
  279. package/dist/discovery/fold-rank.js +292 -0
  280. package/dist/discovery/graph.js +115 -0
  281. package/dist/discovery/import.d.ts.map +1 -1
  282. package/dist/discovery/import.js +65 -0
  283. package/dist/discovery/index.js +333 -0
  284. package/dist/discovery/param-deps.js +487 -0
  285. package/dist/discovery/resolve.js +39 -0
  286. package/dist/discovery/sandbox/bundle.js +214 -0
  287. package/dist/discovery/sandbox/child-errors.js +26 -0
  288. package/dist/discovery/sandbox/config-run.js +100 -0
  289. package/dist/discovery/sandbox/config-wire.js +183 -0
  290. package/dist/discovery/sandbox/driver.d.ts.map +1 -1
  291. package/dist/discovery/sandbox/driver.js +333 -0
  292. package/dist/discovery/sandbox/fork.js +229 -0
  293. package/dist/discovery/sandbox/policy-run.js +142 -0
  294. package/dist/discovery/sandbox/policy-wire.js +152 -0
  295. package/dist/discovery/sandbox/run.js +77 -0
  296. package/dist/discovery/specifier-resolve.js +320 -0
  297. package/dist/discovery/walk.js +284 -0
  298. package/dist/effect-receipt.js +340 -0
  299. package/dist/env.js +55 -0
  300. package/dist/errors.js +62 -0
  301. package/dist/fold/fold.js +1434 -0
  302. package/dist/fold/foldable-helpers.js +229 -0
  303. package/dist/fold/subset.js +696 -0
  304. package/dist/fold-provenance.js +414 -0
  305. package/dist/gate-decision.d.ts +36 -4
  306. package/dist/gate-decision.d.ts.map +1 -1
  307. package/dist/gate-decision.js +260 -0
  308. package/dist/gate-resume-run.js +154 -0
  309. package/dist/gated-waves.js +165 -0
  310. package/dist/governance.js +43 -0
  311. package/dist/graph-declared.js +45 -0
  312. package/dist/graph-detail.js +207 -0
  313. package/dist/graph-dot.js +54 -0
  314. package/dist/graph-effective.js +107 -0
  315. package/dist/graph-ir.js +623 -0
  316. package/dist/graph-layout.js +184 -0
  317. package/dist/graph-lens.js +105 -0
  318. package/dist/graph-mermaid.js +83 -0
  319. package/dist/graph-ops.js +39 -0
  320. package/dist/graph-refs.js +156 -0
  321. package/dist/held-elsewhere.js +87 -0
  322. package/dist/identity.js +251 -0
  323. package/dist/import/base-parser.js +34 -0
  324. package/dist/import/embedded.js +255 -0
  325. package/dist/import/generator.js +1 -0
  326. package/dist/import/ir-utils.js +85 -0
  327. package/dist/import/parser-options.js +45 -0
  328. package/dist/import/parser.js +1 -0
  329. package/dist/index.js +118 -0
  330. package/dist/intrinsic-interpolation.js +73 -0
  331. package/dist/intrinsic.js +31 -0
  332. package/dist/join-key.js +35 -0
  333. package/dist/kubectl-context.js +150 -0
  334. package/dist/lexicon-config.js +58 -0
  335. package/dist/lexicon-integrity.js +47 -0
  336. package/dist/lexicon-manifest.js +70 -0
  337. package/dist/lexicon-module.d.ts.map +1 -1
  338. package/dist/lexicon-module.js +241 -0
  339. package/dist/lexicon-output.js +218 -0
  340. package/dist/lexicon-plugin-helpers.js +104 -0
  341. package/dist/lexicon-schema.js +136 -0
  342. package/dist/lexicon.js +130 -0
  343. package/dist/lifecycle/affected.js +224 -0
  344. package/dist/lifecycle/assert-live.js +110 -0
  345. package/dist/lifecycle/build-ledger-store.js +160 -0
  346. package/dist/lifecycle/build-ledger.js +155 -0
  347. package/dist/lifecycle/change-set.js +356 -0
  348. package/dist/lifecycle/converge-ledger.js +161 -0
  349. package/dist/lifecycle/deep-diff.js +233 -0
  350. package/dist/lifecycle/deep-observe.js +147 -0
  351. package/dist/lifecycle/digest.js +143 -0
  352. package/dist/lifecycle/disruption.js +135 -0
  353. package/dist/lifecycle/gate-applied.js +113 -0
  354. package/dist/lifecycle/gate-audit.js +341 -0
  355. package/dist/lifecycle/gate-ledger-select.js +89 -0
  356. package/dist/lifecycle/gate-ledger.d.ts +8 -0
  357. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  358. package/dist/lifecycle/gate-ledger.js +193 -0
  359. package/dist/lifecycle/gate-origin.js +117 -0
  360. package/dist/lifecycle/gate-pending.js +58 -0
  361. package/dist/lifecycle/git.js +1182 -0
  362. package/dist/lifecycle/identity.js +58 -0
  363. package/dist/lifecycle/index.js +26 -0
  364. package/dist/lifecycle/lease.js +283 -0
  365. package/dist/lifecycle/ledger-port.js +1 -0
  366. package/dist/lifecycle/legacy-digest.js +91 -0
  367. package/dist/lifecycle/live-diff.js +274 -0
  368. package/dist/lifecycle/local-note.js +15 -0
  369. package/dist/lifecycle/member-ledger.js +122 -0
  370. package/dist/lifecycle/observation-baseline.js +155 -0
  371. package/dist/lifecycle/observe.js +375 -0
  372. package/dist/lifecycle/oras-referrer-lookup.js +82 -0
  373. package/dist/lifecycle/override-ledger.js +54 -0
  374. package/dist/lifecycle/plan-digest.js +110 -0
  375. package/dist/lifecycle/plan-ledger.js +129 -0
  376. package/dist/lifecycle/receipt-plan.js +192 -0
  377. package/dist/lifecycle/release-ledger.js +155 -0
  378. package/dist/lifecycle/release-read.js +64 -0
  379. package/dist/lifecycle/replay.js +193 -0
  380. package/dist/lifecycle/rollback.js +102 -0
  381. package/dist/lifecycle/run-ledger.js +183 -0
  382. package/dist/lifecycle/scenario-eval.js +204 -0
  383. package/dist/lifecycle/scenario.js +214 -0
  384. package/dist/lifecycle/snapshot.js +239 -0
  385. package/dist/lifecycle/status.js +447 -0
  386. package/dist/lifecycle/symptoms.js +117 -0
  387. package/dist/lifecycle/teardown.js +255 -0
  388. package/dist/lifecycle/types.js +1 -0
  389. package/dist/lifecycle/unobserved-gate.js +33 -0
  390. package/dist/lifecycle/wave-plans.js +68 -0
  391. package/dist/lifecycle/work-item-id.js +36 -0
  392. package/dist/lifecycle/work-lease.js +393 -0
  393. package/dist/lint/component-checks.js +87 -0
  394. package/dist/lint/config.js +483 -0
  395. package/dist/lint/declarative.js +122 -0
  396. package/dist/lint/discover.d.ts.map +1 -1
  397. package/dist/lint/discover.js +138 -0
  398. package/dist/lint/engine.js +246 -0
  399. package/dist/lint/knowledge-checks.js +64 -0
  400. package/dist/lint/named-checks.js +22 -0
  401. package/dist/lint/output-checks.js +87 -0
  402. package/dist/lint/output-docs.js +163 -0
  403. package/dist/lint/parser.js +33 -0
  404. package/dist/lint/pipeline-change-gate.js +70 -0
  405. package/dist/lint/policy-import.d.ts +1 -1
  406. package/dist/lint/policy-import.d.ts.map +1 -1
  407. package/dist/lint/policy-import.js +62 -0
  408. package/dist/lint/policy-sandbox.js +86 -0
  409. package/dist/lint/policy.js +122 -0
  410. package/dist/lint/post-synth.js +87 -0
  411. package/dist/lint/presets/relaxed.json +26 -0
  412. package/dist/lint/presets/strict.json +24 -24
  413. package/dist/lint/receipt-checks.js +83 -0
  414. package/dist/lint/rule-loader.d.ts.map +1 -1
  415. package/dist/lint/rule-loader.js +89 -0
  416. package/dist/lint/rule-registry.js +86 -0
  417. package/dist/lint/rule.js +1 -0
  418. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.js +7 -0
  419. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.js +7 -0
  420. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.js +9 -0
  421. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.js +11 -0
  422. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.js +9 -0
  423. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.js +25 -0
  424. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.js +8 -0
  425. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.js +21 -0
  426. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.js +8 -0
  427. package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.js +24 -0
  428. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.js +17 -0
  429. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.js +8 -0
  430. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.js +18 -0
  431. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.js +20 -0
  432. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.js +8 -0
  433. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.js +12 -0
  434. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.js +16 -0
  435. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.js +8 -0
  436. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.js +12 -0
  437. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.js +11 -0
  438. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.js +11 -0
  439. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.js +10 -0
  440. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.js +16 -0
  441. package/dist/lint/rules/comp/comp001-publishes-never-applies.js +69 -0
  442. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.js +84 -0
  443. package/dist/lint/rules/comp/comp003-mutating-no-rollback.js +103 -0
  444. package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.js +70 -0
  445. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.js +109 -0
  446. package/dist/lint/rules/comp/comp006-shell-needs-reason.js +49 -0
  447. package/dist/lint/rules/comp/comp007-composition-sprawl.js +64 -0
  448. package/dist/lint/rules/comp/index.js +33 -0
  449. package/dist/lint/rules/comp/support.js +129 -0
  450. package/dist/lint/rules/composite-scope.js +51 -0
  451. package/dist/lint/rules/cor017-composite-name-match.js +93 -0
  452. package/dist/lint/rules/cor018-composite-prefer-lexicon-type.js +136 -0
  453. package/dist/lint/rules/cor021-env-literal-name.js +100 -0
  454. package/dist/lint/rules/cor022-receipt-leaf.js +118 -0
  455. package/dist/lint/rules/cor024-receipt-secret-pointer.js +199 -0
  456. package/dist/lint/rules/declarable-naming-convention.js +62 -0
  457. package/dist/lint/rules/evl001-non-literal-expression.js +66 -0
  458. package/dist/lint/rules/evl002-control-flow-resource.js +69 -0
  459. package/dist/lint/rules/evl003-dynamic-property-access.js +44 -0
  460. package/dist/lint/rules/evl004-spread-non-const.js +94 -0
  461. package/dist/lint/rules/evl005-resource-block-body.js +41 -0
  462. package/dist/lint/rules/evl007-invalid-siblings.js +105 -0
  463. package/dist/lint/rules/evl009-composite-no-constant.js +158 -0
  464. package/dist/lint/rules/evl010-composite-no-transform.js +59 -0
  465. package/dist/lint/rules/evl011-symbolic-in-template.js +106 -0
  466. package/dist/lint/rules/export-required.js +115 -0
  467. package/dist/lint/rules/file-declarable-limit.js +88 -0
  468. package/dist/lint/rules/flat-declarations.js +62 -0
  469. package/dist/lint/rules/index.js +90 -0
  470. package/dist/lint/rules/no-cyclic-declarable-ref.js +138 -0
  471. package/dist/lint/rules/no-redundant-type-import.js +76 -0
  472. package/dist/lint/rules/no-redundant-value-cast.js +41 -0
  473. package/dist/lint/rules/no-string-ref.js +59 -0
  474. package/dist/lint/rules/no-unused-declarable-import.js +75 -0
  475. package/dist/lint/rules/no-unused-declarable.js +142 -0
  476. package/dist/lint/rules/op/index.js +28 -0
  477. package/dist/lint/rules/op/ops012-activity-contract.js +54 -0
  478. package/dist/lint/rules/op/ops013-step-output-ref.js +88 -0
  479. package/dist/lint/rules/op/ops014-converge-rule-refusals.js +114 -0
  480. package/dist/lint/rules/op/ops015-gate-approval.js +45 -0
  481. package/dist/lint/rules/op/support.js +11 -0
  482. package/dist/lint/rules/op/sys010-key-over-plain-http.js +100 -0
  483. package/dist/lint/rules/property-kind.js +56 -0
  484. package/dist/lint/rules/single-concern-file.js +71 -0
  485. package/dist/lint/rules/sys001-no-literal-key.js +60 -0
  486. package/dist/lint/selectors.js +168 -0
  487. package/dist/lint/suppressions.js +129 -0
  488. package/dist/lint/typescript.js +17 -0
  489. package/dist/live-endpoint.js +113 -0
  490. package/dist/live-read-session.js +76 -0
  491. package/dist/lsp/lexicon-providers.js +163 -0
  492. package/dist/lsp/types.js +5 -0
  493. package/dist/managed-fields.js +293 -0
  494. package/dist/mcp/types.js +4 -0
  495. package/dist/notify-verify.js +0 -1
  496. package/dist/notify.js +0 -1
  497. package/dist/notify.schema.json +72 -0
  498. package/dist/observation.js +266 -0
  499. package/dist/okf-read.js +134 -0
  500. package/dist/okf.js +275 -0
  501. package/dist/op/__fixtures__/decide-stub-backend.js +125 -0
  502. package/dist/op/activities/activity-contracts.js +313 -0
  503. package/dist/op/activities/apply.js +582 -0
  504. package/dist/op/activities/build.js +18 -0
  505. package/dist/op/activities/change-coverage.js +40 -0
  506. package/dist/op/activities/change-set.js +64 -0
  507. package/dist/op/activities/converge.js +492 -0
  508. package/dist/op/activities/decide.js +211 -0
  509. package/dist/op/activities/env-teardown.js +110 -0
  510. package/dist/op/activities/factory.js +591 -0
  511. package/dist/op/activities/forge-pull-request.js +82 -0
  512. package/dist/op/activities/gh-host.js +78 -0
  513. package/dist/op/activities/guard-validate.js +165 -0
  514. package/dist/op/activities/http-check.js +40 -0
  515. package/dist/op/activities/index.js +59 -0
  516. package/dist/op/activities/lexicon-upgrade.js +629 -0
  517. package/dist/op/activities/lifecycle.js +109 -0
  518. package/dist/op/activities/pipeline-audit.js +147 -0
  519. package/dist/op/activities/policy.js +26 -0
  520. package/dist/op/activities/predict-behaviour.js +341 -0
  521. package/dist/op/activities/propose-upgrade.js +165 -0
  522. package/dist/op/activities/reconcile.js +997 -0
  523. package/dist/op/activities/shell.js +118 -0
  524. package/dist/op/activities/source-release.js +97 -0
  525. package/dist/op/activities/source-rollback.js +165 -0
  526. package/dist/op/activities/teardown.js +17 -0
  527. package/dist/op/activities/util.js +6 -0
  528. package/dist/op/activities/wait.js +51 -0
  529. package/dist/op/activities/work-evidence.js +35 -0
  530. package/dist/op/activities/workflow-audit.js +133 -0
  531. package/dist/op/activity-contract-registry.js +106 -0
  532. package/dist/op/activity-contract.js +232 -0
  533. package/dist/op/activity-failure.js +31 -0
  534. package/dist/op/activity-profiles.js +129 -0
  535. package/dist/op/activity-registry.js +105 -0
  536. package/dist/op/activity-runtime.js +28 -0
  537. package/dist/op/builders.js +801 -0
  538. package/dist/op/change-signal.js +118 -0
  539. package/dist/op/composites/apply-op.js +151 -0
  540. package/dist/op/composites/behaviour-op.js +65 -0
  541. package/dist/op/composites/converge-op.js +141 -0
  542. package/dist/op/composites/index.js +19 -0
  543. package/dist/op/composites/lexicon-upgrade-op.js +107 -0
  544. package/dist/op/composites/pipeline-audit-op.js +50 -0
  545. package/dist/op/composites/reconcile-op.js +84 -0
  546. package/dist/op/composites/watch-op.js +69 -0
  547. package/dist/op/composites/workflow-audit-op.js +57 -0
  548. package/dist/op/converge-rule.js +205 -0
  549. package/dist/op/cron.js +146 -0
  550. package/dist/op/decide-backend.js +181 -0
  551. package/dist/op/decide-config.js +68 -0
  552. package/dist/op/decide-read-inputs.js +141 -0
  553. package/dist/op/discover.d.ts.map +1 -1
  554. package/dist/op/discover.js +213 -0
  555. package/dist/op/duration.js +21 -0
  556. package/dist/op/emulator-freshness.js +80 -0
  557. package/dist/op/emulator-lifecycle.js +269 -0
  558. package/dist/op/factory.js +83 -0
  559. package/dist/op/gate-approval.js +172 -0
  560. package/dist/op/gate-name.js +86 -0
  561. package/dist/op/gate-plan-context.js +167 -0
  562. package/dist/op/gate-point-run.js +67 -0
  563. package/dist/op/gate-point.js +111 -0
  564. package/dist/op/gate-resume-plan.js +155 -0
  565. package/dist/op/gate-resume.js +31 -0
  566. package/dist/op/gate-review.js +290 -0
  567. package/dist/op/gate-run-locator.js +85 -0
  568. package/dist/op/gate-summary.js +100 -0
  569. package/dist/op/gate-wait.js +56 -0
  570. package/dist/op/gate.js +449 -0
  571. package/dist/op/generate-pipeline.js +124 -0
  572. package/dist/op/index.js +51 -0
  573. package/dist/op/lifecycle-receipt-store.js +45 -0
  574. package/dist/op/local-executor.js +1164 -0
  575. package/dist/op/local-output.js +140 -0
  576. package/dist/op/op-ir.js +317 -0
  577. package/dist/op/op-verb-class.js +131 -0
  578. package/dist/op/op-waves-notify.js +136 -0
  579. package/dist/op/op-waves-run.d.ts +1 -1
  580. package/dist/op/op-waves-run.d.ts.map +1 -1
  581. package/dist/op/op-waves-run.js +1657 -0
  582. package/dist/op/op-waves.js +409 -0
  583. package/dist/op/operator.js +743 -0
  584. package/dist/op/receipt-store.js +94 -0
  585. package/dist/op/resource.js +23 -0
  586. package/dist/op/run-context.js +28 -0
  587. package/dist/op/run-live.js +256 -0
  588. package/dist/op/runtime.js +21 -0
  589. package/dist/op/runtimes/local.js +195 -0
  590. package/dist/op/source-archive.js +131 -0
  591. package/dist/op/step-output-ref.js +397 -0
  592. package/dist/op/steward-beside.js +169 -0
  593. package/dist/op/steward-points.js +138 -0
  594. package/dist/op/steward-turn.js +59 -0
  595. package/dist/op/steward.js +317 -0
  596. package/dist/op/types.js +25 -0
  597. package/dist/op/work-lease-decl.js +81 -0
  598. package/dist/op/work-lease-run.js +393 -0
  599. package/dist/override-gate.js +284 -0
  600. package/dist/owner-chain.js +74 -0
  601. package/dist/ownership.js +92 -0
  602. package/dist/params.js +61 -0
  603. package/dist/plan-summary.js +711 -0
  604. package/dist/point-decision.js +211 -0
  605. package/dist/pr-forge.js +810 -0
  606. package/dist/pr-loop.js +203 -0
  607. package/dist/project-codegen.js +191 -0
  608. package/dist/project-root.js +74 -0
  609. package/dist/project-validation.js +50 -0
  610. package/dist/provenance.js +157 -0
  611. package/dist/pseudo-parameter.js +40 -0
  612. package/dist/reconcile.js +450 -0
  613. package/dist/resource-attributes.js +33 -0
  614. package/dist/runtime-adapter.js +77 -0
  615. package/dist/runtime.js +66 -0
  616. package/dist/secret-materialization.js +153 -0
  617. package/dist/secret-provenance.js +250 -0
  618. package/dist/serializer-walker.js +112 -0
  619. package/dist/serializer.js +1 -0
  620. package/dist/sort.js +45 -0
  621. package/dist/stack-output.js +115 -0
  622. package/dist/telemetry-attribution.js +149 -0
  623. package/dist/terraform/__fixtures__/build-graph.js +63 -0
  624. package/dist/terraform/adopt-state.js +40 -0
  625. package/dist/terraform/aws-resources.js +384 -0
  626. package/dist/terraform/bridge.js +204 -0
  627. package/dist/terraform/carve-provider.js +155 -0
  628. package/dist/terraform/carve.js +138 -0
  629. package/dist/terraform/data-source-shape.js +57 -0
  630. package/dist/terraform/emit-source.js +36 -0
  631. package/dist/terraform/excise.js +123 -0
  632. package/dist/terraform/graduate.js +128 -0
  633. package/dist/terraform/graph.js +435 -0
  634. package/dist/terraform/hcl2json.js +60 -0
  635. package/dist/terraform/manifest.js +149 -0
  636. package/dist/terraform/parse.js +81 -0
  637. package/dist/terraform/providers/aws.js +146 -0
  638. package/dist/terraform/providers/gcp.js +294 -0
  639. package/dist/terraform/providers/index.js +17 -0
  640. package/dist/terraform/providers/kubernetes.js +253 -0
  641. package/dist/terraform/score.js +151 -0
  642. package/dist/terraform/state.js +67 -0
  643. package/dist/terraform/tier-map.js +74 -0
  644. package/dist/terraform/types.js +13 -0
  645. package/dist/terraform/unified-diff.js +132 -0
  646. package/dist/testing.js +295 -0
  647. package/dist/toml-emit.js +153 -0
  648. package/dist/toml-parse.js +355 -0
  649. package/dist/toml-utils.js +60 -0
  650. package/dist/toml.js +428 -0
  651. package/dist/ts-loader.d.ts +46 -0
  652. package/dist/ts-loader.d.ts.map +1 -0
  653. package/dist/ts-loader.js +103 -0
  654. package/dist/types.js +1 -0
  655. package/dist/utils.js +61 -0
  656. package/dist/validation.js +20 -0
  657. package/dist/vendor/js-yaml-load.js +1662 -0
  658. package/dist/workspace/__fixtures__/contract-repo.js +103 -0
  659. package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
  660. package/dist/workspace/__fixtures__/sessions.js +91 -0
  661. package/dist/workspace/__fixtures__/two-member-workspace.js +34 -0
  662. package/dist/workspace/agent-cli.js +99 -0
  663. package/dist/workspace/agent.schema.json +390 -0
  664. package/dist/workspace/answers-ledger.js +89 -0
  665. package/dist/workspace/box-cli.js +142 -0
  666. package/dist/workspace/box-factory-write.js +196 -0
  667. package/dist/workspace/box-factory-write.schema.json +342 -0
  668. package/dist/workspace/box-factory.js +88 -0
  669. package/dist/workspace/box-intent.js +126 -0
  670. package/dist/workspace/box-isolation.js +169 -0
  671. package/dist/workspace/box-listing-write.schema.json +204 -0
  672. package/dist/workspace/box-listing.js +298 -0
  673. package/dist/workspace/box-publish.js +352 -0
  674. package/dist/workspace/box-publish.schema.json +498 -0
  675. package/dist/workspace/box-services.js +39 -0
  676. package/dist/workspace/broker-protocol.js +359 -0
  677. package/dist/workspace/broker-protocol.schema.json +228 -0
  678. package/dist/workspace/change-set.schema.json +460 -0
  679. package/dist/workspace/changes-cli.js +56 -0
  680. package/dist/workspace/changes.js +446 -0
  681. package/dist/workspace/changes.schema.json +642 -0
  682. package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.js +198 -0
  683. package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.js +155 -0
  684. package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.js +214 -0
  685. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.js +180 -0
  686. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.js +99 -0
  687. package/dist/workspace/chant-migrations/chud-lexicon-exit.js +847 -0
  688. package/dist/workspace/chant-migrations.js +113 -0
  689. package/dist/workspace/check.schema.json +433 -0
  690. package/dist/workspace/checks/box-isolation.js +62 -0
  691. package/dist/workspace/checks/boxes.js +491 -0
  692. package/dist/workspace/checks/diagrams.js +104 -0
  693. package/dist/workspace/checks/generated.js +419 -0
  694. package/dist/workspace/checks/ledgers.js +212 -0
  695. package/dist/workspace/checks/links.js +191 -0
  696. package/dist/workspace/checks/live.js +100 -0
  697. package/dist/workspace/checks/pipelines.js +188 -0
  698. package/dist/workspace/checks/records.js +169 -0
  699. package/dist/workspace/checks.js +426 -0
  700. package/dist/workspace/ci-green-cli.js +125 -0
  701. package/dist/workspace/ci-green-forge.js +83 -0
  702. package/dist/workspace/ci-green-workflow.js +199 -0
  703. package/dist/workspace/ci-green.js +325 -0
  704. package/dist/workspace/ci-last-green.schema.json +158 -0
  705. package/dist/workspace/compose-graph.js +235 -0
  706. package/dist/workspace/compose-reports.js +146 -0
  707. package/dist/workspace/composites.js +264 -0
  708. package/dist/workspace/composites.schema.json +617 -0
  709. package/dist/workspace/conformance/__fixture__/app/package.json +7 -0
  710. package/dist/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
  711. package/dist/workspace/conformance/__fixture__/decisions/decision.kind.mjs +54 -0
  712. package/dist/workspace/conformance/__fixture__/decisions/decision.schema.json +512 -0
  713. package/dist/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
  714. package/dist/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
  715. package/dist/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
  716. package/dist/workspace/conformance/__fixture__/delivery/package.json +7 -0
  717. package/dist/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
  718. package/dist/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
  719. package/dist/workspace/conformance/__fixtures__/reference-broker.js +205 -0
  720. package/dist/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  721. package/dist/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  722. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  723. package/dist/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  724. package/dist/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  725. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  726. package/dist/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  727. package/dist/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  728. package/dist/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  729. package/dist/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  730. package/dist/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  731. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  732. package/dist/workspace/conformance/broker.js +736 -0
  733. package/dist/workspace/conformance/index.js +673 -0
  734. package/dist/workspace/conformance/vitest.js +108 -0
  735. package/dist/workspace/conformance/writer.js +1080 -0
  736. package/dist/workspace/decide.js +879 -0
  737. package/dist/workspace/decision-points.schema.json +135 -135
  738. package/dist/workspace/declaration-write-cli.js +74 -0
  739. package/dist/workspace/declaration-write.js +238 -0
  740. package/dist/workspace/declaration.js +938 -0
  741. package/dist/workspace/declaration.schema.json +1413 -1413
  742. package/dist/workspace/declared-kinds.js +106 -0
  743. package/dist/workspace/environments.js +164 -0
  744. package/dist/workspace/evidence.schema.json +279 -0
  745. package/dist/workspace/export-cli.js +185 -0
  746. package/dist/workspace/export.js +499 -0
  747. package/dist/workspace/factory-rules.js +175 -0
  748. package/dist/workspace/generated-files.js +92 -0
  749. package/dist/workspace/glob.js +45 -0
  750. package/dist/workspace/graph-cache.js +352 -0
  751. package/dist/workspace/graph-cli.js +348 -0
  752. package/dist/workspace/graph.schema.json +1338 -0
  753. package/dist/workspace/identity-gate-rule.d.ts +65 -0
  754. package/dist/workspace/identity-gate-rule.d.ts.map +1 -0
  755. package/dist/workspace/identity-gate-rule.js +75 -0
  756. package/dist/workspace/identity.d.ts +4 -2
  757. package/dist/workspace/identity.d.ts.map +1 -1
  758. package/dist/workspace/identity.js +126 -0
  759. package/dist/workspace/import.js +283 -0
  760. package/dist/workspace/init.js +620 -0
  761. package/dist/workspace/intent-cli.js +263 -0
  762. package/dist/workspace/intent-joins.js +201 -0
  763. package/dist/workspace/intent-record.js +352 -0
  764. package/dist/workspace/intent-record.schema.json +864 -0
  765. package/dist/workspace/intent.js +1582 -0
  766. package/dist/workspace/intent.schema.json +2420 -0
  767. package/dist/workspace/json-edit.js +221 -0
  768. package/dist/workspace/jsonc.js +235 -0
  769. package/dist/workspace/kind-readers.js +103 -0
  770. package/dist/workspace/kinds.js +587 -0
  771. package/dist/workspace/lexicon-symbols.js +112 -0
  772. package/dist/workspace/lineage-adopt-cli.js +102 -0
  773. package/dist/workspace/lineage-adopt.js +360 -0
  774. package/dist/workspace/lineage-check.js +282 -0
  775. package/dist/workspace/lineage-cli.js +121 -0
  776. package/dist/workspace/lineage-hash-index.js +284 -0
  777. package/dist/workspace/lineage-init.js +507 -0
  778. package/dist/workspace/lineage-lock.js +387 -0
  779. package/dist/workspace/lineage-merge.js +45 -0
  780. package/dist/workspace/lineage-migrations.d.ts.map +1 -1
  781. package/dist/workspace/lineage-migrations.js +329 -0
  782. package/dist/workspace/lineage-provenance.js +36 -0
  783. package/dist/workspace/lineage-update.js +138 -0
  784. package/dist/workspace/lineage-upgrade-cli.js +131 -0
  785. package/dist/workspace/lineage-upgrade.js +889 -0
  786. package/dist/workspace/lineage-vendor.js +171 -0
  787. package/dist/workspace/lineage-version.js +128 -0
  788. package/dist/workspace/lineage-versions.js +275 -0
  789. package/dist/workspace/links.js +330 -0
  790. package/dist/workspace/ls-generated.js +95 -0
  791. package/dist/workspace/ls.js +277 -0
  792. package/dist/workspace/ls.schema.json +333 -0
  793. package/dist/workspace/member-commands.js +508 -0
  794. package/dist/workspace/member-handles.js +216 -0
  795. package/dist/workspace/member-pipeline.js +258 -0
  796. package/dist/workspace/member-run.js +117 -0
  797. package/dist/workspace/member-write.schema.json +193 -0
  798. package/dist/workspace/nested-graph.js +156 -0
  799. package/dist/workspace/nesting.js +38 -0
  800. package/dist/workspace/patch.js +301 -0
  801. package/dist/workspace/patch.schema.json +321 -0
  802. package/dist/workspace/pin-cli.js +55 -0
  803. package/dist/workspace/pin-integrity.js +100 -0
  804. package/dist/workspace/plan-summary.schema.json +155 -0
  805. package/dist/workspace/point-answer.schema.json +129 -129
  806. package/dist/workspace/points-cli.js +291 -0
  807. package/dist/workspace/points-write.schema.json +660 -0
  808. package/dist/workspace/points.js +521 -0
  809. package/dist/workspace/points.schema.json +916 -0
  810. package/dist/workspace/pr-report.schema.json +108 -0
  811. package/dist/workspace/principal-classes.d.ts +3 -14
  812. package/dist/workspace/principal-classes.d.ts.map +1 -1
  813. package/dist/workspace/principal-classes.js +245 -0
  814. package/dist/workspace/reason-codes.js +326 -0
  815. package/dist/workspace/record-assets.js +151 -0
  816. package/dist/workspace/record-decided.js +105 -0
  817. package/dist/workspace/record-sessions.js +96 -0
  818. package/dist/workspace/record-source.js +114 -0
  819. package/dist/workspace/records-amend.schema.json +284 -0
  820. package/dist/workspace/records-checkout.js +76 -0
  821. package/dist/workspace/records-cli.js +707 -0
  822. package/dist/workspace/records-close.js +116 -0
  823. package/dist/workspace/records-close.schema.json +278 -0
  824. package/dist/workspace/records-new.schema.json +202 -0
  825. package/dist/workspace/records-review.schema.json +367 -0
  826. package/dist/workspace/records-since.js +317 -0
  827. package/dist/workspace/records-since.schema.json +218 -0
  828. package/dist/workspace/records-write.js +1229 -0
  829. package/dist/workspace/records.js +1345 -0
  830. package/dist/workspace/records.schema.json +604 -0
  831. package/dist/workspace/reference-kinds/app/package.json +10 -0
  832. package/dist/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  833. package/dist/workspace/returns.js +303 -0
  834. package/dist/workspace/root-refusal.js +75 -0
  835. package/dist/workspace/run-statement.schema.json +622 -0
  836. package/dist/workspace/runs-cli.js +584 -0
  837. package/dist/workspace/runs-write.schema.json +994 -0
  838. package/dist/workspace/runs.js +708 -0
  839. package/dist/workspace/runs.schema.json +1257 -0
  840. package/dist/workspace/runtimes.js +76 -0
  841. package/dist/workspace/session-kinds.js +83 -0
  842. package/dist/workspace/signers.schema.json +206 -0
  843. package/dist/workspace/source-block.js +125 -0
  844. package/dist/workspace/squash.js +177 -0
  845. package/dist/workspace/status-gates.js +162 -0
  846. package/dist/workspace/status-stewards.js +330 -0
  847. package/dist/workspace/status.js +514 -0
  848. package/dist/workspace/status.schema.json +998 -0
  849. package/dist/workspace/steward-index.js +191 -0
  850. package/dist/workspace/symbols.js +188 -0
  851. package/dist/workspace/template-manifest.js +227 -0
  852. package/dist/workspace/template-pins.js +115 -0
  853. package/dist/workspace/trailer-joins.js +65 -0
  854. package/dist/workspace/trailers.js +111 -0
  855. package/dist/workspace/tree.js +136 -0
  856. package/dist/workspace/trust/attestor.js +63 -0
  857. package/dist/workspace/trust/dsse.js +108 -0
  858. package/dist/workspace/trust/evidence-cli.js +175 -0
  859. package/dist/workspace/trust/evidence.js +161 -0
  860. package/dist/workspace/trust/gate-seal.js +226 -0
  861. package/dist/workspace/trust/policy.js +190 -0
  862. package/dist/workspace/trust/provenance.js +180 -0
  863. package/dist/workspace/trust/rotation.js +298 -0
  864. package/dist/workspace/trust/run-commits.js +101 -0
  865. package/dist/workspace/trust/run-statement.js +182 -0
  866. package/dist/workspace/trust/seal.js +272 -0
  867. package/dist/workspace/trust/signers-cli.js +152 -0
  868. package/dist/workspace/trust/ssh-commit.js +178 -0
  869. package/dist/workspace/trust/test-repo.js +118 -0
  870. package/dist/workspace/trust/trust-files.js +193 -0
  871. package/dist/workspace/trust/verify-cli.js +63 -0
  872. package/dist/workspace/trust/verify.js +192 -0
  873. package/dist/workspace/which-chant.js +141 -0
  874. package/dist/workspace/wip-cli.js +95 -0
  875. package/dist/workspace/wip-write.schema.json +504 -0
  876. package/dist/workspace/wip.js +631 -0
  877. package/dist/workspace/wip.schema.json +334 -0
  878. package/dist/workspace/work-cli.js +448 -0
  879. package/dist/workspace/work-evidence.js +122 -0
  880. package/dist/workspace/work-evidence.schema.json +222 -0
  881. package/dist/workspace/work-history.schema.json +421 -0
  882. package/dist/workspace/work-lease.schema.json +246 -0
  883. package/dist/workspace/work-size.js +77 -0
  884. package/dist/workspace/work.js +283 -0
  885. package/dist/workspace/workspace-kinds.schema.json +259 -259
  886. package/dist/workspace/workspace-principals.schema.json +53 -53
  887. package/dist/workspace/write-lock-cli.js +105 -0
  888. package/dist/workspace/write-lock.js +424 -0
  889. package/dist/workspace/write-lock.schema.json +172 -0
  890. package/dist/workspace/write-scope.js +484 -0
  891. package/dist/yaml.js +459 -0
  892. package/package.json +2 -2
  893. package/src/cli/commands/check-lexicon-plugin.ts +2 -0
  894. package/src/cli/commands/lint.ts +36 -6
  895. package/src/cli/commands/migrate.ts +2 -0
  896. package/src/cli/compiled-cli.e2e.test.ts +165 -0
  897. package/src/cli/main.ts +121 -27
  898. package/src/cli/mcp/workspace-tools.ts +1 -1
  899. package/src/codegen/pinned-upgrade.ts +2 -0
  900. package/src/components/discover.ts +2 -0
  901. package/src/components/sandbox/driver.ts +3 -1
  902. package/src/config-import.ts +3 -0
  903. package/src/discovery/fold-import.ts +23 -14
  904. package/src/discovery/import.ts +2 -0
  905. package/src/discovery/sandbox/driver.ts +3 -1
  906. package/src/gate-decision-bundle.test.ts +3 -2
  907. package/src/gate-decision-identity.test.ts +176 -0
  908. package/src/gate-decision.ts +100 -22
  909. package/src/lexicon-module.ts +3 -0
  910. package/src/lifecycle/gate-ledger.ts +8 -0
  911. package/src/lint/config.ts +1 -1
  912. package/src/lint/discover.ts +28 -8
  913. package/src/lint/policy-import.ts +4 -1
  914. package/src/lint/rule-loader.ts +2 -0
  915. package/src/op/discover.ts +3 -0
  916. package/src/op/op-waves-point.test.ts +1 -0
  917. package/src/op/op-waves-run.ts +5 -4
  918. package/src/op/op-waves.test.ts +14 -0
  919. package/src/ts-loader.test.ts +23 -0
  920. package/src/ts-loader.ts +122 -0
  921. package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
  922. package/src/workspace/declaration.ts +1 -1
  923. package/src/workspace/identity-gate-rule.ts +109 -0
  924. package/src/workspace/identity.ts +8 -18
  925. package/src/workspace/kinds.ts +1 -1
  926. package/src/workspace/lineage-migrations.ts +2 -0
  927. package/src/workspace/points.ts +1 -1
  928. package/src/workspace/principal-classes.ts +5 -30
@@ -0,0 +1,938 @@
1
+ /**
2
+ * The workspace declaration, `chant.workspace.json` or `.jsonc` (#2524 D1, D2;
3
+ * ws-051 for example groups).
4
+ *
5
+ * Every read goes through {@link parseDeclaration}: the text is parsed with
6
+ * positions, the declared `minReader` is checked, the result is validated
7
+ * against the JSON Schema shipped beside this file, and then the rules JSON
8
+ * Schema can't say are checked in code: unique names, and the placement rules.
9
+ * Any failure is a {@link WorkspaceReadError} naming the file, line and
10
+ * column. A declaration never reads as empty.
11
+ *
12
+ * Group matches depend on the tree, so their placement is checked when they
13
+ * are expanded ({@link resolveGroups}).
14
+ *
15
+ * Everything under `workspace/` loads only when a `chant workspace` command
16
+ * runs. The level-0 goldens (#2526) fail if a level-0 command loads it.
17
+ */
18
+ import { readFileSync } from "node:fs";
19
+ import { createRequire } from "node:module";
20
+ import { fileURLToPath } from "node:url";
21
+ import schema from "./declaration.schema.json" with { type: "json" };
22
+ import { expandGlob } from "./glob.js";
23
+ import { EXAMPLES_KIND, holdsChantProject } from "./kinds.js";
24
+ import { parseJsonText, pointerToken } from "./jsonc.js";
25
+ import { joinPath } from "./tree.js";
26
+ export const DECLARATION_SCHEMA_ID = schema.$id;
27
+ export const DECLARATION_FILES = ["chant.workspace.json", "chant.workspace.jsonc"];
28
+ export const DECLARATION_SCHEMA_VERSION = 1;
29
+ /** Names no member or group may take: ledger paths use them (#2524 D7, D17). */
30
+ export const RESERVED_NAMES = ["_workspace", "_members"];
31
+ export const NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,39}$/;
32
+ // ── Errors ───────────────────────────────────────────────────────────────────
33
+ /**
34
+ * Why a workspace could not be read. The list is closed: a reader may switch
35
+ * on it, and a new code is a contract change (#2524 D15).
36
+ */
37
+ export const WORKSPACE_ERROR_CODES = [
38
+ /** No chant.workspace.json or .jsonc between the directory and the git root. */
39
+ "declaration-missing",
40
+ /** Both chant.workspace.json and chant.workspace.jsonc are present. */
41
+ "declaration-ambiguous",
42
+ /** The file is not valid JSON (or JSONC, for .jsonc). */
43
+ "declaration-unparseable",
44
+ /** The file does not match the declaration schema, or repeats a name. */
45
+ "declaration-invalid",
46
+ /** A member or group match breaks a placement rule (#2524 D2, ws-051). */
47
+ "placement-invalid",
48
+ /** The declaration's minReader is newer than this chant. */
49
+ "reader-too-old",
50
+ /** The declaration pins another chant, which is not installed at the root (#2524 D15, ws-021). */
51
+ "root-chant-required",
52
+ /** `--at` was given outside a git repository. */
53
+ "not-a-git-repository",
54
+ /** `--at` names no commit. */
55
+ "revision-unknown",
56
+ ];
57
+ export class WorkspaceReadError extends Error {
58
+ constructor(code, message, location) {
59
+ super(message);
60
+ this.code = code;
61
+ this.location = location;
62
+ this.name = "WorkspaceReadError";
63
+ }
64
+ /** `file:line:column: message`, or the message alone. */
65
+ describe() {
66
+ const l = this.location;
67
+ return l ? `${l.file}:${l.line}:${l.column}: ${this.message}` : this.message;
68
+ }
69
+ }
70
+ /** The core principal classes (#2524 D5). A pinned package may supply domain classes too (#3080, `principal-classes.ts`). */
71
+ export const PRINCIPAL_CLASSES = ["human", "agent", "runner", "service"];
72
+ /** How a record is written, as the records commands name it (#2548). */
73
+ export const WRITE_VERBS = ["new", "amend", "review", "close"];
74
+ /** The default `ci.green.window`. */
75
+ export const DEFAULT_CI_WINDOW = "24h";
76
+ /** A renderer a diagram is pinned to (#2764): a closed list of tools chant does not run. */
77
+ export const DIAGRAM_TOOLS = ["d2", "mermaid", "graphviz", "excalidraw"];
78
+ /** The gate a ship Op stops at when the block names none (ws-100). */
79
+ export const DEFAULT_SHIP_GATE = "ship";
80
+ /** The environment a ship Op records its releases in when the block names none (ws-100). */
81
+ export const DEFAULT_SHIP_ENV = "box";
82
+ /** What a replicate policy pushes (#3172): work branches, kept attempts, work-in-progress snapshots and the ledger branch. */
83
+ export const REPLICATE_REF_CLASSES = ["work", "kept", "wip", "ledger"];
84
+ /** When chant pushes on its own under a replicate policy (#3172). */
85
+ export const REPLICATE_TRIGGERS = ["save", "release"];
86
+ /** The remote a replicate policy pushes to when it names none. */
87
+ export const DEFAULT_REPLICATE_REMOTE = "origin";
88
+ /** What a check command is (#3146). */
89
+ export const FACTORY_CHECK_KINDS = ["test", "build", "lint", "plan", "conformance"];
90
+ /** The branch prefix a publish target uses when it names none: the work lease's own branch. */
91
+ export const DEFAULT_PUBLISH_BRANCH_PREFIX = "chant/work/";
92
+ /** Where boxes keep state when their host names no stateRoot (#2727). */
93
+ export const DEFAULT_STATE_ROOT = "${XDG_STATE_HOME}/chant/boxes";
94
+ // ── This chant ───────────────────────────────────────────────────────────────
95
+ /** The package whose pin names the root's chant (#2524 D15, ws-021). */
96
+ export const CHANT_PACKAGE = "@intentius/chant";
97
+ let readerVersionCache;
98
+ /**
99
+ * The version of the chant doing the reading. Read as a file, not through
100
+ * `require`: discovery reads the declaration on every walk under a workspace
101
+ * root (#2527), and a CJS require of `package.json` took about a minute per
102
+ * call in a vitest worker once a build had run in it, where a file read takes
103
+ * well under a millisecond.
104
+ */
105
+ export function readerVersion() {
106
+ readerVersionCache ?? (readerVersionCache = JSON.parse(readFileSync(fileURLToPath(new URL("../../package.json", import.meta.url)), "utf-8")).version);
107
+ return readerVersionCache;
108
+ }
109
+ const SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?$/;
110
+ /** Negative when `a` is older than `b`. Build metadata is not allowed, and prereleases sort before their release. */
111
+ export function compareVersions(a, b) {
112
+ const ma = SEMVER.exec(a);
113
+ const mb = SEMVER.exec(b);
114
+ if (!ma || !mb)
115
+ throw new Error(`not a version: ${ma ? b : a}`);
116
+ for (let i = 1; i <= 3; i++) {
117
+ const d = Number(ma[i]) - Number(mb[i]);
118
+ if (d !== 0)
119
+ return d;
120
+ }
121
+ if (ma[4] === mb[4])
122
+ return 0;
123
+ if (ma[4] === undefined)
124
+ return 1;
125
+ if (mb[4] === undefined)
126
+ return -1;
127
+ return ma[4] < mb[4] ? -1 : 1;
128
+ }
129
+ let compiled;
130
+ function validator() {
131
+ if (compiled)
132
+ return compiled;
133
+ const require = createRequire(import.meta.url);
134
+ // ajv is CommonJS; its class is the default export, or that export's own default.
135
+ const mod = require("ajv/dist/2020");
136
+ const Ajv = (mod.default ?? mod);
137
+ compiled = new Ajv({ allErrors: true, strict: true }).compile(schema);
138
+ return compiled;
139
+ }
140
+ /** Readable text for one schema error, keyed on the rule that failed. */
141
+ function explain(e, value) {
142
+ const def = /#\/\$defs\/([A-Za-z]+)\//.exec(e.schemaPath)?.[1];
143
+ if (e.keyword === "pattern") {
144
+ const shown = JSON.stringify(value);
145
+ if (def === "name" && typeof value === "string" && RESERVED_NAMES.includes(value)) {
146
+ return `${shown} is reserved; pick another name`;
147
+ }
148
+ if (def === "name")
149
+ return `${shown} is not a valid name: use lowercase letters, digits and hyphens, starting with a letter or digit, at most 40 characters`;
150
+ if (def === "kindName")
151
+ return `${shown} is not a valid kind or role name`;
152
+ if (def === "dir")
153
+ return `${shown} is not a directory inside the workspace: use a relative path with / separators, and no . or .. segments`;
154
+ if (def === "path")
155
+ return `${shown} is not a path inside the member or workspace: use a relative path with / separators, and no . or .. segments`;
156
+ if (def === "glob")
157
+ return `${shown} is not a glob inside the workspace: use a relative pattern with / separators, and no . or .. segments`;
158
+ if (def === "version")
159
+ return `${shown} is not a version such as 1.2.3`;
160
+ return `${shown} is not allowed here`;
161
+ }
162
+ if (e.keyword === "additionalProperties") {
163
+ return `unknown field ${JSON.stringify(e.params.additionalProperty)}; only fields named x-... may be added`;
164
+ }
165
+ if (e.keyword === "required") {
166
+ const missing = String(e.params.missingProperty);
167
+ if (missing === "because" && e.instancePath.endsWith("/handWritten"))
168
+ return `a hand-written generated file needs "because", saying why it is kept by hand`;
169
+ if (missing === "because")
170
+ return `a member of kind other needs "because", saying why it is there`;
171
+ return `missing required field ${JSON.stringify(missing)}`;
172
+ }
173
+ if (e.keyword === "const" && e.instancePath === "/schema")
174
+ return `schema must be 1, the only declaration format this chant reads`;
175
+ return e.message ?? "is invalid";
176
+ }
177
+ /** Keywords that only summarise errors reported on their own. */
178
+ const SUMMARY_KEYWORDS = new Set(["if", "then", "else", "oneOf", "anyOf"]);
179
+ function valueAt(root, pointer) {
180
+ let v = root;
181
+ for (const token of pointer.split("/").slice(1)) {
182
+ const key = token.replace(/~1/g, "/").replace(/~0/g, "~");
183
+ if (v === null || typeof v !== "object")
184
+ return undefined;
185
+ v = v[key];
186
+ }
187
+ return v;
188
+ }
189
+ /** The version the declaration's `@intentius/chant` pin names, and where the pin is. Undefined without one. */
190
+ export function pinnedChant(obj) {
191
+ if (!Array.isArray(obj.pins))
192
+ return undefined;
193
+ const index = obj.pins.findIndex((p) => p !== null && typeof p === "object" && p.package === CHANT_PACKAGE && typeof p.version === "string");
194
+ return index < 0 ? undefined : { version: obj.pins[index].version, index };
195
+ }
196
+ /**
197
+ * Parse and check a declaration's text. `file` is the name used in messages
198
+ * and decides the dialect: a name ending in `.jsonc` allows comments and
199
+ * trailing commas.
200
+ */
201
+ export function parseDeclaration(text, file, reader = readerVersion(), options = {}) {
202
+ const parsed = parseJsonText(text, { jsonc: file.endsWith(".jsonc") });
203
+ if (!parsed.ok) {
204
+ throw new WorkspaceReadError("declaration-unparseable", parsed.message, { file, ...parsed.location });
205
+ }
206
+ const at = (pointer, key = false) => ({ file, ...parsed.locate(pointer, key) });
207
+ const raw = parsed.value;
208
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
209
+ throw new WorkspaceReadError("declaration-invalid", "the declaration must be a JSON object", at(""));
210
+ }
211
+ const obj = raw;
212
+ // The root's chant reads the declaration (ws-021). A pin to another chant
213
+ // comes before minReader and the schema: that chant may know fields this
214
+ // one doesn't.
215
+ const pin = options.rootChant ? pinnedChant(obj) : undefined;
216
+ if (pin && pin.version !== reader) {
217
+ throw new WorkspaceReadError("root-chant-required", `this declaration pins ${CHANT_PACKAGE} ${pin.version}, and this is chant ${reader}; the root's chant reads it, so install ${CHANT_PACKAGE}@${pin.version} at the workspace root`, at(`/pins/${pin.index}/version`));
218
+ }
219
+ // minReader first: a declaration written for a newer chant may use fields
220
+ // this one doesn't know, and "too old" is the true reason it can't read it.
221
+ if (typeof obj.minReader === "string" && SEMVER.test(obj.minReader) && compareVersions(reader, obj.minReader) < 0) {
222
+ throw new WorkspaceReadError("reader-too-old", `this declaration needs chant ${obj.minReader} or newer to read it, and this is chant ${reader}`, at("/minReader"));
223
+ }
224
+ const validate = validator();
225
+ if (!validate(raw)) {
226
+ const errors = (validate.errors ?? []).filter((e) => !SUMMARY_KEYWORDS.has(e.keyword));
227
+ // The deepest error first: it is the one closest to what needs fixing.
228
+ errors.sort((a, b) => b.instancePath.split("/").length - a.instancePath.split("/").length);
229
+ const first = errors[0] ?? validate.errors[0];
230
+ const isKey = first.keyword === "additionalProperties";
231
+ const pointer = isKey ? `${first.instancePath}/${pointerToken(String(first.params.additionalProperty))}` : first.instancePath;
232
+ const where = first.instancePath === "" ? "" : ` (at ${first.instancePath})`;
233
+ const more = errors.length > 1 ? `; ${errors.length - 1} more problem${errors.length > 2 ? "s" : ""} after this one` : "";
234
+ throw new WorkspaceReadError("declaration-invalid", `${explain(first, valueAt(raw, first.instancePath))}${where}${more}`, at(pointer, isKey));
235
+ }
236
+ const entries = obj.members.map((e, i) => {
237
+ const pointer = `/members/${i}`;
238
+ const suppress = (e.suppress ?? []).map((x) => ({ check: x.check, because: x.because }));
239
+ if (e.kind === EXAMPLES_KIND) {
240
+ const glob = e.glob;
241
+ return {
242
+ type: "group",
243
+ name: e.name,
244
+ kind: EXAMPLES_KIND,
245
+ globs: typeof glob === "string" ? [glob] : [...glob],
246
+ suppress,
247
+ pointer,
248
+ globLocation: parsed.locate(`${pointer}/glob`),
249
+ };
250
+ }
251
+ const roles = (e.roles ?? []).map((r) => typeof r === "string" ? { name: r, path: null } : { name: r.name, path: r.path ?? null });
252
+ const generated = (e.generated ?? []).map((g, j) => ({
253
+ path: g.path,
254
+ generator: g.generator,
255
+ sources: [...(g.sources ?? [])],
256
+ handWritten: g.handWritten ? { because: g.handWritten.because } : null,
257
+ pointer: `${pointer}/generated/${j}`,
258
+ }));
259
+ const links = (e.links ?? []).map((l, j) => ({
260
+ member: l.member,
261
+ output: l.output,
262
+ kind: l.kind ?? null,
263
+ protocol: l.protocol ?? null,
264
+ pointer: `${pointer}/links/${j}`,
265
+ }));
266
+ const records = recordKindsOf(e.records, e.dir, e.name, `${pointer}/records`);
267
+ const diagrams = diagramsOf(e.diagrams, e.name, `${pointer}/diagrams`);
268
+ const box = boxOf(e.box, `${pointer}/box`);
269
+ return {
270
+ type: "member",
271
+ name: e.name,
272
+ dir: e.dir,
273
+ kind: e.kind,
274
+ roles,
275
+ generated,
276
+ outputs: e.outputs === undefined ? null : [...e.outputs],
277
+ fields: e.fields === undefined ? null : structuredClone(e.fields),
278
+ links,
279
+ records,
280
+ diagrams,
281
+ box,
282
+ upstream: e.upstream ?? null,
283
+ because: e.because ?? null,
284
+ travel: e.travel === true,
285
+ suppress,
286
+ pointer,
287
+ };
288
+ });
289
+ // Names are unique across members and groups.
290
+ const names = new Map();
291
+ for (const e of entries) {
292
+ const first = names.get(e.name);
293
+ if (first) {
294
+ throw new WorkspaceReadError("declaration-invalid", `the name ${JSON.stringify(e.name)} is already used by the entry at ${first.pointer}`, at(`${e.pointer}/name`));
295
+ }
296
+ names.set(e.name, e);
297
+ }
298
+ // Placement (#2524 D2): one root member at most, no two members in one
299
+ // directory, and only the root member contains other members.
300
+ const members = entries.filter((e) => e.type === "member");
301
+ const byDir = new Map();
302
+ for (const m of members) {
303
+ const other = byDir.get(m.dir);
304
+ if (other) {
305
+ throw new WorkspaceReadError("placement-invalid", `member ${m.name} has the same directory as member ${other.name} (${m.dir})`, at(`${m.pointer}/dir`));
306
+ }
307
+ byDir.set(m.dir, m);
308
+ }
309
+ for (const m of members) {
310
+ const outer = members.find((o) => o !== m && o.dir !== "." && isInside(m.dir, o.dir));
311
+ if (outer) {
312
+ throw new WorkspaceReadError("placement-invalid", `member ${m.name} (${m.dir}) sits inside member ${outer.name} (${outer.dir}); only the root member "." may contain other members`, at(`${m.pointer}/dir`));
313
+ }
314
+ }
315
+ // A member lists a generated file once, and never one inside another
316
+ // member's directory: that member owns the file and lists it (#2541).
317
+ for (const m of members) {
318
+ const seen = new Map();
319
+ for (const g of m.generated) {
320
+ const first = seen.get(g.path);
321
+ if (first) {
322
+ throw new WorkspaceReadError("declaration-invalid", `member ${m.name} lists the generated file ${g.path} twice; the first is at ${first.pointer}`, at(`${g.pointer}/path`));
323
+ }
324
+ seen.set(g.path, g);
325
+ const full = m.dir === "." ? g.path : `${m.dir}/${g.path}`;
326
+ const inner = members.find((o) => o !== m && o.dir !== "." && isInside(o.dir, m.dir) && isInside(full, o.dir));
327
+ if (inner) {
328
+ throw new WorkspaceReadError("placement-invalid", `member ${m.name} lists the generated file ${g.path}, which sits inside member ${inner.name} (${inner.dir}); list it there`, at(`${g.pointer}/path`));
329
+ }
330
+ }
331
+ }
332
+ // A kind file is declared once, and a name the declaration gives a kind is
333
+ // given once (#2680): readers key the kinds by both.
334
+ const ownRecords = recordKindsOf(obj.records, ".", null, "/records");
335
+ const byPath = new Map();
336
+ const byName = new Map();
337
+ for (const r of [...ownRecords, ...members.flatMap((m) => m.records)]) {
338
+ const first = byPath.get(r.path);
339
+ if (first)
340
+ throw new WorkspaceReadError("declaration-invalid", `the record kind ${r.path} is already declared at ${first.pointer}`, at(`${r.pointer}/kind`));
341
+ byPath.set(r.path, r);
342
+ if (r.name === null)
343
+ continue;
344
+ const named = byName.get(r.name);
345
+ if (named)
346
+ throw new WorkspaceReadError("declaration-invalid", `the record kind name ${JSON.stringify(r.name)} is already given at ${named.pointer}`, at(`${r.pointer}/name`));
347
+ byName.set(r.name, r);
348
+ }
349
+ // A box names each capability once (#2726): a broker reads its scope by name.
350
+ for (const m of members) {
351
+ const seen = new Map();
352
+ for (const c of m.box?.capabilities ?? []) {
353
+ const first = seen.get(c.name);
354
+ if (first)
355
+ throw new WorkspaceReadError("declaration-invalid", `member ${m.name}'s box lists the capability ${c.name} twice; the first is at ${first.pointer}`, at(`${c.pointer}/name`));
356
+ seen.set(c.name, c);
357
+ }
358
+ // Its services name each other only within the block, without a cycle (#2880).
359
+ const problem = m.box ? boxServicesProblem(m.name, m.box.services) : null;
360
+ if (problem)
361
+ throw new WorkspaceReadError("declaration-invalid", problem.message, at(problem.pointer));
362
+ }
363
+ // One factory, building and naming declared members (#3146).
364
+ const factory = factoryProblem(members);
365
+ if (factory)
366
+ throw new WorkspaceReadError("declaration-invalid", factory.message, at(factory.pointer));
367
+ // One replicate policy (#3172): the checkout is the whole repository's, so one remote takes its work in progress.
368
+ const replicating = members.filter((m) => m.box?.replicate);
369
+ if (replicating.length > 1) {
370
+ throw new WorkspaceReadError("declaration-invalid", `members ${replicating[0].name} and ${replicating[1].name} both declare replicate in their box block; a checkout's work in progress goes to one remote, so a workspace has one replicate policy`, at(replicating[1].box.replicate.pointer));
371
+ }
372
+ // A diagram name is given once across the declaration (#2764): a reader keys diagrams by name.
373
+ const ownDiagrams = diagramsOf(obj.diagrams, null, "/diagrams");
374
+ const byDiagramName = new Map();
375
+ for (const d of [...ownDiagrams, ...members.flatMap((m) => m.diagrams)]) {
376
+ const first = byDiagramName.get(d.name);
377
+ if (first) {
378
+ throw new WorkspaceReadError("declaration-invalid", `the diagram name ${JSON.stringify(d.name)} is already used by the diagram at ${first.pointer}`, at(`${d.pointer}/name`));
379
+ }
380
+ byDiagramName.set(d.name, d);
381
+ }
382
+ const hosts = hostsOf(obj, members, at);
383
+ const writeScope = writeScopeOf(obj.writeScope, members, at);
384
+ const agents = agentsOf(obj.agents, members, at);
385
+ const tierSession = factoryTierSessionProblem(members, agents);
386
+ if (tierSession)
387
+ throw new WorkspaceReadError("declaration-invalid", tierSession.message, at(tierSession.pointer));
388
+ const ci = ciOf(obj.ci, at);
389
+ const pins = (obj.pins ?? []).map((p) => ({
390
+ package: p.package ?? null,
391
+ version: p.version ?? null,
392
+ path: p.path ?? null,
393
+ integrity: p.integrity ?? null,
394
+ }));
395
+ const declaration = {
396
+ name: obj.name,
397
+ schema: obj.schema,
398
+ minReader: obj.minReader ?? null,
399
+ entries,
400
+ members,
401
+ groups: entries.filter((e) => e.type === "group"),
402
+ pins,
403
+ checks: { ...(obj.checks ?? {}) },
404
+ quorum: typeof obj.quorum === "number" ? obj.quorum : null,
405
+ records: ownRecords,
406
+ diagrams: ownDiagrams,
407
+ hosts,
408
+ changes: changesOf(obj.changes),
409
+ writeScope,
410
+ agents,
411
+ identity: identityOf(obj.identity),
412
+ ci,
413
+ file,
414
+ };
415
+ written.set(declaration, raw);
416
+ return declaration;
417
+ }
418
+ /** Each parsed declaration's JSON as written, for its x- keys (#3595). */
419
+ const written = new WeakMap();
420
+ /**
421
+ * The `x-` keys of the object at `pointer` in the declaration as written
422
+ * (#3595), in file order: what a reader of `status --json` or `ls --json`
423
+ * gets back on the object the declaration holds them on. Empty when the
424
+ * pointer names no object, and for a declaration not read through
425
+ * {@link parseDeclaration}.
426
+ */
427
+ export function extensionsAt(declaration, pointer) {
428
+ const value = valueAt(written.get(declaration), pointer);
429
+ if (value === null || typeof value !== "object" || Array.isArray(value))
430
+ return {};
431
+ return Object.fromEntries(Object.entries(value).filter(([k]) => k.startsWith("x-")));
432
+ }
433
+ /**
434
+ * The `writeScope` block, already validated, with the rule the schema can't
435
+ * say (#2548): a member it names is a declared member. Its keys are kept in
436
+ * file order: the core classes and any domain class (#3080).
437
+ */
438
+ function writeScopeOf(raw, members, at) {
439
+ if (raw === undefined)
440
+ return null;
441
+ const block = raw;
442
+ const out = {};
443
+ for (const [cls, entry] of Object.entries(block)) {
444
+ const pointer = `/writeScope/${cls}`;
445
+ const list = entry.members === undefined || entry.members === "*" ? null : [...entry.members];
446
+ for (const [i, name] of (list ?? []).entries()) {
447
+ if (!members.some((m) => m.name === name)) {
448
+ throw new WorkspaceReadError("declaration-invalid", `writeScope.${cls} names the member ${JSON.stringify(name)}, which the declaration does not declare; declared members: ${members.map((m) => m.name).join(", ") || "none"}`, at(`${pointer}/members/${i}`));
449
+ }
450
+ }
451
+ const records = entry.records === undefined ? null : Object.fromEntries(Object.entries(entry.records).map(([k, v]) => [k, [...v]]));
452
+ const guarded = (entry.protected ?? []).map((p) => (typeof p === "string" ? { path: p, except: [] } : { path: p.path, except: [...(p.except ?? [])] }));
453
+ out[cls] = { members: list, records, protected: guarded, pointer };
454
+ }
455
+ return out;
456
+ }
457
+ /**
458
+ * The `agents` list, already validated, with the rules the schema can't say
459
+ * (#2548, ws-101): names are unique, every member a session names is a
460
+ * declared member, and a principal is listed by one session at most.
461
+ */
462
+ /** The `identity` block, already validated by the schema (#3163). */
463
+ function identityOf(raw) {
464
+ if (raw === undefined)
465
+ return null;
466
+ const block = raw;
467
+ const gates = {};
468
+ for (const [gate, entry] of Object.entries(block.gates ?? {})) {
469
+ gates[gate] = { gate, class: entry.class ?? null, pointer: `/identity/gates/${gate.replace(/~/g, "~0").replace(/\//g, "~1")}` };
470
+ }
471
+ return { attribution: block.attribution ?? "any", gates };
472
+ }
473
+ /**
474
+ * The `ci` block, already validated by the schema, with its defaults and the
475
+ * rule the schema can't say (#3573): every phase `require` names is declared.
476
+ */
477
+ function ciOf(raw, at) {
478
+ if (raw === undefined)
479
+ return null;
480
+ const block = raw;
481
+ if (block.green === undefined)
482
+ return { green: null };
483
+ const g = block.green;
484
+ const phases = Object.entries(g.phases).map(([name, p]) => ({
485
+ name,
486
+ runs: [...(Array.isArray(p) ? p : p.runs)],
487
+ skipped: Array.isArray(p) ? "fail" : (p.skipped ?? "fail"),
488
+ pointer: `/ci/green/phases/${pointerToken(name)}`,
489
+ }));
490
+ for (const [i, name] of g.require.entries()) {
491
+ if (phases.some((p) => p.name === name))
492
+ continue;
493
+ throw new WorkspaceReadError("declaration-invalid", `ci.green.require names the phase ${JSON.stringify(name)}, which ci.green.phases does not declare; declared phases: ${phases.map((p) => p.name).join(", ")}`, at(`/ci/green/require/${i}`));
494
+ }
495
+ return { green: { branch: g.branch, window: g.window ?? DEFAULT_CI_WINDOW, phases, require: [...g.require], pointer: "/ci/green" } };
496
+ }
497
+ function agentsOf(raw, members, at) {
498
+ const agents = (raw ?? []).map((a, i) => {
499
+ // The schema requires exactly one of member and members (ws-101).
500
+ const bound = a.members !== undefined ? [...a.members] : [a.member];
501
+ return {
502
+ name: a.name,
503
+ members: bound,
504
+ member: bound[0],
505
+ principals: [...(a.principals ?? [])],
506
+ pointer: `/agents/${i}`,
507
+ listed: a.members !== undefined,
508
+ };
509
+ });
510
+ const byName = new Map();
511
+ const byPrincipal = new Map();
512
+ for (const { listed, ...a } of agents) {
513
+ const first = byName.get(a.name);
514
+ if (first)
515
+ throw new WorkspaceReadError("declaration-invalid", `the agent name ${JSON.stringify(a.name)} is already used by the agent at ${first.pointer}`, at(`${a.pointer}/name`));
516
+ byName.set(a.name, a);
517
+ for (const [i, name] of a.members.entries()) {
518
+ if (members.some((m) => m.name === name))
519
+ continue;
520
+ throw new WorkspaceReadError("declaration-invalid", `agent ${a.name} is bound to ${JSON.stringify(name)}, which is not a declared member; an agent session is bound to members, not an example group`, at(listed ? `${a.pointer}/members/${i}` : `${a.pointer}/member`));
521
+ }
522
+ for (const [i, p] of a.principals.entries()) {
523
+ const other = byPrincipal.get(p);
524
+ if (other)
525
+ throw new WorkspaceReadError("declaration-invalid", `the principal ${JSON.stringify(p)} is already listed by agent ${other.name}`, at(`${a.pointer}/principals/${i}`));
526
+ byPrincipal.set(p, a);
527
+ }
528
+ }
529
+ return [...byName.values()];
530
+ }
531
+ /** The `changes` block, already validated, with its defaults (#2773). */
532
+ function changesOf(block) {
533
+ if (block === undefined)
534
+ return null;
535
+ return { severity: block.severity ?? "warn", ignore: [...(block.ignore ?? [])] };
536
+ }
537
+ /** The `records` list at `pointer`, already validated, with each kind file's path from the workspace root. */
538
+ function recordKindsOf(raw, dir, member, pointer) {
539
+ return (raw ?? []).map((r, i) => ({
540
+ kind: r.kind,
541
+ path: dir === "." ? r.kind : `${dir}/${r.kind}`,
542
+ name: r.name ?? null,
543
+ member,
544
+ pointer: `${pointer}/${i}`,
545
+ }));
546
+ }
547
+ /**
548
+ * The `diagrams` list at `pointer`, already validated. `source` and `render`
549
+ * are workspace-root-relative as written: unlike a generated file or a
550
+ * record kind, a diagram's files need not sit inside the declaring member's
551
+ * directory, so there is no member-relative form to resolve (#2764).
552
+ */
553
+ function diagramsOf(raw, member, pointer) {
554
+ return (raw ?? []).map((d, i) => ({
555
+ name: d.name,
556
+ title: d.title,
557
+ source: d.source ?? null,
558
+ render: d.render ?? null,
559
+ renderer: { tool: d.renderer.tool, version: d.renderer.version, args: [...(d.renderer.args ?? [])] },
560
+ sourceHash: d.sourceHash ?? null,
561
+ member,
562
+ pointer: `${pointer}/${i}`,
563
+ }));
564
+ }
565
+ /** The `box` block at `pointer`, already validated, or null when there is none (#2726, #2727). */
566
+ function boxOf(raw, pointer) {
567
+ if (raw === undefined)
568
+ return null;
569
+ const b = raw;
570
+ const f = b.factory;
571
+ const l = b.listing;
572
+ const r = b.replicate;
573
+ return {
574
+ capabilities: (b.capabilities ?? []).map((c, i) => ({ name: c.name, broker: c.broker ?? null, scope: [...(c.scope ?? [])], pointer: `${pointer}/capabilities/${i}` })),
575
+ // The schema requires host and slot together, and host for ports, state and cookies.
576
+ isolation: b.host === undefined
577
+ ? null
578
+ : { host: b.host, slot: b.slot, ports: { ...(b.ports ?? {}) }, state: { ...(b.state ?? {}) }, cookies: [...(b.cookies ?? [])] },
579
+ intent: b.intent ?? null,
580
+ services: (b.services ?? []).map((s, i) => ({
581
+ name: s.name,
582
+ cmd: s.cmd,
583
+ needs: [...(s.needs ?? [])],
584
+ httpPort: s.httpPort ?? null,
585
+ duration: s.duration ?? null,
586
+ health: s.health ?? null,
587
+ optional: s.optional ?? false,
588
+ pointer: `${pointer}/services/${i}`,
589
+ })),
590
+ factory: f === undefined
591
+ ? null
592
+ : {
593
+ builds: [...f.builds],
594
+ check: f.check === undefined ? null : typeof f.check === "string" ? { run: f.check, kind: "test" } : { run: f.check.run, kind: f.check.kind ?? "test" },
595
+ checks: f.checks ?? null,
596
+ builders: f.builders ?? null,
597
+ tiers: (f.tiers ?? []).map((t) => ({ tier: t.tier, agent: t.agent, kinds: t.kinds === undefined ? null : [...t.kinds], session: t.session ?? null })),
598
+ publish: f.publish === undefined
599
+ ? null
600
+ : {
601
+ forge: f.publish.forge ?? "github",
602
+ repo: f.publish.repo,
603
+ base: f.publish.base ?? null,
604
+ branchPrefix: f.publish.branchPrefix ?? DEFAULT_PUBLISH_BRANCH_PREFIX,
605
+ head: f.publish.head ?? null,
606
+ },
607
+ pointer: `${pointer}/factory`,
608
+ },
609
+ listing: l === undefined ? null : { published: l.published ?? true, title: l.title ?? "", line: l.line ?? "", cover: l.cover ?? null },
610
+ publisher: b.publisher ?? null,
611
+ ship: b.ship === undefined
612
+ ? null
613
+ : {
614
+ op: b.ship.op,
615
+ gate: b.ship.gate ?? DEFAULT_SHIP_GATE,
616
+ env: b.ship.env ?? DEFAULT_SHIP_ENV,
617
+ bookkeeping: (b.ship.bookkeeping ?? []).map((p) => p.replace(/^\.\//, "").replace(/\/+$/, "")),
618
+ pointer: `${pointer}/ship`,
619
+ },
620
+ replicate: r === undefined
621
+ ? null
622
+ : {
623
+ remote: r.remote ?? DEFAULT_REPLICATE_REMOTE,
624
+ // In the order the closed lists give, so a reader compares them without sorting.
625
+ refs: REPLICATE_REF_CLASSES.filter((c) => (r.refs ?? REPLICATE_REF_CLASSES).includes(c)),
626
+ on: REPLICATE_TRIGGERS.filter((t) => (r.on ?? REPLICATE_TRIGGERS).includes(t)),
627
+ every: r.every ?? null,
628
+ pointer: `${pointer}/replicate`,
629
+ },
630
+ pointer,
631
+ };
632
+ }
633
+ /**
634
+ * The rules the schema can't say about the factories (#3146, ws-077): at most
635
+ * one box block declares one, and the members its builds and builders name
636
+ * are declared members.
637
+ */
638
+ function factoryProblem(members) {
639
+ const declaring = members.filter((m) => m.box?.factory);
640
+ if (declaring.length > 1) {
641
+ return {
642
+ message: `members ${declaring[0].name} and ${declaring[1].name} both declare a factory in their box block; a workspace has one factory, so an orchestrator reads one`,
643
+ pointer: declaring[1].box.factory.pointer,
644
+ };
645
+ }
646
+ const factory = declaring[0]?.box?.factory;
647
+ if (!factory)
648
+ return null;
649
+ const known = () => members.map((m) => m.name).join(", ");
650
+ const j = factory.builds.findIndex((name) => !members.some((m) => m.name === name));
651
+ if (j >= 0) {
652
+ return { message: `the factory builds ${JSON.stringify(factory.builds[j])}, which is not a declared member; declared members: ${known()}`, pointer: `${factory.pointer}/builds/${j}` };
653
+ }
654
+ if (factory.builders !== null && !members.some((m) => m.name === factory.builders)) {
655
+ return { message: `the factory's builders names ${JSON.stringify(factory.builders)}, which is not a declared member; declared members: ${known()}`, pointer: `${factory.pointer}/builders` };
656
+ }
657
+ // Builder tiers (#3152): their agents are the builders member's, and one entry answers each tier and kind.
658
+ if (factory.tiers.length > 0 && factory.builders === null) {
659
+ return { message: "the factory declares tiers and no builders; tiers name agents the builders member declares, so name it", pointer: `${factory.pointer}/tiers` };
660
+ }
661
+ const answered = new Map();
662
+ for (const [i, t] of factory.tiers.entries()) {
663
+ for (const kind of t.kinds ?? [null]) {
664
+ const key = `${t.tier}\0${kind ?? ""}`;
665
+ const first = answered.get(key);
666
+ if (first !== undefined) {
667
+ const which = kind === null ? "with no kinds" : `for kind ${kind}`;
668
+ return { message: `tiers/${first} and tiers/${i} both name a builder at tier ${t.tier} ${which}; a tier has one builder per kind, so one entry answers it`, pointer: `${factory.pointer}/tiers/${i}` };
669
+ }
670
+ answered.set(key, i);
671
+ }
672
+ }
673
+ return null;
674
+ }
675
+ /** The rule the schema can't say about the factory's tiers once the sessions are read (#3152): a session is a declared agent session. */
676
+ function factoryTierSessionProblem(members, agents) {
677
+ const factory = members.find((m) => m.box?.factory)?.box?.factory;
678
+ if (!factory)
679
+ return null;
680
+ for (const [i, t] of factory.tiers.entries()) {
681
+ if (t.session !== null && !agents.some((a) => a.name === t.session)) {
682
+ const known = agents.map((a) => a.name).join(", ") || "none";
683
+ return { message: `tiers/${i} names the session ${JSON.stringify(t.session)}, which is not a declared agent session; declared sessions: ${known}`, pointer: `${factory.pointer}/tiers/${i}/session` };
684
+ }
685
+ }
686
+ return null;
687
+ }
688
+ /**
689
+ * The rules the schema can't say about a box's services (#2880), as a
690
+ * message and the pointer to show, or null when they hold: each name is
691
+ * given once, every `needs` names a service of the same block, the `needs`
692
+ * form no cycle, and at most one service sets `httpPort`. The fly lexicon
693
+ * checks a list it is handed inline with the same rules.
694
+ */
695
+ export function boxServicesProblem(member, services) {
696
+ const byName = new Map();
697
+ for (const s of services) {
698
+ const first = byName.get(s.name);
699
+ if (first)
700
+ return { message: `member ${member}'s box declares the service ${s.name} twice; the first is at ${first.pointer}`, pointer: `${s.pointer}/name` };
701
+ byName.set(s.name, s);
702
+ }
703
+ let routed;
704
+ for (const s of services) {
705
+ if (s.httpPort === null)
706
+ continue;
707
+ if (routed) {
708
+ return {
709
+ message: `member ${member}'s box gives both ${routed.name} (port ${routed.httpPort}) and ${s.name} (port ${s.httpPort}) an httpPort, and the supervisor routes the sprite's URL to one service`,
710
+ pointer: `${s.pointer}/httpPort`,
711
+ };
712
+ }
713
+ routed = s;
714
+ }
715
+ for (const s of services) {
716
+ const j = s.needs.findIndex((n) => !byName.has(n));
717
+ if (j >= 0) {
718
+ const known = services.map((x) => x.name).join(", ");
719
+ return { message: `member ${member}'s box service ${s.name} needs ${JSON.stringify(s.needs[j])}, which the block does not declare; declared services: ${known}`, pointer: `${s.pointer}/needs/${j}` };
720
+ }
721
+ }
722
+ const cycle = serviceCycle(services);
723
+ if (cycle) {
724
+ const s = byName.get(cycle[0]);
725
+ return { message: `member ${member}'s box services need each other in a cycle: ${cycle.join(" -> ")}`, pointer: `${s.pointer}/needs` };
726
+ }
727
+ return null;
728
+ }
729
+ /** The first cycle the services' `needs` form, as names ending where it starts, or null. */
730
+ function serviceCycle(services) {
731
+ const byName = new Map(services.map((s) => [s.name, s]));
732
+ const state = new Map();
733
+ const visit = (name, trail) => {
734
+ const st = state.get(name);
735
+ if (st === "done")
736
+ return null;
737
+ if (st === "visiting")
738
+ return [...trail.slice(trail.indexOf(name)), name];
739
+ state.set(name, "visiting");
740
+ for (const dep of byName.get(name)?.needs ?? []) {
741
+ const found = visit(dep, [...trail, name]);
742
+ if (found)
743
+ return found;
744
+ }
745
+ state.set(name, "done");
746
+ return null;
747
+ };
748
+ for (const s of services) {
749
+ const found = visit(s.name, []);
750
+ if (found)
751
+ return found;
752
+ }
753
+ return null;
754
+ }
755
+ /**
756
+ * The hosts, already validated, with the rules the schema can't say (#2727):
757
+ * host names are unique, a box's host is declared, its slot's block fits the
758
+ * host's range and its offsets fit the block. What two boxes resolve to is
759
+ * `chant workspace check`'s question (WSP123), not a read error.
760
+ */
761
+ function hostsOf(obj, members, at) {
762
+ const hosts = (obj.hosts ?? []).map((h, i) => ({
763
+ name: h.name,
764
+ ports: { ...h.ports },
765
+ stateRoot: h.stateRoot ?? null,
766
+ pointer: `/hosts/${i}`,
767
+ }));
768
+ const invalid = (message, pointer) => new WorkspaceReadError("declaration-invalid", message, at(pointer));
769
+ const byName = new Map();
770
+ for (const h of hosts) {
771
+ const first = byName.get(h.name);
772
+ if (first)
773
+ throw invalid(`the host name ${JSON.stringify(h.name)} is already used by the host at ${first.pointer}`, `${h.pointer}/name`);
774
+ byName.set(h.name, h);
775
+ if (h.ports.from > h.ports.to)
776
+ throw invalid(`host ${h.name}'s port range starts at ${h.ports.from}, after its end ${h.ports.to}`, `${h.pointer}/ports`);
777
+ }
778
+ for (const m of members) {
779
+ const iso = m.box?.isolation;
780
+ if (!iso)
781
+ continue;
782
+ const box = m.box.pointer;
783
+ const host = byName.get(iso.host);
784
+ if (!host) {
785
+ const known = hosts.map((h) => h.name).join(", ") || "none are declared";
786
+ throw invalid(`member ${m.name}'s box names the host ${JSON.stringify(iso.host)}, which hosts does not declare; declared hosts: ${known}`, `${box}/host`);
787
+ }
788
+ const { from, to, perBox } = host.ports;
789
+ const last = from + (iso.slot + 1) * perBox - 1;
790
+ if (last > to) {
791
+ const slots = Math.floor((to - from + 1) / perBox);
792
+ throw invalid(`member ${m.name}'s box has slot ${iso.slot} on host ${host.name}, which needs ports ${from + iso.slot * perBox} to ${last}, past the end of the host's range (${to}); the range holds ${slots} slot${slots === 1 ? "" : "s"}`, `${box}/slot`);
793
+ }
794
+ for (const [port, offset] of Object.entries(iso.ports)) {
795
+ if (offset >= perBox) {
796
+ throw invalid(`member ${m.name}'s box gives port ${port} offset ${offset}, and host ${host.name} gives each box ${perBox} port${perBox === 1 ? "" : "s"} (offsets 0 to ${perBox - 1})`, `${box}/ports/${pointerToken(port)}`);
797
+ }
798
+ }
799
+ }
800
+ return hosts;
801
+ }
802
+ /**
803
+ * Every record kind the declaration names (#2680), in the order readers use
804
+ * them: the workspace's own first, then each member's, members in file order
805
+ * and each list in its own order.
806
+ */
807
+ export function declaredRecordKinds(declaration) {
808
+ return [...declaration.records, ...declaration.members.flatMap((m) => m.records)];
809
+ }
810
+ /**
811
+ * Every diagram artifact the declaration names (#2764), in the order readers
812
+ * use them: the workspace's own first, then each member's, members in file
813
+ * order and each list in its own order.
814
+ */
815
+ export function declaredDiagrams(declaration) {
816
+ return [...declaration.diagrams, ...declaration.members.flatMap((m) => m.diagrams)];
817
+ }
818
+ /** Whether `path` is `dir` or sits under it. Both are tree-relative; `"."` is the root. */
819
+ export function isInside(path, dir) {
820
+ if (dir === ".")
821
+ return true;
822
+ return path === dir || path.startsWith(`${dir}/`);
823
+ }
824
+ // ── Reading from a tree ──────────────────────────────────────────────────────
825
+ /**
826
+ * Read the declaration in directory `dir` of `tree`. Throws
827
+ * `declaration-missing` when neither name is there and
828
+ * `declaration-ambiguous` when both are.
829
+ */
830
+ export function readDeclaration(tree, dir = "", options = {}) {
831
+ const present = DECLARATION_FILES.map((name) => joinPath(dir, name)).filter((p) => tree.stat(p) === "file");
832
+ if (present.length === 0) {
833
+ throw new WorkspaceReadError("declaration-missing", `no ${DECLARATION_FILES.join(" or ")} in ${dir || "the workspace root"}${tree.label}`);
834
+ }
835
+ if (present.length > 1) {
836
+ throw new WorkspaceReadError("declaration-ambiguous", `both ${present.join(" and ")} exist${tree.label}; keep one of them`, { file: present[1], line: 1, column: 1 });
837
+ }
838
+ return parseDeclaration(tree.read(present[0]), present[0], readerVersion(), options);
839
+ }
840
+ /**
841
+ * Walk up from `start` (tree-relative) to the nearest directory holding a
842
+ * declaration, within `tree`. The tree's root is the git root, so this is
843
+ * `findWorkspaceRoot` for a revision. Returns the directory, or undefined.
844
+ */
845
+ export function findDeclarationDir(tree, start) {
846
+ for (let dir = start;; dir = dir.includes("/") ? dir.slice(0, dir.lastIndexOf("/")) : "") {
847
+ if (DECLARATION_FILES.some((name) => tree.stat(joinPath(dir, name)) === "file"))
848
+ return dir;
849
+ if (dir === "")
850
+ return undefined;
851
+ }
852
+ }
853
+ /**
854
+ * Expand every group's globs in `tree` (rooted at the workspace root) and
855
+ * check where the matches sit (ws-051): a match is never a member's directory
856
+ * and never contains one, it doesn't sit inside a nested workspace, and no
857
+ * two groups claim the same directory. A match may sit inside any other
858
+ * member's directory; that member leaves it to the group.
859
+ */
860
+ export function resolveGroups(declaration, tree) {
861
+ const at = (g) => ({ file: declaration.file, ...g.globLocation });
862
+ const claimed = new Map();
863
+ const resolved = [];
864
+ for (const group of declaration.groups) {
865
+ const dirs = [...new Set(group.globs.flatMap((g) => expandGlob(tree, g)))].sort();
866
+ const matches = [];
867
+ const skipped = [];
868
+ for (const dir of dirs) {
869
+ if (!holdsChantProject(tree, dir)) {
870
+ skipped.push(dir);
871
+ continue;
872
+ }
873
+ const clash = (message) => new WorkspaceReadError("placement-invalid", `group ${group.name} matches ${dir}, ${message}`, at(group));
874
+ for (const m of declaration.members) {
875
+ if (m.dir === ".")
876
+ continue;
877
+ if (m.dir === dir)
878
+ throw clash(`which is member ${m.name}'s directory; a match is never a member`);
879
+ if (isInside(m.dir, dir))
880
+ throw clash(`which contains member ${m.name} (${m.dir})`);
881
+ if (m.kind === "workspace" && isInside(dir, m.dir)) {
882
+ throw clash(`which sits inside the nested workspace ${m.name}; that workspace declares its own examples`);
883
+ }
884
+ }
885
+ const other = claimed.get(dir);
886
+ if (other)
887
+ throw clash(`which group ${other.name} also matches`);
888
+ claimed.set(dir, group);
889
+ matches.push(dir);
890
+ }
891
+ resolved.push({ group, matches, skipped });
892
+ }
893
+ return resolved;
894
+ }
895
+ // ── Ownership ────────────────────────────────────────────────────────────────
896
+ /**
897
+ * Which entry owns `path` (relative to the workspace root): the group whose
898
+ * match holds it, else the member with the deepest directory holding it, else
899
+ * none. A group match wins over the member whose directory it sits in
900
+ * (ws-051). Ledgers (#2538), telemetry attribution (#2558) and the root
901
+ * project's discovery (#2537) all ask this question.
902
+ */
903
+ export function ownerOf(declaration, groups, path) {
904
+ for (const g of groups) {
905
+ const match = g.matches.find((m) => isInside(path, m));
906
+ if (match)
907
+ return { group: g.group, match };
908
+ }
909
+ let best;
910
+ for (const m of declaration.members) {
911
+ if (!isInside(path, m.dir))
912
+ continue;
913
+ if (!best || best.dir === "." || (m.dir !== "." && m.dir.length > best.dir.length))
914
+ best = m;
915
+ }
916
+ return best ? { member: best } : undefined;
917
+ }
918
+ /**
919
+ * The directories that leave the root project once the declaration exists
920
+ * (#2524 D0, D2): every member's directory but the root's, and every group
921
+ * match. The root project's build, lint, Op and audit discovery skip them
922
+ * (#2537); `chant workspace init` prints them before it writes.
923
+ */
924
+ export function rootExclusions(declaration, groups) {
925
+ const out = [];
926
+ for (const m of declaration.members)
927
+ if (m.dir !== ".")
928
+ out.push({ dir: m.dir, owner: m.name });
929
+ for (const g of groups) {
930
+ for (const dir of g.matches) {
931
+ // A match inside a member's directory already left with that member.
932
+ if (declaration.members.some((m) => m.dir !== "." && isInside(dir, m.dir)))
933
+ continue;
934
+ out.push({ dir, owner: g.group.name });
935
+ }
936
+ }
937
+ return out.sort((a, b) => (a.dir < b.dir ? -1 : a.dir > b.dir ? 1 : 0));
938
+ }