@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
@@ -1,7 +1,7 @@
1
1
  import { describe, test, expect } from "vitest";
2
2
  import { applyResult } from "../../apply";
3
3
  import { defaultOutput, nativeApply, compensateApply, hasNativeRollback } from "./apply";
4
- import type { K8sApplier, AzureApplier, GcpApplier, FlyApplier, AwsApplier, AwsRollback } from "./apply";
4
+ import type { K8sApplier, AzureApplier, GcpApplier, FlyApplier, GrafanaApplier, ClickHouseApplier, PostgresApplier, AwsApplier, AwsRollback } from "./apply";
5
5
 
6
6
  /**
7
7
  * The kubectl branch moved to the k8s lexicon in chant #1075, the arm branch to
@@ -415,6 +415,189 @@ describe("nativeApply: fly dispatches to the fly lexicon (chant #1449)", () => {
415
415
  });
416
416
  });
417
417
 
418
+ describe("nativeApply: grafana dispatches to the grafana lexicon (chant #3011)", () => {
419
+ /** Records what the applier was handed, and reports an empty envelope. */
420
+ const spy = (): { calls: Array<Parameters<GrafanaApplier>[0]>; applier: GrafanaApplier } => {
421
+ const calls: Array<Parameters<GrafanaApplier>[0]> = [];
422
+ const applier: GrafanaApplier = async (args) => {
423
+ calls.push(args);
424
+ return applyResult([]);
425
+ };
426
+ return { calls, applier };
427
+ };
428
+ /** nativeApply with only the grafana applier injected. */
429
+ const applyGrafana = (args: Parameters<typeof nativeApply>[0], applier: GrafanaApplier) =>
430
+ nativeApply(args, undefined, undefined, undefined, undefined, undefined, undefined, undefined, applier);
431
+
432
+ test("output maps to the index path and env to the environment, and nothing else is passed", async () => {
433
+ const { calls, applier } = spy();
434
+ await applyGrafana({ target: "grafana", env: "prod", output: "dist/grafana.json" }, applier);
435
+ // env selects grafana.profiles.<env>; the ownership marker is read from
436
+ // chant.config.ts inside grafanaApply, so neither stack nor
437
+ // ownershipEnv crosses this seam.
438
+ expect(calls).toEqual([{ indexPath: "dist/grafana.json", environment: "prod", prune: false }]);
439
+ });
440
+
441
+ test("owned-only and gated ask the grafana applier to prune", async () => {
442
+ for (const deleteMode of ["owned-only", "gated"] as const) {
443
+ const { calls, applier } = spy();
444
+ await applyGrafana({ target: "grafana", env: "prod", deleteMode }, applier);
445
+ expect(calls[0].prune).toBe(true);
446
+ }
447
+ });
448
+
449
+ test("never (and the default) do not prune", async () => {
450
+ const explicit = spy();
451
+ await applyGrafana({ target: "grafana", env: "prod", deleteMode: "never" }, explicit.applier);
452
+ expect(explicit.calls[0].prune).toBe(false);
453
+
454
+ const defaulted = spy();
455
+ await applyGrafana({ target: "grafana", env: "prod" }, defaulted.applier);
456
+ expect(defaulted.calls[0].prune).toBe(false);
457
+ });
458
+
459
+ test("defaults the index path to dist/grafana.json", async () => {
460
+ const { calls, applier } = spy();
461
+ await applyGrafana({ target: "grafana", env: "prod" }, applier);
462
+ expect(calls[0].indexPath).toBe("dist/grafana.json");
463
+ expect(defaultOutput("grafana")).toBe("dist/grafana.json");
464
+ });
465
+
466
+ test("counts are preserved from the applier's envelope, not-prunable kinds included", async () => {
467
+ const applier: GrafanaApplier = async () =>
468
+ applyResult(
469
+ [
470
+ { kind: "Folder", name: "team-a", action: "created" },
471
+ { kind: "Dashboard", name: "api", action: "updated" },
472
+ { kind: "Dashboard", name: "db", action: "unchanged" },
473
+ ],
474
+ [{ kind: "Dashboard", name: "old", deleted: true }],
475
+ [{ kind: "LibraryPanel", name: "*", reason: "not-prunable", detail: "library panels carry no labels" }],
476
+ );
477
+ const result = await applyGrafana({ target: "grafana", env: "prod" }, applier);
478
+ expect(result).toEqual({ applied: 3, pruned: 1, notAttempted: 1 });
479
+ });
480
+
481
+ test("with nothing injected it resolves the real grafana lexicon's grafanaApply", async () => {
482
+ // An index path that does not exist fails inside grafanaApply's own read,
483
+ // reachable only if the dynamic import found the lexicon, and before any
484
+ // binding or HTTP call.
485
+ const err = await nativeApply({
486
+ target: "grafana",
487
+ env: "prod",
488
+ output: "/nonexistent/chant-3011-grafana.json",
489
+ }).catch((e: unknown) => e);
490
+ expect(String(err)).toMatch(/ENOENT|no such file/);
491
+ expect(String(err)).not.toMatch(/could not be loaded/);
492
+ });
493
+ });
494
+
495
+ describe("nativeApply: clickhouse dispatches to the sql lexicon (chant #3208)", () => {
496
+ const spy = (): { calls: Array<Parameters<ClickHouseApplier>[0]>; applier: ClickHouseApplier } => {
497
+ const calls: Array<Parameters<ClickHouseApplier>[0]> = [];
498
+ const applier: ClickHouseApplier = async (args) => {
499
+ calls.push(args);
500
+ return applyResult([]);
501
+ };
502
+ return { calls, applier };
503
+ };
504
+ const applyClickHouse = (args: Parameters<typeof nativeApply>[0], applier: ClickHouseApplier) =>
505
+ nativeApply(args, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, applier);
506
+
507
+ test("output maps to the build path and env to the environment, and nothing else is passed", async () => {
508
+ const { calls, applier } = spy();
509
+ await applyClickHouse({ target: "clickhouse", env: "prod", output: "dist/schema.json" }, applier);
510
+ expect(calls).toEqual([{ buildPath: "dist/schema.json", environment: "prod", prune: false }]);
511
+ });
512
+
513
+ test("owned-only and gated prune; never and the default do not", async () => {
514
+ for (const [deleteMode, prune] of [["owned-only", true], ["gated", true], ["never", false], [undefined, false]] as const) {
515
+ const { calls, applier } = spy();
516
+ await applyClickHouse({ target: "clickhouse", env: "prod", ...(deleteMode ? { deleteMode } : {}) }, applier);
517
+ expect(calls[0].prune).toBe(prune);
518
+ }
519
+ });
520
+
521
+ test("defaults the build path to dist/schema.json", async () => {
522
+ const { calls, applier } = spy();
523
+ await applyClickHouse({ target: "clickhouse", env: "prod" }, applier);
524
+ expect(calls[0].buildPath).toBe("dist/schema.json");
525
+ expect(defaultOutput("clickhouse")).toBe("dist/schema.json");
526
+ });
527
+
528
+ test("counts come from the envelope, a refused rebuild among the not-attempted", async () => {
529
+ const applier: ClickHouseApplier = async () =>
530
+ applyResult(
531
+ [
532
+ { kind: "ClickHouse::Database", name: "shop", action: "unchanged" },
533
+ { kind: "ClickHouse::Table", name: "shop.users", action: "updated" },
534
+ ],
535
+ [{ kind: "ClickHouse::Table", name: "shop.old", deleted: true }],
536
+ [{ kind: "ClickHouse::Table", name: "shop.events", reason: "unsupported-kind", detail: "needs a rebuild" }],
537
+ );
538
+ expect(await applyClickHouse({ target: "clickhouse", env: "prod" }, applier)).toEqual({ applied: 2, pruned: 1, notAttempted: 1 });
539
+ });
540
+
541
+ test("with nothing injected it resolves the real sql lexicon's clickhouseApply", async () => {
542
+ const err = await nativeApply({ target: "clickhouse", env: "prod", output: "/nonexistent/chant-3208-schema.json" }).catch((e: unknown) => e);
543
+ expect(String(err)).toMatch(/ENOENT|no such file/);
544
+ expect(String(err)).not.toMatch(/could not be loaded/);
545
+ });
546
+ });
547
+
548
+ describe("nativeApply: postgres dispatches to the sql lexicon (chant #3280)", () => {
549
+ const spy = (): { calls: Array<Parameters<PostgresApplier>[0]>; applier: PostgresApplier } => {
550
+ const calls: Array<Parameters<PostgresApplier>[0]> = [];
551
+ const applier: PostgresApplier = async (args) => {
552
+ calls.push(args);
553
+ return applyResult([]);
554
+ };
555
+ return { calls, applier };
556
+ };
557
+ const applyPostgres = (args: Parameters<typeof nativeApply>[0], applier: PostgresApplier) =>
558
+ nativeApply(args, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, applier);
559
+
560
+ test("output maps to the build path and env to the environment, and nothing else is passed", async () => {
561
+ const { calls, applier } = spy();
562
+ await applyPostgres({ target: "postgres", env: "prod", output: "dist/schema.json" }, applier);
563
+ expect(calls).toEqual([{ buildPath: "dist/schema.json", environment: "prod", prune: false }]);
564
+ });
565
+
566
+ test("owned-only and gated prune; never and the default do not", async () => {
567
+ for (const [deleteMode, prune] of [["owned-only", true], ["gated", true], ["never", false], [undefined, false]] as const) {
568
+ const { calls, applier } = spy();
569
+ await applyPostgres({ target: "postgres", env: "prod", ...(deleteMode ? { deleteMode } : {}) }, applier);
570
+ expect(calls[0].prune).toBe(prune);
571
+ }
572
+ });
573
+
574
+ test("defaults the build path to dist/schema.json", async () => {
575
+ const { calls, applier } = spy();
576
+ await applyPostgres({ target: "postgres", env: "prod" }, applier);
577
+ expect(calls[0].buildPath).toBe("dist/schema.json");
578
+ expect(defaultOutput("postgres")).toBe("dist/schema.json");
579
+ });
580
+
581
+ test("counts come from the envelope, a refused expand-and-contract change among the not-attempted", async () => {
582
+ const applier: PostgresApplier = async () =>
583
+ applyResult(
584
+ [
585
+ { kind: "Postgres::Schema", name: "app", action: "unchanged" },
586
+ { kind: "Postgres::Table", name: "app.users", action: "updated" },
587
+ ],
588
+ [{ kind: "Postgres::Table", name: "app.old", deleted: true }],
589
+ [{ kind: "Postgres::Table", name: "app.orders", reason: "unsupported-kind", detail: "SQLPG205 Rename a column" }],
590
+ );
591
+ expect(await applyPostgres({ target: "postgres", env: "prod" }, applier)).toEqual({ applied: 2, pruned: 1, notAttempted: 1 });
592
+ });
593
+
594
+ test("with nothing injected it resolves the real sql lexicon's postgresApply", async () => {
595
+ const err = await nativeApply({ target: "postgres", env: "prod", output: "/nonexistent/chant-3280-schema.json" }).catch((e: unknown) => e);
596
+ expect(String(err)).toMatch(/ENOENT|no such file/);
597
+ expect(String(err)).not.toMatch(/could not be loaded/);
598
+ });
599
+ });
600
+
418
601
  describe("nativeApply: cloudformation dispatches to the aws lexicon (chant #1449)", () => {
419
602
  /** Records what the applier was handed, and reports a settled create. */
420
603
  const spy = (): { calls: Array<Parameters<AwsApplier>[0]>; applier: AwsApplier } => {
@@ -515,11 +698,11 @@ describe("compensateApply: cloudformation rolls back through the aws lexicon (ch
515
698
  expect(result).toEqual({ command: "echo custom-rollback" });
516
699
  });
517
700
 
518
- test("kubectl / kustomize / arm / gcp / fly without a command throw — the defensive branch (#1449)", async () => {
701
+ test("kubectl / kustomize / arm / gcp / fly / grafana / clickhouse / postgres without a command throw — the defensive branch (#1449)", async () => {
519
702
  // Unreachable from a built ApplyOp, which refuses this combination at
520
703
  // build time. A hand-assembled op that reaches it fails loudly rather than
521
704
  // returning a result that could read as a revert.
522
- for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly"] as const) {
705
+ for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres"] as const) {
523
706
  const err = await compensateApply({ target, env: "prod" }).catch((e: unknown) => e);
524
707
  expect(String(err)).toMatch(`no automatic rollback for target "${target}"`);
525
708
  expect(String(err)).toMatch(/NOT\s+reverted/);
@@ -529,7 +712,7 @@ describe("compensateApply: cloudformation rolls back through the aws lexicon (ch
529
712
 
530
713
  test("hasNativeRollback: cloudformation only", () => {
531
714
  expect(hasNativeRollback("cloudformation")).toBe(true);
532
- for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly"] as const) {
715
+ for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres"] as const) {
533
716
  expect(hasNativeRollback(target)).toBe(false);
534
717
  }
535
718
  });
@@ -557,11 +740,12 @@ describe("compensateApply: cloudformation rolls back through the aws lexicon (ch
557
740
  });
558
741
 
559
742
  describe('defaultOutput (target-aware apply output)', () => {
560
- test('kubectl → dist (dir); cloudformation/arm → template.json (file); gcp → dist/gcp.yaml; fly → dist/fly.json', () => {
743
+ test('kubectl → dist (dir); cloudformation/arm → template.json (file); gcp → dist/gcp.yaml; fly → dist/fly.json; grafana → dist/grafana.json', () => {
561
744
  expect(defaultOutput('kubectl')).toBe('dist');
562
745
  expect(defaultOutput('cloudformation')).toBe('template.json');
563
746
  expect(defaultOutput('arm')).toBe('template.json');
564
747
  expect(defaultOutput('gcp')).toBe('dist/gcp.yaml');
565
748
  expect(defaultOutput('fly')).toBe('dist/fly.json');
749
+ expect(defaultOutput('grafana')).toBe('dist/grafana.json');
566
750
  });
567
751
  });
@@ -21,6 +21,14 @@
21
21
  * per-resource `gcpApply` and the fly lexicon's `flyApply`, which never had a
22
22
  * CLI in the path to begin with: gcp maps each CNRM kind to its REST API
23
23
  * itself, and fly speaks the Machines API (flaps) directly, no flyctl.
24
+ * `grafana` joined later (#3011): the grafana lexicon's `grafanaApply`, which
25
+ * writes folders, library panels and dashboards over Grafana's HTTP API.
26
+ * `clickhouse` joined after it (#3208): the sql lexicon's `clickhouseApply`,
27
+ * which sends a ClickHouse server the CREATE and ALTER statements a build's
28
+ * classified changes need, over its HTTP interface. `postgres` joined after
29
+ * that (#3280): the sql lexicon's `postgresApply`, which sends a Postgres
30
+ * server the statements a build's classified changes need, grouped into
31
+ * transactions, with `CONCURRENTLY` statements outside them.
24
32
  * **The dispatcher stayed here**, because "which
25
33
  * mechanism applies this target" is not any one product's knowledge — and
26
34
  * because the activity keeps its name, its arguments and its place in
@@ -40,7 +48,7 @@ import { importLexiconPackage } from "../../lexicon-module";
40
48
  const execAsync = promisify(exec);
41
49
 
42
50
  /** The native apply mechanism for a target. */
43
- export type ApplyTarget = "cloudformation" | "kubectl" | "arm" | "kustomize" | "gcp" | "fly";
51
+ export type ApplyTarget = "cloudformation" | "kubectl" | "arm" | "kustomize" | "gcp" | "fly" | "grafana" | "clickhouse" | "postgres";
44
52
 
45
53
  /**
46
54
  * How apply treats resources no longer declared.
@@ -52,7 +60,16 @@ export type ApplyTarget = "cloudformation" | "kubectl" | "arm" | "kustomize" | "
52
60
  * ownership label (via the gcp lexicon's `gcpApply` — only kinds it can
53
61
  * list; the rest are reported not-prunable), `fly` prunes machines by the
54
62
  * metadata marker and the metadata-less types (volumes/ips/certs/secrets)
55
- * app-scoped under a managed app (via the fly lexicon's `flyApply`), and
63
+ * app-scoped under a managed app (via the fly lexicon's `flyApply`),
64
+ * `grafana` prunes dashboards and folders by the ownership labels (via the
65
+ * grafana lexicon's `grafanaApply`; library panels, Grafana 11 and a project
66
+ * with no ownership stack are reported not-prunable), `clickhouse` drops
67
+ * tables, views and databases whose comment carries the project's marker
68
+ * (via the sql lexicon's `clickhouseApply`; a project with no ownership
69
+ * stack is reported not-prunable), `postgres` drops the objects in the
70
+ * declared schemas whose comment carries the project's marker (via the sql
71
+ * lexicon's `postgresApply`; never an object another tool keeps, and a
72
+ * project with no ownership stack is reported not-prunable), and
56
73
  * `cloudformation` is bounded by the stack — which holds, because a
57
74
  * resource CFN did not create is not in the stack.
58
75
  * - `gated` — same delete scope as `owned-only`, but an approval gate precedes
@@ -66,7 +83,11 @@ export interface NativeApplyArgs {
66
83
  target: ApplyTarget;
67
84
  /** Environment. What it means is per target: the CFN stack name on
68
85
  * `cloudformation`, the ARM resource group on `arm`, the chant environment
69
- * on `kubectl`/`kustomize`. On `gcp` and `fly` it is a log label only — the
86
+ * on `kubectl`/`kustomize`, and on `grafana` the chant environment whose
87
+ * `grafana.profiles.<env>` names the Grafana to write to, and on
88
+ * `clickhouse` and `postgres` the chant environment whose
89
+ * `sql.profiles.<env>` names the server. On `gcp` and
90
+ * `fly` it is a log label only — the
70
91
  * gcp applier resolves the project (`GOOGLE_CLOUD_PROJECT` env / CNRM
71
92
  * annotation) and endpoint (`GCP_ENDPOINT_URL` env) itself, and the fly
72
93
  * applier resolves its endpoint (`FLY_FLAPS_BASE_URL` env) and token
@@ -74,7 +95,9 @@ export interface NativeApplyArgs {
74
95
  env: string;
75
96
  /** Built manifest/template path. Default per target ({@link defaultOutput}):
76
97
  * `dist` (a dir) for kubectl, `template.json` (a file) for
77
- * CloudFormation/ARM, `dist/gcp.yaml` for gcp, `dist/fly.json` for fly. */
98
+ * CloudFormation/ARM, `dist/gcp.yaml` for gcp, `dist/fly.json` for fly,
99
+ * `dist/grafana.json` (the build index) for grafana, `dist/schema.json`
100
+ * (the sql lexicon's build output) for clickhouse and postgres. */
78
101
  output?: string;
79
102
  /** Delete handling. Default: never. */
80
103
  deleteMode?: DeleteMode;
@@ -182,6 +205,57 @@ export type FlyApplier = (
182
205
  signal?: AbortSignal,
183
206
  ) => Promise<ApplyResult>;
184
207
 
208
+ /**
209
+ * The grafana lexicon's API applier, as this module needs to call it (#3011):
210
+ * `grafanaApply` composed with the lexicon's own `toApplyResult` projection,
211
+ * so what crosses this seam is core's versioned apply envelope (#1446).
212
+ *
213
+ * `environment` selects `grafana.profiles.<environment>` (else `GRAFANA_URL`
214
+ * with `GRAFANA_TOKEN`), the binding observe and export use. The ownership
215
+ * marker is not passed: `grafanaApply` reads `ownership` from the project's
216
+ * `chant.config.ts` itself, and a prune without a stack declines as
217
+ * not-prunable rather than delete another project's dashboards.
218
+ */
219
+ export type GrafanaApplier = (
220
+ args: {
221
+ indexPath: string;
222
+ environment?: string;
223
+ prune?: boolean;
224
+ },
225
+ signal?: AbortSignal,
226
+ ) => Promise<ApplyResult>;
227
+
228
+ /**
229
+ * The sql lexicon's ClickHouse applier, as this module needs to call it
230
+ * (#3208): `clickhouseApply` composed with the lexicon's own `toApplyResult`
231
+ * projection, so what crosses this seam is core's versioned apply envelope
232
+ * (#1446). A rebuild-class change rides it as NOT-ATTEMPTED.
233
+ *
234
+ * `environment` selects `sql.profiles.<environment>` (else `CLICKHOUSE_URL`),
235
+ * the binding observe and import use. The ownership marker is not passed:
236
+ * `clickhouseApply` reads `ownership` from the project's `chant.config.ts`.
237
+ */
238
+ export type ClickHouseApplier = (
239
+ args: {
240
+ buildPath: string;
241
+ environment?: string;
242
+ prune?: boolean;
243
+ },
244
+ signal?: AbortSignal,
245
+ ) => Promise<ApplyResult>;
246
+
247
+ /**
248
+ * The sql lexicon's Postgres applier, as this module needs to call it
249
+ * (#3280): `postgresApply` composed with the lexicon's own `toApplyResult`,
250
+ * the same seam as {@link ClickHouseApplier}. An expand-and-contract change
251
+ * and a rolled-back transaction's objects ride it as NOT-ATTEMPTED.
252
+ *
253
+ * `environment` selects `sql.profiles.<environment>` (else `POSTGRES_URL`).
254
+ * The ownership marker and the timeouts are not passed: `postgresApply`
255
+ * reads `ownership` and the profile from the project's `chant.config.ts`.
256
+ */
257
+ export type PostgresApplier = ClickHouseApplier;
258
+
185
259
  /**
186
260
  * The aws lexicon's CloudFormation applier, as this module needs to call it
187
261
  * (#1449). Structural, like {@link K8sApplier} and {@link AzureApplier}.
@@ -363,6 +437,102 @@ async function loadFlyApplier(): Promise<FlyApplier> {
363
437
  return async (args, signal) => toApplyResult(await flyApply(args, signal));
364
438
  }
365
439
 
440
+ /**
441
+ * Load the grafana lexicon's `grafanaApply` (#3011). Same variable-specifier
442
+ * trick as {@link loadK8sApplier}, for the same reason. The activities subpath,
443
+ * not the package root or `op/builders`: those hold the typed step builder,
444
+ * while the activity itself (and its `toApplyResult`) lives here.
445
+ */
446
+ async function loadGrafanaApplier(): Promise<GrafanaApplier> {
447
+ const spec = "@intentius/chant-lexicon-grafana/op/activities";
448
+ type GrafanaModule = {
449
+ grafanaApply?: (args: Parameters<GrafanaApplier>[0], signal?: AbortSignal) => Promise<unknown>;
450
+ toApplyResult?: (result: unknown) => ApplyResult;
451
+ };
452
+ let mod: GrafanaModule;
453
+ try {
454
+ mod = (await importLexiconPackage(spec)) as GrafanaModule;
455
+ } catch (err) {
456
+ throw new Error(
457
+ `apply target "grafana" needs @intentius/chant-lexicon-grafana, which could not be loaded ` +
458
+ `(${err instanceof Error ? err.message : String(err)}). Grafana applies go through the grafana ` +
459
+ `lexicon's API applier (chant #2948); install the grafana lexicon and list it in chant.config.ts.`,
460
+ );
461
+ }
462
+ const { grafanaApply, toApplyResult } = mod;
463
+ if (typeof grafanaApply !== "function") {
464
+ throw new Error(
465
+ "the installed @intentius/chant-lexicon-grafana exports no grafanaApply — it predates chant #2948",
466
+ );
467
+ }
468
+ if (typeof toApplyResult !== "function") {
469
+ throw new Error(
470
+ "the installed @intentius/chant-lexicon-grafana exports no toApplyResult — it predates chant #2948",
471
+ );
472
+ }
473
+ return async (args, signal) => toApplyResult(await grafanaApply(args, signal));
474
+ }
475
+
476
+ /**
477
+ * Load the sql lexicon's `clickhouseApply` (#3208). Same variable-specifier
478
+ * trick as {@link loadK8sApplier}, for the same reason.
479
+ */
480
+ async function loadClickHouseApplier(): Promise<ClickHouseApplier> {
481
+ const spec = "@intentius/chant-lexicon-sql/op/activities";
482
+ type SqlModule = {
483
+ clickhouseApply?: (args: Parameters<ClickHouseApplier>[0], signal?: AbortSignal) => Promise<unknown>;
484
+ toApplyResult?: (result: unknown) => ApplyResult;
485
+ };
486
+ let mod: SqlModule;
487
+ try {
488
+ mod = (await importLexiconPackage(spec)) as SqlModule;
489
+ } catch (err) {
490
+ throw new Error(
491
+ `apply target "clickhouse" needs @intentius/chant-lexicon-sql, which could not be loaded ` +
492
+ `(${err instanceof Error ? err.message : String(err)}). ClickHouse applies go through the sql ` +
493
+ `lexicon's applier (chant #3208); install the sql lexicon and list it in chant.config.ts.`,
494
+ );
495
+ }
496
+ const { clickhouseApply, toApplyResult } = mod;
497
+ if (typeof clickhouseApply !== "function") {
498
+ throw new Error("the installed @intentius/chant-lexicon-sql exports no clickhouseApply — it predates chant #3208");
499
+ }
500
+ if (typeof toApplyResult !== "function") {
501
+ throw new Error("the installed @intentius/chant-lexicon-sql exports no toApplyResult — it predates chant #3208");
502
+ }
503
+ return async (args, signal) => toApplyResult(await clickhouseApply(args, signal));
504
+ }
505
+
506
+ /**
507
+ * Load the sql lexicon's `postgresApply` (#3280). Same variable-specifier
508
+ * trick as {@link loadK8sApplier}, for the same reason.
509
+ */
510
+ async function loadPostgresApplier(): Promise<PostgresApplier> {
511
+ const spec = "@intentius/chant-lexicon-sql/op/activities";
512
+ type SqlModule = {
513
+ postgresApply?: (args: Parameters<PostgresApplier>[0], signal?: AbortSignal) => Promise<unknown>;
514
+ toApplyResult?: (result: unknown) => ApplyResult;
515
+ };
516
+ let mod: SqlModule;
517
+ try {
518
+ mod = (await importLexiconPackage(spec)) as SqlModule;
519
+ } catch (err) {
520
+ throw new Error(
521
+ `apply target "postgres" needs @intentius/chant-lexicon-sql, which could not be loaded ` +
522
+ `(${err instanceof Error ? err.message : String(err)}). Postgres applies go through the sql ` +
523
+ `lexicon's applier (chant #3280); install the sql lexicon and list it in chant.config.ts.`,
524
+ );
525
+ }
526
+ const { postgresApply, toApplyResult } = mod;
527
+ if (typeof postgresApply !== "function") {
528
+ throw new Error("the installed @intentius/chant-lexicon-sql exports no postgresApply — it predates chant #3280");
529
+ }
530
+ if (typeof toApplyResult !== "function") {
531
+ throw new Error("the installed @intentius/chant-lexicon-sql exports no toApplyResult — it predates chant #3208");
532
+ }
533
+ return async (args, signal) => toApplyResult(await postgresApply(args, signal));
534
+ }
535
+
366
536
  /**
367
537
  * Load the aws lexicon's `awsApply` (#1449). Same variable-specifier trick as
368
538
  * {@link loadK8sApplier}, for the same reason.
@@ -418,8 +588,11 @@ async function loadAwsRollback(): Promise<AwsRollback> {
418
588
  * manifests), so `dist`; kustomize's "output" is the kustomization DIRECTORY
419
589
  * the render reads. The file targets take the file their lexicon's build
420
590
  * conventionally emits: `template.json` for CloudFormation/ARM, `dist/gcp.yaml`
421
- * (the CNRM manifest) for gcp, `dist/fly.json` (the serialized plan) for fly.
422
- * Pure — exported for testing.
591
+ * (the CNRM manifest) for gcp, `dist/fly.json` (the serialized plan) for fly,
592
+ * `dist/grafana.json` (the index the grafana serializer writes, with the
593
+ * dashboard files beside it) for grafana, `dist/schema.json` (the sql
594
+ * lexicon's build output) for clickhouse and postgres. Pure — exported for
595
+ * testing.
423
596
  */
424
597
  export function defaultOutput(target: ApplyTarget): string {
425
598
  switch (target) {
@@ -430,6 +603,11 @@ export function defaultOutput(target: ApplyTarget): string {
430
603
  return "dist/gcp.yaml";
431
604
  case "fly":
432
605
  return "dist/fly.json";
606
+ case "grafana":
607
+ return "dist/grafana.json";
608
+ case "clickhouse":
609
+ case "postgres":
610
+ return "dist/schema.json";
433
611
  default:
434
612
  return "template.json";
435
613
  }
@@ -469,7 +647,9 @@ function collapseEnvelope(envelope: ApplyResult, label: string): NativeApplyResu
469
647
  * Apply declared source to the cloud via the target's native mechanism.
470
648
  * Deletes (when enabled) ride that mechanism's own delete path — marker-scoped
471
649
  * on `kubectl`, tag-scoped on `arm`, label-scoped on `gcp`, marker- and
472
- * app-scoped on `fly`, and stack-scoped on `cloudformation`, where the deploy
650
+ * app-scoped on `fly`, label-scoped on `grafana`, comment-marker-scoped on
651
+ * `clickhouse` and `postgres`, and stack-scoped on
652
+ * `cloudformation`, where the deploy
473
653
  * itself removes resources dropped from the template and `deleteMode` changes
474
654
  * nothing: a resource CFN did not create is not in the stack. See
475
655
  * {@link DeleteMode}.
@@ -477,7 +657,7 @@ function collapseEnvelope(envelope: ApplyResult, label: string): NativeApplyResu
477
657
  * The appliers are injectable so this dispatcher can be tested without the
478
658
  * product lexicons present; production resolves them through
479
659
  * {@link loadK8sApplier} / {@link loadAzureApplier} / {@link loadAwsApplier} /
480
- * {@link loadGcpApplier} / {@link loadFlyApplier}.
660
+ * {@link loadGcpApplier} / {@link loadFlyApplier} / {@link loadGrafanaApplier}.
481
661
  */
482
662
  export async function nativeApply(
483
663
  args: NativeApplyArgs,
@@ -488,6 +668,9 @@ export async function nativeApply(
488
668
  awsApplier?: AwsApplier,
489
669
  gcpApplier?: GcpApplier,
490
670
  flyApplier?: FlyApplier,
671
+ grafanaApplier?: GrafanaApplier,
672
+ clickhouseApplier?: ClickHouseApplier,
673
+ postgresApplier?: PostgresApplier,
491
674
  ): Promise<NativeApplyResult> {
492
675
  const output = args.output ?? defaultOutput(args.target);
493
676
  const deleteMode = args.deleteMode ?? "never";
@@ -568,6 +751,45 @@ export async function nativeApply(
568
751
  return collapseEnvelope(envelope, args.env);
569
752
  }
570
753
 
754
+ if (args.target === "grafana") {
755
+ // grafana (#3011): the grafana lexicon's API applier. Unlike gcp and fly,
756
+ // env is not just a label here: it selects `grafana.profiles.<env>`, the
757
+ // Grafana observe and export already read. The ownership marker comes from
758
+ // the project's chant.config.ts inside grafanaApply.
759
+ const apply = grafanaApplier ?? (await loadGrafanaApplier());
760
+ const envelope = await apply(
761
+ { indexPath: output, environment: args.env, prune: deleteMode !== "never" },
762
+ signal,
763
+ );
764
+ // No binding or a refused token rides the envelope as NOT-ATTEMPTED for
765
+ // every resource, as do library panels and anything else prune could
766
+ // not consider.
767
+ return collapseEnvelope(envelope, args.env);
768
+ }
769
+
770
+ if (args.target === "clickhouse") {
771
+ // clickhouse (#3208): the sql lexicon's applier. env selects
772
+ // `sql.profiles.<env>`, the server observe and import read; the marker
773
+ // comes from the project's chant.config.ts inside clickhouseApply.
774
+ const apply = clickhouseApplier ?? (await loadClickHouseApplier());
775
+ const envelope = await apply({ buildPath: output, environment: args.env, prune: deleteMode !== "never" }, signal);
776
+ // A refused rebuild and a column drop an additive apply withholds ride the
777
+ // envelope as NOT-ATTEMPTED, so an Op can gate on them.
778
+ return collapseEnvelope(envelope, args.env);
779
+ }
780
+
781
+ if (args.target === "postgres") {
782
+ // postgres (#3280): the sql lexicon's applier. env selects
783
+ // `sql.profiles.<env>`; the marker and the lock and statement timeouts
784
+ // come from the project's chant.config.ts inside postgresApply.
785
+ const apply = postgresApplier ?? (await loadPostgresApplier());
786
+ const envelope = await apply({ buildPath: output, environment: args.env, prune: deleteMode !== "never" }, signal);
787
+ // A refused expand-and-contract change, a column drop an additive apply
788
+ // withholds, and the objects of a rolled-back transaction ride the
789
+ // envelope as NOT-ATTEMPTED, so an Op can gate on them.
790
+ return collapseEnvelope(envelope, args.env);
791
+ }
792
+
571
793
  // cloudformation (#1449): the aws lexicon's native applier. env is the stack
572
794
  // name and output the template path; endpoint resolution (#1694) and
573
795
  // capability derivation (#980) are awsApply's own, so nothing else is passed.
@@ -70,6 +70,9 @@ export type {
70
70
  AzureApplier,
71
71
  GcpApplier,
72
72
  FlyApplier,
73
+ GrafanaApplier,
74
+ ClickHouseApplier,
75
+ PostgresApplier,
73
76
  AwsApplier,
74
77
  AwsRollback,
75
78
  } from "./apply";