@intentius/chant 0.100.0 → 0.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (608) hide show
  1. package/dist/agents/checks.d.ts.map +1 -1
  2. package/dist/attrref.d.ts.map +1 -1
  3. package/dist/audit/discover.d.ts.map +1 -1
  4. package/dist/audit/nginx.d.ts.map +1 -1
  5. package/dist/audit/prior-art.d.ts +48 -0
  6. package/dist/audit/prior-art.d.ts.map +1 -1
  7. package/dist/behaviour-kinds.d.ts.map +1 -1
  8. package/dist/build.d.ts +6 -0
  9. package/dist/build.d.ts.map +1 -1
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/cli/build-options.d.ts +2 -0
  12. package/dist/cli/build-options.d.ts.map +1 -1
  13. package/dist/cli/commands/build.d.ts.map +1 -1
  14. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  15. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  16. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  17. package/dist/cli/commands/import.d.ts +8 -0
  18. package/dist/cli/commands/import.d.ts.map +1 -1
  19. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  20. package/dist/cli/commands/init.d.ts +19 -0
  21. package/dist/cli/commands/init.d.ts.map +1 -1
  22. package/dist/cli/commands/onboard.d.ts +9 -0
  23. package/dist/cli/commands/onboard.d.ts.map +1 -1
  24. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  25. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  26. package/dist/cli/handlers/dev.d.ts.map +1 -1
  27. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  28. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  29. package/dist/cli/handlers/misc.d.ts.map +1 -1
  30. package/dist/cli/handlers/operator.d.ts +9 -0
  31. package/dist/cli/handlers/operator.d.ts.map +1 -1
  32. package/dist/cli/handlers/run.d.ts.map +1 -1
  33. package/dist/cli/lsp/server.d.ts.map +1 -1
  34. package/dist/cli/main.d.ts.map +1 -1
  35. package/dist/cli/mcp/server.d.ts.map +1 -1
  36. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  37. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  38. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  39. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  40. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  41. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  42. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  43. package/dist/cli/mcp/workspace-tools.d.ts +9 -1
  44. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  45. package/dist/cli/registry.d.ts +33 -2
  46. package/dist/cli/registry.d.ts.map +1 -1
  47. package/dist/codegen/fetch.d.ts.map +1 -1
  48. package/dist/codegen/naming.d.ts.map +1 -1
  49. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  50. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  51. package/dist/codegen/registry.d.ts.map +1 -1
  52. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  53. package/dist/components/capability.d.ts.map +1 -1
  54. package/dist/components/driver.d.ts.map +1 -1
  55. package/dist/components/fan-out.d.ts.map +1 -1
  56. package/dist/components/starter-plugin.d.ts.map +1 -1
  57. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  58. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  59. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  60. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  61. package/dist/components/verbs/sign.d.ts.map +1 -1
  62. package/dist/components/verbs/verify.d.ts.map +1 -1
  63. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  64. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  65. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  66. package/dist/composite.d.ts.map +1 -1
  67. package/dist/config.d.ts +30 -7
  68. package/dist/config.d.ts.map +1 -1
  69. package/dist/declarable.d.ts +16 -0
  70. package/dist/declarable.d.ts.map +1 -1
  71. package/dist/discovery/cache.d.ts.map +1 -1
  72. package/dist/discovery/fold-import.d.ts +15 -5
  73. package/dist/discovery/fold-import.d.ts.map +1 -1
  74. package/dist/discovery/param-deps.d.ts +16 -0
  75. package/dist/discovery/param-deps.d.ts.map +1 -1
  76. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  77. package/dist/discovery/specifier-resolve.d.ts +37 -0
  78. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  79. package/dist/errors.d.ts.map +1 -1
  80. package/dist/fold/fold.d.ts +3 -1
  81. package/dist/fold/fold.d.ts.map +1 -1
  82. package/dist/graph-detail.d.ts.map +1 -1
  83. package/dist/graph-ir.d.ts.map +1 -1
  84. package/dist/graph-layout.d.ts.map +1 -1
  85. package/dist/import/base-parser.d.ts.map +1 -1
  86. package/dist/import/embedded.d.ts +7 -0
  87. package/dist/import/embedded.d.ts.map +1 -1
  88. package/dist/import/parser-options.d.ts +14 -0
  89. package/dist/import/parser-options.d.ts.map +1 -0
  90. package/dist/import/parser.d.ts +17 -0
  91. package/dist/import/parser.d.ts.map +1 -1
  92. package/dist/kubectl-context.d.ts.map +1 -1
  93. package/dist/lexicon-output.d.ts.map +1 -1
  94. package/dist/lexicon-schema.d.ts +3 -3
  95. package/dist/lexicon.d.ts +78 -3
  96. package/dist/lexicon.d.ts.map +1 -1
  97. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  98. package/dist/lifecycle/gate-ledger.d.ts +15 -0
  99. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  100. package/dist/lifecycle/git.d.ts.map +1 -1
  101. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  102. package/dist/lifecycle/observe.d.ts.map +1 -1
  103. package/dist/lifecycle/plan-digest.d.ts +26 -5
  104. package/dist/lifecycle/plan-digest.d.ts.map +1 -1
  105. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  106. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  107. package/dist/lifecycle/scenario.d.ts.map +1 -1
  108. package/dist/lifecycle/status.d.ts.map +1 -1
  109. package/dist/lifecycle/work-lease.d.ts +61 -2
  110. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  111. package/dist/lint/config.d.ts +4 -4
  112. package/dist/lint/engine.d.ts +6 -0
  113. package/dist/lint/engine.d.ts.map +1 -1
  114. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  115. package/dist/op/activities/activity-contracts.d.ts +12 -11
  116. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  117. package/dist/op/activities/apply.d.ts +79 -9
  118. package/dist/op/activities/apply.d.ts.map +1 -1
  119. package/dist/op/activities/decide.d.ts.map +1 -1
  120. package/dist/op/activities/index.d.ts +1 -1
  121. package/dist/op/activities/index.d.ts.map +1 -1
  122. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  123. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  124. package/dist/op/activities/propose-upgrade.d.ts +2 -0
  125. package/dist/op/activities/propose-upgrade.d.ts.map +1 -1
  126. package/dist/op/activity-contract.d.ts +1 -1
  127. package/dist/op/activity-failure.d.ts.map +1 -1
  128. package/dist/op/activity-profiles.d.ts.map +1 -1
  129. package/dist/op/builders.d.ts.map +1 -1
  130. package/dist/op/composites/apply-op.d.ts +12 -5
  131. package/dist/op/composites/apply-op.d.ts.map +1 -1
  132. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  133. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  134. package/dist/op/decide-backend.d.ts.map +1 -1
  135. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  136. package/dist/op/emulator-lifecycle.d.ts +21 -2
  137. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  138. package/dist/op/gate-approval.d.ts +5 -1
  139. package/dist/op/gate-approval.d.ts.map +1 -1
  140. package/dist/op/gate-wait.d.ts.map +1 -1
  141. package/dist/op/gate.d.ts +19 -3
  142. package/dist/op/gate.d.ts.map +1 -1
  143. package/dist/op/index.d.ts +3 -1
  144. package/dist/op/index.d.ts.map +1 -1
  145. package/dist/op/local-executor.d.ts +6 -0
  146. package/dist/op/local-executor.d.ts.map +1 -1
  147. package/dist/op/operator.d.ts.map +1 -1
  148. package/dist/op/run-context.d.ts +39 -0
  149. package/dist/op/run-context.d.ts.map +1 -0
  150. package/dist/op/run-live.d.ts.map +1 -1
  151. package/dist/op/runtimes/local.d.ts.map +1 -1
  152. package/dist/op/source-archive.d.ts.map +1 -1
  153. package/dist/op/steward-beside.d.ts.map +1 -1
  154. package/dist/op/steward-points.d.ts.map +1 -1
  155. package/dist/op/steward.d.ts.map +1 -1
  156. package/dist/op/types.d.ts +8 -3
  157. package/dist/op/types.d.ts.map +1 -1
  158. package/dist/op/work-lease-run.d.ts +24 -4
  159. package/dist/op/work-lease-run.d.ts.map +1 -1
  160. package/dist/project-root.d.ts.map +1 -1
  161. package/dist/provenance.d.ts +21 -0
  162. package/dist/provenance.d.ts.map +1 -1
  163. package/dist/pseudo-parameter.d.ts.map +1 -1
  164. package/dist/reconcile.d.ts.map +1 -1
  165. package/dist/secret-materialization.d.ts.map +1 -1
  166. package/dist/serializer.d.ts +8 -0
  167. package/dist/serializer.d.ts.map +1 -1
  168. package/dist/telemetry-attribution.d.ts +77 -0
  169. package/dist/telemetry-attribution.d.ts.map +1 -0
  170. package/dist/terraform/emit-source.d.ts.map +1 -1
  171. package/dist/terraform/parse.d.ts.map +1 -1
  172. package/dist/testing.d.ts.map +1 -1
  173. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  174. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  175. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  176. package/dist/workspace/agent-cli.d.ts +88 -0
  177. package/dist/workspace/agent-cli.d.ts.map +1 -0
  178. package/dist/workspace/box-factory.d.ts +73 -0
  179. package/dist/workspace/box-factory.d.ts.map +1 -0
  180. package/dist/workspace/changes-cli.d.ts.map +1 -1
  181. package/dist/workspace/changes.d.ts +8 -1
  182. package/dist/workspace/changes.d.ts.map +1 -1
  183. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  184. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  185. package/dist/workspace/checks/links.d.ts +1 -0
  186. package/dist/workspace/checks/links.d.ts.map +1 -1
  187. package/dist/workspace/checks/live.d.ts +40 -0
  188. package/dist/workspace/checks/live.d.ts.map +1 -0
  189. package/dist/workspace/checks.d.ts +26 -2
  190. package/dist/workspace/checks.d.ts.map +1 -1
  191. package/dist/workspace/compose-graph.d.ts +73 -0
  192. package/dist/workspace/compose-graph.d.ts.map +1 -1
  193. package/dist/workspace/conformance/index.d.ts +67 -6
  194. package/dist/workspace/conformance/index.d.ts.map +1 -1
  195. package/dist/workspace/conformance/vitest.d.ts +12 -3
  196. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  197. package/dist/workspace/conformance/writer.d.ts +368 -0
  198. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  199. package/dist/workspace/decide.d.ts +1 -1
  200. package/dist/workspace/decide.d.ts.map +1 -1
  201. package/dist/workspace/declaration.d.ts +119 -0
  202. package/dist/workspace/declaration.d.ts.map +1 -1
  203. package/dist/workspace/declaration.schema.json +368 -4
  204. package/dist/workspace/export-cli.d.ts +12 -0
  205. package/dist/workspace/export-cli.d.ts.map +1 -0
  206. package/dist/workspace/export.d.ts +145 -0
  207. package/dist/workspace/export.d.ts.map +1 -0
  208. package/dist/workspace/generated-files.d.ts.map +1 -1
  209. package/dist/workspace/graph-cache.d.ts.map +1 -1
  210. package/dist/workspace/graph-cli.d.ts +2 -0
  211. package/dist/workspace/graph-cli.d.ts.map +1 -1
  212. package/dist/workspace/identity.d.ts +111 -0
  213. package/dist/workspace/identity.d.ts.map +1 -0
  214. package/dist/workspace/import.d.ts +73 -0
  215. package/dist/workspace/import.d.ts.map +1 -0
  216. package/dist/workspace/intent-cli.d.ts +7 -4
  217. package/dist/workspace/intent-cli.d.ts.map +1 -1
  218. package/dist/workspace/intent-record.d.ts +8 -1
  219. package/dist/workspace/intent-record.d.ts.map +1 -1
  220. package/dist/workspace/intent.d.ts +149 -5
  221. package/dist/workspace/intent.d.ts.map +1 -1
  222. package/dist/workspace/kinds.d.ts +24 -6
  223. package/dist/workspace/kinds.d.ts.map +1 -1
  224. package/dist/workspace/lineage-adopt-cli.d.ts +15 -0
  225. package/dist/workspace/lineage-adopt-cli.d.ts.map +1 -0
  226. package/dist/workspace/lineage-adopt.d.ts +106 -0
  227. package/dist/workspace/lineage-adopt.d.ts.map +1 -0
  228. package/dist/workspace/lineage-check.d.ts +9 -2
  229. package/dist/workspace/lineage-check.d.ts.map +1 -1
  230. package/dist/workspace/lineage-cli.d.ts +6 -1
  231. package/dist/workspace/lineage-cli.d.ts.map +1 -1
  232. package/dist/workspace/lineage-hash-index.d.ts +110 -0
  233. package/dist/workspace/lineage-hash-index.d.ts.map +1 -0
  234. package/dist/workspace/lineage-init.d.ts +10 -0
  235. package/dist/workspace/lineage-init.d.ts.map +1 -1
  236. package/dist/workspace/lineage-lock.d.ts +149 -2
  237. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  238. package/dist/workspace/lineage-migrations.d.ts +15 -3
  239. package/dist/workspace/lineage-migrations.d.ts.map +1 -1
  240. package/dist/workspace/lineage-provenance.d.ts +18 -0
  241. package/dist/workspace/lineage-provenance.d.ts.map +1 -0
  242. package/dist/workspace/lineage-upgrade-cli.d.ts +2 -0
  243. package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -1
  244. package/dist/workspace/lineage-upgrade.d.ts +30 -1
  245. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  246. package/dist/workspace/lineage-versions.d.ts +116 -0
  247. package/dist/workspace/lineage-versions.d.ts.map +1 -0
  248. package/dist/workspace/links.d.ts +31 -5
  249. package/dist/workspace/links.d.ts.map +1 -1
  250. package/dist/workspace/ls-generated.d.ts +37 -0
  251. package/dist/workspace/ls-generated.d.ts.map +1 -0
  252. package/dist/workspace/ls.d.ts +4 -0
  253. package/dist/workspace/ls.d.ts.map +1 -1
  254. package/dist/workspace/member-commands.d.ts.map +1 -1
  255. package/dist/workspace/nested-graph.d.ts +56 -0
  256. package/dist/workspace/nested-graph.d.ts.map +1 -0
  257. package/dist/workspace/nesting.d.ts +21 -0
  258. package/dist/workspace/nesting.d.ts.map +1 -0
  259. package/dist/workspace/pin-cli.d.ts +10 -0
  260. package/dist/workspace/pin-cli.d.ts.map +1 -0
  261. package/dist/workspace/pin-integrity.d.ts +51 -0
  262. package/dist/workspace/pin-integrity.d.ts.map +1 -0
  263. package/dist/workspace/points.d.ts.map +1 -1
  264. package/dist/workspace/principal-classes.d.ts +114 -0
  265. package/dist/workspace/principal-classes.d.ts.map +1 -0
  266. package/dist/workspace/reason-codes.d.ts +47 -3
  267. package/dist/workspace/reason-codes.d.ts.map +1 -1
  268. package/dist/workspace/record-assets.d.ts.map +1 -1
  269. package/dist/workspace/record-sessions.d.ts +7 -11
  270. package/dist/workspace/record-sessions.d.ts.map +1 -1
  271. package/dist/workspace/records-checkout.d.ts +54 -0
  272. package/dist/workspace/records-checkout.d.ts.map +1 -0
  273. package/dist/workspace/records-cli.d.ts +57 -2
  274. package/dist/workspace/records-cli.d.ts.map +1 -1
  275. package/dist/workspace/records-close.d.ts +5 -2
  276. package/dist/workspace/records-close.d.ts.map +1 -1
  277. package/dist/workspace/records-since.d.ts.map +1 -1
  278. package/dist/workspace/records-write.d.ts +23 -4
  279. package/dist/workspace/records-write.d.ts.map +1 -1
  280. package/dist/workspace/records.d.ts +58 -5
  281. package/dist/workspace/records.d.ts.map +1 -1
  282. package/dist/workspace/returns.d.ts +129 -0
  283. package/dist/workspace/returns.d.ts.map +1 -0
  284. package/dist/workspace/runs-cli.d.ts +164 -0
  285. package/dist/workspace/runs-cli.d.ts.map +1 -0
  286. package/dist/workspace/runs.d.ts +423 -0
  287. package/dist/workspace/runs.d.ts.map +1 -0
  288. package/dist/workspace/source-block.d.ts +1 -1
  289. package/dist/workspace/source-block.d.ts.map +1 -1
  290. package/dist/workspace/status-gates.d.ts +15 -3
  291. package/dist/workspace/status-gates.d.ts.map +1 -1
  292. package/dist/workspace/status.d.ts +10 -0
  293. package/dist/workspace/status.d.ts.map +1 -1
  294. package/dist/workspace/symbols.d.ts +52 -0
  295. package/dist/workspace/symbols.d.ts.map +1 -0
  296. package/dist/workspace/template-manifest.d.ts +11 -3
  297. package/dist/workspace/template-manifest.d.ts.map +1 -1
  298. package/dist/workspace/trailer-joins.d.ts +46 -0
  299. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  300. package/dist/workspace/trailers.d.ts +89 -0
  301. package/dist/workspace/trailers.d.ts.map +1 -0
  302. package/dist/workspace/trust/attestor.d.ts +8 -0
  303. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  304. package/dist/workspace/trust/dsse.d.ts +58 -0
  305. package/dist/workspace/trust/dsse.d.ts.map +1 -0
  306. package/dist/workspace/trust/evidence-cli.d.ts +66 -0
  307. package/dist/workspace/trust/evidence-cli.d.ts.map +1 -0
  308. package/dist/workspace/trust/evidence.d.ts +93 -0
  309. package/dist/workspace/trust/evidence.d.ts.map +1 -0
  310. package/dist/workspace/trust/policy.d.ts +54 -1
  311. package/dist/workspace/trust/policy.d.ts.map +1 -1
  312. package/dist/workspace/trust/provenance.d.ts +21 -1
  313. package/dist/workspace/trust/provenance.d.ts.map +1 -1
  314. package/dist/workspace/trust/rotation.d.ts +132 -0
  315. package/dist/workspace/trust/rotation.d.ts.map +1 -0
  316. package/dist/workspace/trust/seal.d.ts +33 -0
  317. package/dist/workspace/trust/seal.d.ts.map +1 -1
  318. package/dist/workspace/trust/signers-cli.d.ts +49 -0
  319. package/dist/workspace/trust/signers-cli.d.ts.map +1 -0
  320. package/dist/workspace/trust/ssh-commit.d.ts +12 -0
  321. package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
  322. package/dist/workspace/trust/test-repo.d.ts +13 -0
  323. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  324. package/dist/workspace/trust/verify.d.ts +15 -0
  325. package/dist/workspace/trust/verify.d.ts.map +1 -1
  326. package/dist/workspace/work-cli.d.ts +39 -3
  327. package/dist/workspace/work-cli.d.ts.map +1 -1
  328. package/dist/workspace/work-evidence.d.ts +1 -1
  329. package/dist/workspace/work-evidence.d.ts.map +1 -1
  330. package/dist/workspace/work.d.ts +26 -1
  331. package/dist/workspace/work.d.ts.map +1 -1
  332. package/dist/workspace/workspace-principals.schema.json +60 -0
  333. package/dist/workspace/write-scope.d.ts +259 -0
  334. package/dist/workspace/write-scope.d.ts.map +1 -0
  335. package/dist/yaml.d.ts +21 -39
  336. package/dist/yaml.d.ts.map +1 -1
  337. package/package.json +2 -2
  338. package/src/audit/prior-art.ts +15 -0
  339. package/src/build.ts +8 -0
  340. package/src/cli/build-options.ts +4 -1
  341. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  342. package/src/cli/commands/build.ts +2 -0
  343. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  344. package/src/cli/commands/carve-emit.ts +5 -19
  345. package/src/cli/commands/check-lexicon.test.ts +62 -1
  346. package/src/cli/commands/check-lexicon.ts +36 -6
  347. package/src/cli/commands/import-live.test.ts +87 -1
  348. package/src/cli/commands/import-parser-options.test.ts +133 -0
  349. package/src/cli/commands/import.ts +69 -25
  350. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  351. package/src/cli/commands/init.test.ts +8 -1
  352. package/src/cli/commands/init.ts +23 -8
  353. package/src/cli/commands/lint.test.ts +37 -0
  354. package/src/cli/commands/onboard.test.ts +53 -3
  355. package/src/cli/commands/onboard.ts +52 -4
  356. package/src/cli/commands/pinned-upgrade.ts +73 -33
  357. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  358. package/src/cli/handlers/components.ts +2 -2
  359. package/src/cli/handlers/dev.ts +8 -6
  360. package/src/cli/handlers/fan-out.test.ts +6 -6
  361. package/src/cli/handlers/fan-out.ts +2 -1
  362. package/src/cli/handlers/graph.test.ts +42 -0
  363. package/src/cli/handlers/graph.ts +22 -0
  364. package/src/cli/handlers/lifecycle.test.ts +67 -0
  365. package/src/cli/handlers/lifecycle.ts +6 -5
  366. package/src/cli/handlers/misc.ts +2 -0
  367. package/src/cli/handlers/operator.ts +88 -4
  368. package/src/cli/handlers/run.test.ts +111 -0
  369. package/src/cli/handlers/run.ts +85 -24
  370. package/src/cli/handlers/scenario.ts +2 -2
  371. package/src/cli/main.test.ts +33 -0
  372. package/src/cli/main.ts +168 -17
  373. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  374. package/src/cli/mcp/workspace-tools.ts +62 -4
  375. package/src/cli/registry.ts +33 -2
  376. package/src/cli/serve-mcp-workspace.test.ts +1 -1
  377. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  378. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  379. package/src/codegen/pinned-upgrade.test.ts +104 -0
  380. package/src/codegen/pinned-upgrade.ts +250 -56
  381. package/src/codegen/release-wiring.test.ts +5 -1
  382. package/src/codegen/testdata/postgres-tags.json +242 -0
  383. package/src/components/fan-out-output.test.ts +1 -1
  384. package/src/components/fan-out.test.ts +1 -1
  385. package/src/components/promote.test.ts +1 -1
  386. package/src/config.test.ts +21 -0
  387. package/src/config.ts +27 -0
  388. package/src/content-digest.test.ts +2 -2
  389. package/src/declarable.test.ts +21 -0
  390. package/src/declarable.ts +19 -0
  391. package/src/discovery/fold-composite.test.ts +41 -5
  392. package/src/discovery/fold-import.test.ts +129 -0
  393. package/src/discovery/fold-import.ts +643 -131
  394. package/src/discovery/fold-package-composite.test.ts +264 -0
  395. package/src/discovery/fold-specifiers.test.ts +191 -0
  396. package/src/discovery/param-deps.test.ts +66 -1
  397. package/src/discovery/param-deps.ts +45 -0
  398. package/src/discovery/specifier-resolve.ts +344 -0
  399. package/src/fold/fold.test.ts +39 -1
  400. package/src/fold/fold.ts +83 -9
  401. package/src/fold-provenance.test.ts +140 -0
  402. package/src/graph-ir.test.ts +83 -0
  403. package/src/graph-ir.ts +29 -0
  404. package/src/import/embedded.test.ts +20 -0
  405. package/src/import/embedded.ts +13 -0
  406. package/src/import/parser-options.ts +46 -0
  407. package/src/import/parser.ts +20 -0
  408. package/src/lexicon.ts +79 -3
  409. package/src/lifecycle/gate-ledger.test.ts +14 -0
  410. package/src/lifecycle/gate-ledger.ts +18 -1
  411. package/src/lifecycle/observe.test.ts +18 -0
  412. package/src/lifecycle/observe.ts +6 -4
  413. package/src/lifecycle/plan-digest.test.ts +54 -3
  414. package/src/lifecycle/plan-digest.ts +38 -8
  415. package/src/lifecycle/snapshot.ts +2 -2
  416. package/src/lifecycle/work-lease.test.ts +1 -1
  417. package/src/lifecycle/work-lease.ts +93 -2
  418. package/src/lint/engine.test.ts +55 -0
  419. package/src/lint/engine.ts +30 -4
  420. package/src/lint/output-docs.test.ts +59 -56
  421. package/src/op/activities/activity-contracts.ts +1 -0
  422. package/src/op/activities/apply.test.ts +189 -5
  423. package/src/op/activities/apply.ts +230 -8
  424. package/src/op/activities/index.ts +3 -0
  425. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  426. package/src/op/activities/lexicon-upgrade.ts +154 -51
  427. package/src/op/activities/propose-upgrade.ts +8 -5
  428. package/src/op/composites/apply-op.ts +12 -5
  429. package/src/op/composites/composites.test.ts +30 -3
  430. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  431. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  432. package/src/op/emulator-lifecycle.test.ts +23 -0
  433. package/src/op/emulator-lifecycle.ts +52 -14
  434. package/src/op/gate-approval.test.ts +91 -0
  435. package/src/op/gate-approval.ts +5 -1
  436. package/src/op/gate.ts +34 -8
  437. package/src/op/index.ts +3 -1
  438. package/src/op/local-executor.test.ts +15 -0
  439. package/src/op/local-executor.ts +40 -12
  440. package/src/op/local-output.ts +1 -1
  441. package/src/op/operator.ts +4 -0
  442. package/src/op/run-context.test.ts +141 -0
  443. package/src/op/run-context.ts +51 -0
  444. package/src/op/runtimes/local.test.ts +14 -0
  445. package/src/op/runtimes/local.ts +2 -0
  446. package/src/op/steward-beside.ts +2 -0
  447. package/src/op/types.ts +8 -3
  448. package/src/op/work-lease-run.test.ts +47 -0
  449. package/src/op/work-lease-run.ts +73 -11
  450. package/src/provenance.ts +35 -0
  451. package/src/serializer.ts +9 -0
  452. package/src/telemetry-attribution.test.ts +91 -0
  453. package/src/telemetry-attribution.ts +145 -0
  454. package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
  455. package/src/workspace/agent-cli.ts +138 -0
  456. package/src/workspace/agent.schema.json +378 -0
  457. package/src/workspace/behold-kinds.test.ts +1 -1
  458. package/src/workspace/box-factory.test.ts +320 -0
  459. package/src/workspace/box-factory.ts +103 -0
  460. package/src/workspace/changes-cli.ts +5 -0
  461. package/src/workspace/changes.schema.json +171 -1
  462. package/src/workspace/changes.ts +61 -4
  463. package/src/workspace/check-live.test.ts +192 -0
  464. package/src/workspace/check.schema.json +64 -0
  465. package/src/workspace/checks/boxes.test.ts +2 -0
  466. package/src/workspace/checks/links.ts +23 -2
  467. package/src/workspace/checks/live.ts +113 -0
  468. package/src/workspace/checks.test.ts +2 -2
  469. package/src/workspace/checks.ts +49 -8
  470. package/src/workspace/compose-graph.test.ts +47 -0
  471. package/src/workspace/compose-graph.ts +127 -3
  472. package/src/workspace/conformance/__fixture__/decisions/decision.kind.mjs +7 -1
  473. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +5 -0
  474. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +27 -0
  475. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +95 -0
  476. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +132 -0
  477. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +48 -0
  478. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +108 -0
  479. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  480. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  481. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +578 -0
  482. package/src/workspace/conformance/conformance.e2e.test.ts +35 -3
  483. package/src/workspace/conformance/index.mjs +30 -3
  484. package/src/workspace/conformance/index.ts +103 -15
  485. package/src/workspace/conformance/vitest.ts +44 -2
  486. package/src/workspace/conformance/writer-conformance.e2e.test.ts +131 -0
  487. package/src/workspace/conformance/writer.test.ts +156 -0
  488. package/src/workspace/conformance/writer.ts +880 -0
  489. package/src/workspace/decide.ts +7 -1
  490. package/src/workspace/declaration.schema.json +368 -4
  491. package/src/workspace/declaration.ts +270 -1
  492. package/src/workspace/declared-kinds.test.ts +33 -0
  493. package/src/workspace/evidence.schema.json +279 -0
  494. package/src/workspace/export-cli.ts +180 -0
  495. package/src/workspace/export-import.test.ts +282 -0
  496. package/src/workspace/export.ts +486 -0
  497. package/src/workspace/graph-cli.ts +51 -2
  498. package/src/workspace/graph-contract.test.ts +89 -4
  499. package/src/workspace/graph.schema.json +453 -1
  500. package/src/workspace/identity.test.ts +196 -0
  501. package/src/workspace/identity.ts +186 -0
  502. package/src/workspace/import.ts +325 -0
  503. package/src/workspace/intent-cli.ts +64 -10
  504. package/src/workspace/intent-record.schema.json +208 -0
  505. package/src/workspace/intent-record.ts +35 -1
  506. package/src/workspace/intent-why.test.ts +274 -0
  507. package/src/workspace/intent.schema.json +718 -7
  508. package/src/workspace/intent.test.ts +11 -2
  509. package/src/workspace/intent.ts +495 -32
  510. package/src/workspace/kinds.test.ts +5 -5
  511. package/src/workspace/kinds.ts +62 -33
  512. package/src/workspace/lineage-adopt-cli.ts +103 -0
  513. package/src/workspace/lineage-adopt.test.ts +552 -0
  514. package/src/workspace/lineage-adopt.ts +452 -0
  515. package/src/workspace/lineage-check.ts +26 -5
  516. package/src/workspace/lineage-cli.ts +12 -2
  517. package/src/workspace/lineage-hash-index.ts +305 -0
  518. package/src/workspace/lineage-init.test.ts +9 -0
  519. package/src/workspace/lineage-init.ts +29 -9
  520. package/src/workspace/lineage-lock.ts +54 -0
  521. package/src/workspace/lineage-migrations.test.ts +27 -0
  522. package/src/workspace/lineage-migrations.ts +44 -14
  523. package/src/workspace/lineage-provenance.ts +40 -0
  524. package/src/workspace/lineage-upgrade-cli.ts +9 -5
  525. package/src/workspace/lineage-upgrade.test.ts +92 -1
  526. package/src/workspace/lineage-upgrade.ts +111 -16
  527. package/src/workspace/lineage-versions.ts +348 -0
  528. package/src/workspace/links.test.ts +121 -2
  529. package/src/workspace/links.ts +97 -6
  530. package/src/workspace/ls-contract.test.ts +84 -1
  531. package/src/workspace/ls-generated.ts +111 -0
  532. package/src/workspace/ls.schema.json +19 -0
  533. package/src/workspace/ls.ts +8 -1
  534. package/src/workspace/member-commands.ts +3 -1
  535. package/src/workspace/nested-graph.test.ts +176 -0
  536. package/src/workspace/nested-graph.ts +169 -0
  537. package/src/workspace/nesting.ts +37 -0
  538. package/src/workspace/pin-cli.test.ts +71 -0
  539. package/src/workspace/pin-cli.ts +57 -0
  540. package/src/workspace/pin-integrity.test.ts +121 -0
  541. package/src/workspace/pin-integrity.ts +104 -0
  542. package/src/workspace/points-write.schema.json +2 -0
  543. package/src/workspace/principal-classes.test.ts +175 -0
  544. package/src/workspace/principal-classes.ts +307 -0
  545. package/src/workspace/read-contract.test.ts +24 -0
  546. package/src/workspace/reason-codes.test.ts +20 -2
  547. package/src/workspace/reason-codes.ts +53 -3
  548. package/src/workspace/record-sessions.ts +12 -14
  549. package/src/workspace/records-amend.schema.json +6 -0
  550. package/src/workspace/records-checkout.ts +106 -0
  551. package/src/workspace/records-cli.ts +195 -22
  552. package/src/workspace/records-close.schema.json +7 -2
  553. package/src/workspace/records-close.ts +10 -2
  554. package/src/workspace/records-formats.test.ts +13 -5
  555. package/src/workspace/records-new.schema.json +6 -0
  556. package/src/workspace/records-review.schema.json +6 -0
  557. package/src/workspace/records-sessions.test.ts +23 -6
  558. package/src/workspace/records-uncommitted.test.ts +171 -0
  559. package/src/workspace/records-write.test.ts +65 -8
  560. package/src/workspace/records-write.ts +92 -6
  561. package/src/workspace/records.schema.json +127 -4
  562. package/src/workspace/records.ts +123 -5
  563. package/src/workspace/returns.ts +328 -0
  564. package/src/workspace/runs-cli.ts +381 -0
  565. package/src/workspace/runs-write.schema.json +583 -0
  566. package/src/workspace/runs.schema.json +810 -0
  567. package/src/workspace/runs.test.ts +242 -0
  568. package/src/workspace/runs.ts +709 -0
  569. package/src/workspace/signers.schema.json +206 -0
  570. package/src/workspace/status-contract.test.ts +5 -0
  571. package/src/workspace/status-gates.ts +24 -9
  572. package/src/workspace/status.schema.json +127 -2
  573. package/src/workspace/status.ts +21 -1
  574. package/src/workspace/symbols.ts +180 -0
  575. package/src/workspace/template-manifest.ts +22 -4
  576. package/src/workspace/trailer-joins.test.ts +171 -0
  577. package/src/workspace/trailer-joins.ts +82 -0
  578. package/src/workspace/trailers.ts +148 -0
  579. package/src/workspace/trust/attestor.ts +15 -0
  580. package/src/workspace/trust/dsse.ts +134 -0
  581. package/src/workspace/trust/evidence-cli.ts +195 -0
  582. package/src/workspace/trust/evidence.test.ts +241 -0
  583. package/src/workspace/trust/evidence.ts +207 -0
  584. package/src/workspace/trust/policy.ts +110 -3
  585. package/src/workspace/trust/provenance.ts +41 -4
  586. package/src/workspace/trust/record-seal.test.ts +1 -1
  587. package/src/workspace/trust/rotation.test.ts +258 -0
  588. package/src/workspace/trust/rotation.ts +336 -0
  589. package/src/workspace/trust/seal.ts +63 -1
  590. package/src/workspace/trust/signers-cli.ts +178 -0
  591. package/src/workspace/trust/ssh-commit.ts +53 -4
  592. package/src/workspace/trust/test-repo.ts +18 -0
  593. package/src/workspace/trust/trust.test.ts +8 -2
  594. package/src/workspace/trust/verify-cli.ts +1 -0
  595. package/src/workspace/trust/verify.ts +22 -0
  596. package/src/workspace/work-cli.e2e.test.ts +28 -1
  597. package/src/workspace/work-cli.ts +133 -8
  598. package/src/workspace/work-evidence.schema.json +6 -0
  599. package/src/workspace/work-history.schema.json +73 -1
  600. package/src/workspace/work-history.test.ts +48 -5
  601. package/src/workspace/work-kind-fields.test.ts +154 -0
  602. package/src/workspace/work-lease.schema.json +14 -1
  603. package/src/workspace/work.ts +82 -0
  604. package/src/workspace/workspace-principals.schema.json +60 -0
  605. package/src/workspace/write-scope.test.ts +466 -0
  606. package/src/workspace/write-scope.ts +573 -0
  607. package/src/yaml.test.ts +111 -1
  608. package/src/yaml.ts +141 -549
@@ -40,17 +40,19 @@ import { execFileSync } from "node:child_process";
40
40
  import { relative, resolve, sep } from "node:path";
41
41
  // @ts-ignore — picomatch has no types declaration
42
42
  import picomatch from "picomatch";
43
- import { declaredRecordKinds, readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError, type ChangeSeverity } from "./declaration";
43
+ import { declaredRecordKinds, readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError, type ChangeSeverity, type Declaration } from "./declaration";
44
44
  import { declaredKindFile } from "./declared-kinds";
45
45
  import { isGeneratedPath } from "./generated-files";
46
46
  import { parseRegion } from "./intent";
47
+ import { loadClassRegistry } from "./principal-classes";
47
48
  import { constraintCovers, isWorkspacePath, memberHolding } from "./record-assets";
48
- import { RecordReadError, type LoadedRecordKind, type RecordEntry } from "./records";
49
+ import { loadRecordKind, RecordReadError, type LoadedRecordKind, type RecordEntry } from "./records";
49
50
  import { readRecordsFor } from "./records-cli";
50
51
  import type { ReasonCode } from "./reason-codes";
51
52
  import { joinPath } from "./tree";
52
53
  import { locateWorkspace } from "./which-chant";
53
54
  import { idList, isDecided } from "./work";
55
+ import { checkWriteScope, type CheckKind, type ScopeReport } from "./write-scope";
54
56
 
55
57
  /** The version of the `changes` document this chant writes. */
56
58
  export const CHANGES_CONTRACT_VERSION = 1;
@@ -172,7 +174,13 @@ export type ChangesDocument =
172
174
  paths: ChangedPath[];
173
175
  findings: ChangeFinding[];
174
176
  summary: { paths: number; covered: number; uncovered: number; outOfScope: number; ignored: number; records: number };
175
- /** False only when severity is fail and there are findings. */
177
+ /**
178
+ * The write scope check (#2548): each commit in the range judged
179
+ * against the writeScope and agents the declaration at base gives,
180
+ * or null when that declaration restricts no one.
181
+ */
182
+ scope: ScopeReport | null;
183
+ /** False when severity is fail and there are findings, or when a commit writes outside its writer's scope. */
176
184
  ok: boolean;
177
185
  })
178
186
  | (Head & { error: { code: ChangesErrorCode; message: string } });
@@ -463,6 +471,7 @@ async function run(query: ChangesQuery, head: Head): Promise<Exclude<ChangesDocu
463
471
  }
464
472
  }
465
473
  const count = (s: ChangeStatus) => paths.filter((p) => p.status === s).length;
474
+ const scope = await writeScopeAtBase(query, top, range, workspacePrefix);
466
475
  return {
467
476
  ...head,
468
477
  workspace: { name: declaration.name, root: located.root },
@@ -474,10 +483,58 @@ async function run(query: ChangesQuery, head: Head): Promise<Exclude<ChangesDocu
474
483
  paths,
475
484
  findings,
476
485
  summary: { paths: paths.length, covered: count("covered"), uncovered: count("uncovered"), outOfScope: count("out-of-scope"), ignored: count("ignored"), records: count("record") },
477
- ok: !(severity === "fail" && findings.length > 0),
486
+ scope,
487
+ ok: !(severity === "fail" && findings.length > 0) && (scope === null || scope.findings.length === 0),
478
488
  };
479
489
  }
480
490
 
491
+ /**
492
+ * The write scope check over the range (#2548), with the declaration, its
493
+ * record kinds and the trust policy read at the range's base, so a change
494
+ * can't widen its own scope. Null when the base has no declaration, or one
495
+ * that restricts no one. The base is read without the root-chant rule: a
496
+ * change may move the chant pin, and the scope is data either chant reads.
497
+ */
498
+ async function writeScopeAtBase(query: ChangesQuery, top: string, range: { base: string; head: string }, prefix: string): Promise<ScopeReport | null> {
499
+ let located: ReturnType<typeof locateWorkspace>;
500
+ let declaration: Declaration;
501
+ try {
502
+ located = locateWorkspace(query.cwd, range.base);
503
+ declaration = readDeclaration(located.tree);
504
+ } catch (err) {
505
+ if (err instanceof WorkspaceReadError && err.code === "declaration-missing") return null;
506
+ throw err;
507
+ }
508
+ if (declaration.writeScope === null && declaration.agents.length === 0) return null;
509
+ const kinds: CheckKind[] = [];
510
+ for (const d of declaredRecordKinds(declaration)) {
511
+ let loaded: LoadedRecordKind;
512
+ try {
513
+ loaded = await loadRecordKind(declaredKindFile(d, located.rootOnDisk), query.cwd);
514
+ } catch (err) {
515
+ // A kind that doesn't load here: its files are judged as plain paths.
516
+ if (err instanceof RecordReadError) continue;
517
+ throw err;
518
+ }
519
+ const { kind } = loaded;
520
+ const session = kind.session;
521
+ kinds.push({
522
+ scoped: { name: kind.name, declaredName: d.name, member: d.member, declared: true },
523
+ dir: toPosix(relative(top, loaded.dir)) || ".",
524
+ match: new RegExp(kind.location.match),
525
+ reviewFields: [kind.reviews?.field, session?.verdicts].filter((f): f is string => typeof f === "string"),
526
+ session:
527
+ session && kind.stateField !== undefined
528
+ ? { stateField: kind.stateField, closed: kind.closedStates ?? [], fills: [session.openedRev].filter((f): f is string => typeof f === "string") }
529
+ : null,
530
+ format: kind.format,
531
+ });
532
+ }
533
+ // The principal classes the pins supply, a path pin read at the base too (#3080).
534
+ const classes = loadClassRegistry(declaration.pins, located.rootOnDisk, { tree: located.tree }).registry;
535
+ return checkWriteScope({ top, base: range.base, head: range.head, prefix, declaration, kinds, classes });
536
+ }
537
+
481
538
  function finding(code: ChangesFindingCode, p: ChangedPath, severity: "warn" | "fail", message: string, records: string[]): ChangeFinding {
482
539
  return { id: `finding:${code}:${p.path}`, code, path: p.path, message, severity, records, triage: changeFindingSource({ code, path: p.path }) };
483
540
  }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * `chant workspace check --live --env <env>` (#2549, ws-062): declared member
3
+ * links resolved against the live graph of each producer. A fake chant stands
4
+ * in for the member's own toolchain: it prints ir.json for a source read and
5
+ * live.json for `--live`, and records its command line in argv.txt.
6
+ */
7
+
8
+ import { existsSync, readFileSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { afterAll, afterEach, describe, expect, test, vi } from "vitest";
11
+ import { cleanScratch, contract, declaration, repo } from "./__fixtures__/contract-repo";
12
+ import { parseArgs } from "../cli/main";
13
+ import schema from "./check.schema.json";
14
+ import { workspaceGraph } from "./graph-cli";
15
+ import { runChecks, runWorkspaceCheck } from "./lineage-check";
16
+ import type { CheckDocument } from "./lineage-check";
17
+
18
+ const { expectValid } = contract(schema);
19
+
20
+ afterAll(() => cleanScratch());
21
+ afterEach(() => vi.restoreAllMocks());
22
+
23
+ const FAKE_CHANT = `#!/bin/sh
24
+ [ "$1" = graph ] || { echo "Error: Unknown command: $1" >&2; exit 1; }
25
+ printf '%s\\n' "$*" > ../argv.txt
26
+ case " $* " in
27
+ *" --live "*) cat live.json ;;
28
+ *) cat ir.json ;;
29
+ esac
30
+ `;
31
+
32
+ const graph = (exports: { name: string; value?: unknown }[]) => JSON.stringify({ version: 1, nodes: [], edges: [], groups: {}, exports });
33
+
34
+ function workspace(live: { name: string; value?: unknown }[], links: unknown[], producerKind: "chant" | "other" = "chant", extra: Record<string, unknown> = {}) {
35
+ return repo({
36
+ "chant.workspace.json": declaration([
37
+ producerKind === "chant" ? { name: "api", dir: "api", kind: "chant" } : { name: "api", dir: "api", kind: "other", because: "a queue made by hand", outputs: ["QueueUrl"] },
38
+ { name: "web", dir: "web", kind: "other", because: "a static site", links },
39
+ ], extra),
40
+ "api/chant.config.ts": "export default {};\n",
41
+ "api/ir.json": graph([{ name: "QueueUrl" }, { name: "TopicArn" }]),
42
+ "api/live.json": graph(live),
43
+ "web/index.html": "",
44
+ ".gitignore": "node_modules\n",
45
+ "node_modules/.bin/chant": { text: FAKE_CHANT, mode: 0o755 },
46
+ });
47
+ }
48
+
49
+ async function live(root: string, env = "prod") {
50
+ const doc = (await runChecks(root, undefined, { live: { env } })) as Extract<CheckDocument, { workspace: unknown }>;
51
+ const diagnostics = doc.declaration!.diagnostics.filter((d) => d.ruleId === "WSP141" || d.ruleId === "WSP142");
52
+ return { doc, diagnostics, rows: doc.declaration!.live?.links ?? [] };
53
+ }
54
+
55
+ describe("check --live (#2549)", () => {
56
+ test("a link to an output the live graph publishes resolves, and the row says it resolved live", async () => {
57
+ const root = workspace([{ name: "QueueUrl", value: "https://q" }], [{ member: "api", output: "QueueUrl" }]);
58
+ const { doc, diagnostics, rows } = await live(root);
59
+ expect(diagnostics).toEqual([]);
60
+ expectValid(doc);
61
+ expect(doc.declaration!.live!.env).toBe("prod");
62
+ expect(rows).toMatchObject([{ consumer: "web", producer: "api", output: "QueueUrl", resolves: "live", status: "resolved", reason: null }]);
63
+ // The member ran as `chant graph --live --env prod`.
64
+ expect(readFileSync(join(root, "argv.txt"), "utf-8")).toContain("--env prod --live");
65
+ });
66
+
67
+ test("an output the producer declares but its estate does not publish is WSP141, a warning", async () => {
68
+ const root = workspace([{ name: "TopicArn", value: "arn" }], [{ member: "api", output: "QueueUrl" }]);
69
+ const { diagnostics, rows } = await live(root);
70
+ expect(rows[0]).toMatchObject({ status: "missing", resolves: "live" });
71
+ expect(diagnostics).toHaveLength(1);
72
+ expect(diagnostics[0]).toMatchObject({ ruleId: "WSP141", severity: "warning", entity: "web" });
73
+ expect(diagnostics[0].message).toContain("does not resolve live in prod");
74
+ expect(diagnostics[0].message).toContain("TopicArn");
75
+ });
76
+
77
+ test("a live read that returned no outputs at all leaves the link unresolved, not missing", async () => {
78
+ const root = workspace([], [{ member: "api", output: "QueueUrl" }]);
79
+ const { diagnostics, rows } = await live(root);
80
+ expect(rows[0].status).toBe("unresolved");
81
+ expect(diagnostics).toMatchObject([{ ruleId: "WSP142", severity: "info" }]);
82
+ expect(diagnostics[0].message).toContain("returned no outputs");
83
+ });
84
+
85
+ test("a producer of a kind chant does not read live is kept unresolved, with the reason", async () => {
86
+ const root = workspace([], [{ member: "api", output: "QueueUrl" }], "other");
87
+ const { diagnostics, rows } = await live(root);
88
+ expect(rows[0]).toMatchObject({ status: "unresolved", resolves: "live" });
89
+ expect(diagnostics).toMatchObject([{ ruleId: "WSP142" }]);
90
+ expect(diagnostics[0].message).toContain("kind other");
91
+ });
92
+
93
+ test("a telemetry link is not resolved live", async () => {
94
+ const root = workspace([{ name: "QueueUrl" }], [{ member: "api", output: "traces", kind: "telemetry" }]);
95
+ const { rows } = await live(root);
96
+ expect(rows).toEqual([]);
97
+ });
98
+
99
+ test("severity settings apply to the live checks like any other", async () => {
100
+ const root = repo({
101
+ "chant.workspace.json": declaration(
102
+ [
103
+ { name: "api", dir: "api", kind: "chant" },
104
+ { name: "web", dir: "web", kind: "other", because: "a static site", links: [{ member: "api", output: "QueueUrl" }], suppress: [{ check: "WSP141", because: "deployed next week" }] },
105
+ ],
106
+ { checks: { WSP141: "error" } },
107
+ ),
108
+ "api/chant.config.ts": "export default {};\n",
109
+ "api/ir.json": graph([{ name: "QueueUrl" }]),
110
+ "api/live.json": graph([{ name: "Other" }]),
111
+ "web/index.html": "",
112
+ ".gitignore": "node_modules\n",
113
+ "node_modules/.bin/chant": { text: FAKE_CHANT, mode: 0o755 },
114
+ });
115
+ const { doc, diagnostics } = await live(root);
116
+ expect(diagnostics).toEqual([]);
117
+ expect(doc.declaration!.suppressed.map((s) => s.ruleId)).toContain("WSP141");
118
+ });
119
+
120
+ test("without --live no member runs and the report has no live section", async () => {
121
+ const root = workspace([{ name: "QueueUrl" }], [{ member: "api", output: "QueueUrl" }]);
122
+ const doc = (await runChecks(root)) as Extract<CheckDocument, { workspace: unknown }>;
123
+ expect(doc.declaration!.live).toBeUndefined();
124
+ expect(existsSync(join(root, "argv.txt"))).toBe(false);
125
+ });
126
+ });
127
+
128
+ describe("the command (#2549)", () => {
129
+ async function run(root: string, argv: string[]) {
130
+ const out: string[] = [];
131
+ const err: string[] = [];
132
+ vi.spyOn(console, "log").mockImplementation((...a: unknown[]) => void out.push(a.join(" ")));
133
+ vi.spyOn(console, "error").mockImplementation((...a: unknown[]) => void err.push(a.join(" ")));
134
+ vi.spyOn(process, "cwd").mockReturnValue(root);
135
+ const code = await runWorkspaceCheck({ args: parseArgs(["workspace", "check", ...argv]), plugins: [] } as never);
136
+ return { code, out: out.join("\n"), err: err.join("\n") };
137
+ }
138
+
139
+ test("--live needs --env, and takes no --at, and runs no member when it refuses", async () => {
140
+ const root = workspace([{ name: "QueueUrl" }], [{ member: "api", output: "QueueUrl" }]);
141
+ const noEnv = await run(root, ["--live"]);
142
+ expect(noEnv.code).toBe(1);
143
+ expect(noEnv.err).toContain("--live needs an environment");
144
+ const atRev = await run(root, ["--live", "--env", "prod", "--at", "HEAD"]);
145
+ expect(atRev.code).toBe(1);
146
+ expect(atRev.err).toContain("--at");
147
+ expect(existsSync(join(root, "argv.txt"))).toBe(false);
148
+ });
149
+
150
+ test("--live --json prints the live section, and a WSP141 warning leaves the exit code 0", async () => {
151
+ // The fake producer's source lists no outputs, so the source check WSP093 is turned off; the live warning is the one under test.
152
+ const root = workspace([{ name: "TopicArn" }], [{ member: "api", output: "QueueUrl" }], "chant", { checks: { WSP093: "off" } });
153
+ const { code, out } = await run(root, ["--live", "--env", "prod", "--json"]);
154
+ const report = JSON.parse(out) as { declaration: { live: { env: string; links: { status: string }[] }; diagnostics: { ruleId: string }[] } };
155
+ expect(report.declaration.live).toMatchObject({ env: "prod", links: [{ status: "missing" }] });
156
+ expect(report.declaration.diagnostics.map((d) => d.ruleId)).toContain("WSP141");
157
+ expect(code).toBe(0);
158
+ });
159
+ });
160
+
161
+ describe("the design member kind (#2549, ws-062)", () => {
162
+ const designWorkspace = (extra: Record<string, unknown> = {}) =>
163
+ repo({
164
+ "chant.workspace.json": declaration([
165
+ { name: "design", dir: "design", kind: "design", outputs: ["screens/home.json"], ...extra },
166
+ { name: "web", dir: "web", kind: "other", because: "a static site", links: [{ member: "design", output: "screens/home.json" }] },
167
+ ]),
168
+ "design/screens/home.json": "{}\n",
169
+ "web/index.html": "",
170
+ });
171
+
172
+ test("is a declared kind: no WSP003, no WSP009, no `because` needed, and its listed outputs are link targets", async () => {
173
+ const doc = (await runChecks(designWorkspace())) as Extract<CheckDocument, { workspace: unknown }>;
174
+ const ids = doc.declaration!.diagnostics.map((d) => d.ruleId);
175
+ expect(ids).not.toContain("WSP003");
176
+ expect(doc.declaration!.diagnostics.filter((d) => d.entity === "design")).toEqual([]);
177
+ expect(doc.declaration!.links).toMatchObject([{ consumer: "web", producer: "design", output: "screens/home.json", status: "resolved" }]);
178
+ });
179
+
180
+ test("a data member: workspace graph reads it and builds nothing, saying so", async () => {
181
+ const { doc } = await workspaceGraph({ cwd: designWorkspace() });
182
+ if ("error" in doc) throw new Error(doc.error.message);
183
+ expect(doc.members.find((m) => m.name === "design")).toMatchObject({ kind: "design", status: "skipped", reason: { code: "kind-not-run" } });
184
+ expect(doc.members.find((m) => m.name === "design")!.reason!.message).toContain("data");
185
+ });
186
+
187
+ test("a design member's link is not resolved live: its files are not an estate", async () => {
188
+ const { rows, diagnostics } = await live(designWorkspace());
189
+ expect(rows[0]).toMatchObject({ status: "unresolved", resolves: "live" });
190
+ expect(diagnostics).toMatchObject([{ ruleId: "WSP142" }]);
191
+ });
192
+ });
@@ -146,6 +146,70 @@
146
146
  "ok": {
147
147
  "type": "boolean"
148
148
  },
149
+ "live": {
150
+ "description": "Present with --live --env (#2549, ws-062): the declared output links resolved against the live graph of the environment. Each member of kind chant ran chant graph --live. Added by chant 0.101.0.",
151
+ "type": "object",
152
+ "required": [
153
+ "env",
154
+ "links"
155
+ ],
156
+ "properties": {
157
+ "env": {
158
+ "type": "string"
159
+ },
160
+ "links": {
161
+ "type": "array",
162
+ "items": {
163
+ "type": "object",
164
+ "required": [
165
+ "consumer",
166
+ "producer",
167
+ "output",
168
+ "resolves",
169
+ "status",
170
+ "reason"
171
+ ],
172
+ "properties": {
173
+ "consumer": {
174
+ "type": "string"
175
+ },
176
+ "producer": {
177
+ "type": "string"
178
+ },
179
+ "output": {
180
+ "type": "string"
181
+ },
182
+ "kind": {
183
+ "type": "string"
184
+ },
185
+ "origin": {
186
+ "const": "declared"
187
+ },
188
+ "resolves": {
189
+ "const": "live"
190
+ },
191
+ "status": {
192
+ "enum": [
193
+ "resolved",
194
+ "missing",
195
+ "unresolved",
196
+ "invalid"
197
+ ]
198
+ },
199
+ "reason": {
200
+ "type": [
201
+ "string",
202
+ "null"
203
+ ]
204
+ },
205
+ "pointer": {
206
+ "type": "string"
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ },
149
213
  "diagnostics": {
150
214
  "description": "Active findings, in the shape `chant lint --format json` prints, sorted by position.",
151
215
  "type": "array",
@@ -158,6 +158,8 @@ describe("the box block in the declaration", () => {
158
158
  isolation: null,
159
159
  intent: null,
160
160
  services: [],
161
+ factory: null,
162
+ listing: null,
161
163
  capabilities: [
162
164
  { name: "fountain", broker: "lobby", scope: ["agent", "vault"], pointer: "/members/0/box/capabilities/0" },
163
165
  { name: "inference", broker: null, scope: [], pointer: "/members/0/box/capabilities/1" },
@@ -16,12 +16,13 @@
16
16
  * | WSP095 | an inferred join is ambiguous: a parameter matches two or more outputs |
17
17
  * | WSP096 | a consumer states the same link twice |
18
18
  * | WSP097 | an entry lists `outputs` for a kind that doesn't take them from the entry |
19
+ * | WSP098 | a link states a `protocol` and its kind is not `telemetry` (#2558) |
19
20
  */
20
21
 
21
22
  import type { WorkspaceCheck, WorkspaceCheckContext, WorkspaceDiagnostic } from "../checks";
22
23
  import type { Member } from "../declaration";
23
24
  import { sourceMemberHandles } from "../member-handles";
24
- import { DEFAULT_LINK_KIND, LINK_KINDS, linkTargetProblem, resolveLinks, type AmbiguousRow, type LinkRow, type LinkTableRow } from "../links";
25
+ import { DEFAULT_LINK_KIND, LINK_KINDS, TELEMETRY_LINK_KIND, linkTargetProblem, resolveLinks, type AmbiguousRow, type LinkRow, type LinkTableRow } from "../links";
25
26
 
26
27
  const tables = new WeakMap<WorkspaceCheckContext, LinkTableRow[]>();
27
28
 
@@ -62,7 +63,7 @@ export const LINK_CHECKS: readonly WorkspaceCheck[] = [
62
63
  {
63
64
  id: "WSP092",
64
65
  name: "link-kind-unknown",
65
- description: `Every member link's kind is one chant knows. Unknown link kinds fail closed; ${DEFAULT_LINK_KIND} is the default and the only one so far.`,
66
+ description: `Every member link's kind is one chant knows. Unknown link kinds fail closed; ${DEFAULT_LINK_KIND} is the default, and ${LINK_KINDS.filter((k) => k !== DEFAULT_LINK_KIND).join(", ")} is the other.`,
66
67
  severity: "error",
67
68
  configurable: false,
68
69
  check(ctx) {
@@ -180,4 +181,24 @@ export const LINK_CHECKS: readonly WorkspaceCheck[] = [
180
181
  });
181
182
  },
182
183
  },
184
+ {
185
+ id: "WSP098",
186
+ name: "link-protocol-misplaced",
187
+ description: "A link states a protocol only when it is a telemetry link: protocol is the OTLP protocol the consumer sends to the producer's collector, and no other link kind has one.",
188
+ severity: "error",
189
+ configurable: true,
190
+ check(ctx) {
191
+ return ctx.declaration.members.flatMap((m) =>
192
+ m.links
193
+ .filter((l) => l.protocol !== null && (l.kind ?? DEFAULT_LINK_KIND) !== TELEMETRY_LINK_KIND)
194
+ .map((l) => ({
195
+ checkId: this.id,
196
+ severity: this.severity,
197
+ message: `member ${m.name}'s link to ${l.member} output ${l.output} states protocol ${l.protocol}, and its kind is ${l.kind ?? DEFAULT_LINK_KIND}; protocol belongs to a ${TELEMETRY_LINK_KIND} link`,
198
+ entity: m.name,
199
+ pointer: `${l.pointer}/protocol`,
200
+ })),
201
+ );
202
+ },
203
+ },
183
204
  ];
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The live link checks, WSP141 and WSP142 (#2549; #2524 D6, ws-062).
3
+ *
4
+ * `chant workspace check --live --env <env>` resolves each declared member
5
+ * link against what its producer's estate publishes now. It reads the live
6
+ * graph the way `chant workspace graph --live --env <env>` does: each `chant`
7
+ * member runs `chant graph --live` under its own toolchain, and the outputs of
8
+ * the live graph (the stack outputs a lexicon's live read reports) are the
9
+ * names a link may match, exactly. That is the one place this command reaches
10
+ * a network, through the member's own chant, with the member's own
11
+ * credentials. Without `--live` none of this runs, and the source checks
12
+ * (`./links.ts`) stay offline.
13
+ *
14
+ * | Id | Fails when |
15
+ * |---|---|
16
+ * | WSP141 | the producer was read live and publishes no output of that name |
17
+ * | WSP142 | the link could not be resolved live: the producer's kind is not read live, its read failed, or the read returned no outputs at all |
18
+ *
19
+ * Only declared links of kind `output` are resolved live. A `telemetry` link
20
+ * names a collector's pipeline or exporter, which the graph reports from the
21
+ * member's source, so it is not part of this check.
22
+ */
23
+
24
+ import type { WorkspaceCheck, WorkspaceDiagnostic } from "../checks";
25
+ import type { Declaration } from "../declaration";
26
+ import type { KindRegistry } from "../kinds";
27
+ import { DEFAULT_LINK_KIND, irMemberHandles, resolveLinks, type LinkRow } from "../links";
28
+
29
+ /** What a live read of the workspace found, for the live link checks. */
30
+ export interface LiveLinkFacts {
31
+ env: string;
32
+ /** Every declared `output` link, resolved against the live outputs. */
33
+ rows: LinkRow[];
34
+ }
35
+
36
+ const describeLink = (row: LinkRow) => `${row.consumer}'s link to ${row.producer} output ${row.output}`;
37
+
38
+ /**
39
+ * Read the live graph of the workspace at `cwd` for `env` and resolve the
40
+ * declared links against it. `onStderr` gets each member's stderr, which is
41
+ * where a lexicon's live read reports an account it could not reach.
42
+ */
43
+ export async function gatherLiveLinkFacts(cwd: string, declaration: Declaration, kinds: KindRegistry, env: string, onStderr?: (text: string) => void): Promise<LiveLinkFacts> {
44
+ const { workspaceGraph } = await import("../graph-cli");
45
+ const { doc } = await workspaceGraph({ cwd, args: { live: true, env }, noCache: true, ...(onStderr ? { onStderr } : {}) });
46
+ if ("error" in doc) {
47
+ return { env, rows: unreadRows(declaration, `the live graph could not be read: ${doc.error.code}: ${doc.error.message}`) };
48
+ }
49
+ const read = new Map(doc.members.map((m) => [m.name, m]));
50
+ const composed = doc.members.filter((m) => m.status === "composed").map((m) => m.name);
51
+ const handles = irMemberHandles({ composed, exports: doc.exports, imports: doc.imports });
52
+ const table = resolveLinks(declaration, handles);
53
+ const rows: LinkRow[] = [];
54
+ for (const r of table) {
55
+ if (r.status === "ambiguous" || r.origin !== "declared" || r.kind !== DEFAULT_LINK_KIND) continue;
56
+ const row: LinkRow = { ...r, resolves: "live" };
57
+ if (row.status !== "invalid") {
58
+ const producer = read.get(row.producer);
59
+ const kind = kinds.get(declaration.members.find((m) => m.name === row.producer)?.kind ?? "");
60
+ if (!producer || producer.status !== "composed") {
61
+ row.status = "unresolved";
62
+ row.reason =
63
+ producer?.reason?.message ??
64
+ (kind ? `${row.producer} is kind ${kind.name}, which chant does not read live` : `${row.producer} was not read live`);
65
+ } else if (row.status === "missing" && !doc.exports.some((e) => e.member === row.producer)) {
66
+ row.status = "unresolved";
67
+ row.reason = `the live read of ${row.producer} returned no outputs: the account may be unreachable, or its lexicon reports none`;
68
+ } else if (row.status === "missing") {
69
+ row.reason = row.reason?.replace(/^(\S+) has no output/, "$1 publishes no output") ?? row.reason;
70
+ }
71
+ }
72
+ rows.push(row);
73
+ }
74
+ return { env, rows };
75
+ }
76
+
77
+ /** Every declared output link as unresolved, when the live graph could not be read at all. */
78
+ function unreadRows(declaration: Declaration, reason: string): LinkRow[] {
79
+ return resolveLinks(declaration, new Map())
80
+ .filter((r): r is LinkRow => r.status !== "ambiguous" && r.origin === "declared" && r.kind === DEFAULT_LINK_KIND)
81
+ .map((r) => ({ ...r, resolves: "live", ...(r.status === "invalid" ? {} : { status: "unresolved" as const, reason }) }));
82
+ }
83
+
84
+ function liveFinding(check: WorkspaceCheck, row: LinkRow, message: string): WorkspaceDiagnostic {
85
+ return { checkId: check.id, severity: check.severity, message, entity: row.consumer, pointer: `${row.pointer}/output` };
86
+ }
87
+
88
+ export const LIVE_CHECKS: readonly WorkspaceCheck[] = [
89
+ {
90
+ id: "WSP141",
91
+ name: "link-live-missing",
92
+ description: "With --live, a member link names an output its producer's estate publishes now, matched exactly. A producer whose declared output isn't deployed yet, or was renamed in the estate, fails this for every consumer.",
93
+ severity: "warning",
94
+ configurable: true,
95
+ check(ctx) {
96
+ return (ctx.facts?.live?.rows ?? [])
97
+ .filter((r) => r.status === "missing")
98
+ .map((r) => liveFinding(this, r, `${describeLink(r)} does not resolve live in ${ctx.facts!.live!.env}: ${r.reason}`));
99
+ },
100
+ },
101
+ {
102
+ id: "WSP142",
103
+ name: "link-live-unresolved",
104
+ description: "With --live, a member link that could not be resolved against a live read is kept, unresolved, and reported: the producer's kind is not read live, its read failed, or the read returned no outputs.",
105
+ severity: "info",
106
+ configurable: true,
107
+ check(ctx) {
108
+ return (ctx.facts?.live?.rows ?? [])
109
+ .filter((r) => r.status === "unresolved")
110
+ .map((r) => liveFinding(this, r, `${describeLink(r)} is kept unresolved in ${ctx.facts!.live!.env}: ${r.reason}`));
111
+ },
112
+ },
113
+ ];
@@ -75,7 +75,7 @@ describe("the WSP catalog", () => {
75
75
  expect(list.filter((id) => /^WSP(07|08|09|10)\d$/.test(id))).toEqual([
76
76
  "WSP071", "WSP072", "WSP073",
77
77
  "WSP081", "WSP082", "WSP083",
78
- "WSP091", "WSP092", "WSP093", "WSP094", "WSP095", "WSP096", "WSP097",
78
+ "WSP091", "WSP092", "WSP093", "WSP094", "WSP095", "WSP096", "WSP097", "WSP098",
79
79
  "WSP101", "WSP102", "WSP103", "WSP104", "WSP105", "WSP106",
80
80
  ]);
81
81
  });
@@ -111,7 +111,7 @@ describe("declaration checks (#2535)", () => {
111
111
  column: 15,
112
112
  ruleId: "WSP003",
113
113
  severity: "error",
114
- message: "member infra has kind terraform, which no built-in kind or pinned package supplies; known kinds: chant, other, workspace",
114
+ message: "member infra has kind terraform, which no built-in kind or pinned package supplies; known kinds: chant, design, other, workspace",
115
115
  entity: "infra",
116
116
  },
117
117
  ]);