okengine 0.2.6 → 0.3.2

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 (681) hide show
  1. package/AGENTS.md +33 -30
  2. package/README.md +74 -340
  3. package/{spec/manifest.v1.schema.json → manifest.v1.schema.json} +40 -9
  4. package/package.json +47 -44
  5. package/site/content/docs/ai/llms-txt.mdx +54 -0
  6. package/site/content/docs/ai/mcp.mdx +123 -0
  7. package/site/content/docs/ai/meta.json +5 -0
  8. package/site/content/docs/ai/skills.mdx +53 -0
  9. package/site/content/docs/console/access.mdx +29 -0
  10. package/site/content/docs/console/ai.mdx +35 -0
  11. package/site/content/docs/console/architecture.mdx +35 -0
  12. package/site/content/docs/console/channels.mdx +37 -0
  13. package/site/content/docs/console/clock.mdx +31 -0
  14. package/site/content/docs/console/flows.mdx +31 -0
  15. package/site/content/docs/console/gates.mdx +35 -0
  16. package/site/content/docs/console/manifest-diff.mdx +34 -0
  17. package/site/content/docs/console/meta.json +23 -0
  18. package/site/content/docs/console/overview.mdx +40 -0
  19. package/site/content/docs/console/plugins.mdx +41 -0
  20. package/site/content/docs/console/privacy.mdx +32 -0
  21. package/site/content/docs/console/runs.mdx +40 -0
  22. package/site/content/docs/console/signals.mdx +31 -0
  23. package/site/content/docs/console/store.mdx +32 -0
  24. package/site/content/docs/console/tenancy.mdx +32 -0
  25. package/site/content/docs/console/traces.mdx +34 -0
  26. package/site/content/docs/console/vault.mdx +37 -0
  27. package/site/content/docs/elements/ai.mdx +180 -0
  28. package/site/content/docs/elements/channel.mdx +167 -0
  29. package/site/content/docs/elements/clock.mdx +182 -0
  30. package/site/content/docs/elements/flow.mdx +288 -0
  31. package/site/content/docs/elements/gate.mdx +171 -0
  32. package/site/content/docs/elements/meta.json +5 -0
  33. package/site/content/docs/elements/signal.mdx +171 -0
  34. package/site/content/docs/elements/store.mdx +320 -0
  35. package/site/content/docs/elements/vault.mdx +263 -0
  36. package/site/content/docs/get-started/basic-usage.mdx +124 -0
  37. package/site/content/docs/get-started/comparison.mdx +65 -0
  38. package/site/content/docs/get-started/installation.mdx +113 -0
  39. package/site/content/docs/get-started/introduction.mdx +123 -0
  40. package/site/content/docs/get-started/meta.json +5 -0
  41. package/site/content/docs/index.mdx +63 -0
  42. package/site/content/docs/meta.json +5 -0
  43. package/site/content/docs/plugins/compression.mdx +60 -0
  44. package/site/content/docs/plugins/cors.mdx +92 -0
  45. package/site/content/docs/plugins/csrf.mdx +96 -0
  46. package/site/content/docs/plugins/ip-allowlist.mdx +92 -0
  47. package/site/content/docs/plugins/maintenance-mode.mdx +101 -0
  48. package/site/content/docs/plugins/meta.json +15 -0
  49. package/site/content/docs/plugins/security-headers.mdx +136 -0
  50. package/site/content/docs/reference/cli.md +101 -0
  51. package/site/content/docs/reference/configuration.mdx +159 -0
  52. package/site/content/docs/reference/environment-variables.mdx +87 -0
  53. package/site/content/docs/reference/errors.mdx +80 -0
  54. package/site/content/docs/reference/fx.mdx +117 -0
  55. package/site/content/docs/reference/meta.json +5 -0
  56. package/site/content/docs/reference/plugins.mdx +249 -0
  57. package/site/content/docs/reference/security.md +63 -0
  58. package/src/auth/api-keys.ts +2 -5
  59. package/src/auth/attenuation.ts +2 -6
  60. package/src/auth/auth.test.ts +56 -31
  61. package/src/auth/invoke-as.ts +1 -3
  62. package/src/auth/operator.ts +8 -26
  63. package/src/auth/planes.ts +2 -7
  64. package/src/auth/plugin.ts +4 -7
  65. package/src/auth/roles.ts +1 -5
  66. package/src/auth/sessions.ts +10 -39
  67. package/src/cli/args.ts +1 -5
  68. package/src/cli/ask-dev-mode.ts +40 -0
  69. package/src/cli/build.ts +1 -2
  70. package/src/cli/client-add.test.ts +8 -15
  71. package/src/cli/client-add.ts +5 -14
  72. package/src/cli/completion.test.ts +1 -5
  73. package/src/cli/completion.ts +4 -17
  74. package/src/cli/db-auto-push.test.ts +64 -0
  75. package/src/cli/db-auto-push.ts +72 -0
  76. package/src/cli/db.test.ts +189 -0
  77. package/src/cli/db.ts +456 -0
  78. package/src/cli/dev-app-runner.ts +2 -8
  79. package/src/cli/dev-db-push.test.ts +193 -0
  80. package/src/cli/dev-mode.test.ts +45 -0
  81. package/src/cli/dev-mode.ts +78 -0
  82. package/src/cli/dev-schema-sync.test.ts +66 -0
  83. package/src/cli/dev-schema-sync.ts +139 -0
  84. package/src/cli/dev.test.ts +264 -15
  85. package/src/cli/dev.ts +355 -139
  86. package/src/cli/doc-staleness.test.ts +69 -0
  87. package/src/cli/docker-cli.test.ts +27 -8
  88. package/src/cli/docker.ts +11 -3
  89. package/src/cli/doctor-diff.test.ts +1 -5
  90. package/src/cli/doctor-diff.ts +17 -46
  91. package/src/cli/doctor-pii.ts +2 -7
  92. package/src/cli/doctor.test.ts +26 -4
  93. package/src/cli/doctor.ts +35 -11
  94. package/src/cli/drizzle-env.test.ts +67 -0
  95. package/src/cli/drizzle-env.ts +78 -0
  96. package/src/cli/ensure-drizzle-config.ts +50 -0
  97. package/src/cli/eval.ts +4 -14
  98. package/src/cli/gates-list.ts +1 -4
  99. package/src/cli/hero-meta.test.ts +17 -19
  100. package/src/cli/hero-meta.ts +20 -30
  101. package/src/cli/images.ts +3 -8
  102. package/src/cli/index.ts +11 -2
  103. package/src/cli/load-config.images.test.ts +14 -14
  104. package/src/cli/load-config.ts +47 -47
  105. package/src/cli/mcp-from-console.ts +1 -4
  106. package/src/cli/mode.ts +65 -0
  107. package/src/cli/openbao-bootstrap.test.ts +147 -0
  108. package/src/cli/openbao-bootstrap.ts +280 -0
  109. package/src/cli/openbao-restart.integration.test.ts +136 -0
  110. package/src/cli/ports.test.ts +7 -14
  111. package/src/cli/ports.ts +7 -5
  112. package/src/cli/privacy-erase.ts +1 -3
  113. package/src/cli/registry.ts +75 -25
  114. package/src/cli/resolve-dev-sql-env.test.ts +48 -0
  115. package/src/cli/resolve-dev-sql-env.ts +42 -0
  116. package/src/cli/schema.ts +3 -10
  117. package/src/cli/stack.ts +8 -10
  118. package/src/cli/start.ts +4 -15
  119. package/src/cli/upgrade.ts +1 -4
  120. package/src/cli/vault-cmd.ts +63 -0
  121. package/src/client/budget-entry.ts +1 -6
  122. package/src/client/create.test.ts +6 -12
  123. package/src/client/create.ts +2 -8
  124. package/src/client/errors.ts +1 -4
  125. package/src/client/index.ts +1 -6
  126. package/src/client/notes-contract.test.ts +4 -13
  127. package/src/client/transport.ts +9 -30
  128. package/src/client/types.ts +15 -30
  129. package/src/compiler/aot.test.ts +2 -9
  130. package/src/compiler/aot.ts +1 -4
  131. package/src/compiler/differential.test.ts +3 -11
  132. package/src/compiler/dynamic.ts +1 -4
  133. package/src/compiler/effects-infer.ts +8 -34
  134. package/src/compiler/emit.ts +1 -3
  135. package/src/compiler/extract.test.ts +136 -30
  136. package/src/compiler/extract.ts +485 -157
  137. package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
  138. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
  139. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
  140. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
  141. package/src/compiler/fixtures/skyport.expected.json +24 -83
  142. package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
  143. package/src/compiler/http-parse.ts +2 -9
  144. package/src/compiler/index.ts +1 -5
  145. package/src/compiler/response.ts +16 -7
  146. package/src/compiler/sucrose.ts +11 -31
  147. package/src/config/define-config.test.ts +55 -34
  148. package/src/config/index.ts +177 -46
  149. package/src/config/resolve-driver.test.ts +28 -17
  150. package/src/console/budget.test.ts +1 -4
  151. package/src/console/index.ts +1 -4
  152. package/src/console/server/access.test.ts +15 -43
  153. package/src/console/server/access.ts +19 -49
  154. package/src/console/server/ai.test.ts +3 -11
  155. package/src/console/server/ai.ts +23 -46
  156. package/src/console/server/app.ts +16 -45
  157. package/src/console/server/auth-rate.test.ts +4 -12
  158. package/src/console/server/bind.ts +1 -5
  159. package/src/console/server/channels.test.ts +2 -6
  160. package/src/console/server/channels.ts +10 -35
  161. package/src/console/server/claim.ts +2 -8
  162. package/src/console/server/clock.test.ts +2 -6
  163. package/src/console/server/clock.ts +8 -26
  164. package/src/console/server/console.test.ts +1 -3
  165. package/src/console/server/diff.test.ts +5 -17
  166. package/src/console/server/diff.ts +10 -31
  167. package/src/console/server/dry-run.audit.test.ts +2 -8
  168. package/src/console/server/flows.ts +64 -233
  169. package/src/console/server/gates.test.ts +14 -50
  170. package/src/console/server/gates.ts +13 -48
  171. package/src/console/server/index.ts +2 -9
  172. package/src/console/server/live.ts +3 -12
  173. package/src/console/server/operator-db.test.ts +4 -15
  174. package/src/console/server/operator-db.ts +13 -32
  175. package/src/console/server/plugin.ts +50 -53
  176. package/src/console/server/plugins.test.ts +2 -6
  177. package/src/console/server/plugins.ts +17 -56
  178. package/src/console/server/runs-pii.ts +2 -7
  179. package/src/console/server/security.gate.test.ts +18 -40
  180. package/src/console/server/serve.ts +10 -25
  181. package/src/console/server/signals.test.ts +1 -3
  182. package/src/console/server/signals.ts +17 -40
  183. package/src/console/server/state.ts +21 -59
  184. package/src/console/server/store.test.ts +20 -22
  185. package/src/console/server/store.ts +31 -76
  186. package/src/console/server/vault.test.ts +12 -29
  187. package/src/console/server/vault.ts +44 -66
  188. package/src/console/ui/access/AccessA11yView.tsx +6 -21
  189. package/src/console/ui/access/a11y.test.tsx +3 -12
  190. package/src/console/ui/access/acknowledgement.test.ts +1 -4
  191. package/src/console/ui/access/acknowledgement.ts +1 -3
  192. package/src/console/ui/access/blast-radius.ts +1 -3
  193. package/src/console/ui/access/confirmation.test.ts +1 -5
  194. package/src/console/ui/access/confirmation.ts +1 -4
  195. package/src/console/ui/access/fixture.ts +1 -5
  196. package/src/console/ui/access/grantable.test.ts +1 -3
  197. package/src/console/ui/access/grantable.ts +2 -7
  198. package/src/console/ui/access/index.ts +2 -9
  199. package/src/console/ui/access/provenance.test.ts +1 -3
  200. package/src/console/ui/access/provenance.ts +2 -6
  201. package/src/console/ui/access/search.test.ts +1 -5
  202. package/src/console/ui/access/search.ts +2 -6
  203. package/src/console/ui/ai/AiA11yView.tsx +6 -17
  204. package/src/console/ui/ai/a11y.test.tsx +2 -5
  205. package/src/console/ui/ai/fixture.ts +2 -7
  206. package/src/console/ui/ai/format.ts +1 -3
  207. package/src/console/ui/ai/group.test.ts +1 -3
  208. package/src/console/ui/ai/group.ts +4 -12
  209. package/src/console/ui/ai/index.ts +2 -9
  210. package/src/console/ui/ai/promotion.test.ts +2 -7
  211. package/src/console/ui/ai/promotion.ts +4 -13
  212. package/src/console/ui/ai/search.test.ts +2 -11
  213. package/src/console/ui/ai/search.ts +3 -13
  214. package/src/console/ui/ai/types.ts +1 -8
  215. package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
  216. package/src/console/ui/architecture/a11y.test.tsx +1 -2
  217. package/src/console/ui/architecture/declared.ts +1 -5
  218. package/src/console/ui/architecture/index.ts +7 -35
  219. package/src/console/ui/architecture/layout.ts +1 -3
  220. package/src/console/ui/architecture/pathologies.ts +10 -19
  221. package/src/console/ui/architecture/search.ts +6 -15
  222. package/src/console/ui/architecture/traffic.ts +4 -14
  223. package/src/console/ui/architecture/types.ts +2 -10
  224. package/src/console/ui/architecture/view.test.ts +7 -19
  225. package/src/console/ui/architecture/view.ts +9 -36
  226. package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
  227. package/src/console/ui/channels/a11y.test.tsx +1 -2
  228. package/src/console/ui/channels/confirmation.test.ts +1 -4
  229. package/src/console/ui/channels/confirmation.ts +1 -4
  230. package/src/console/ui/channels/findings.ts +1 -5
  231. package/src/console/ui/channels/index.ts +2 -8
  232. package/src/console/ui/channels/locale.test.ts +1 -3
  233. package/src/console/ui/channels/locale.ts +2 -8
  234. package/src/console/ui/channels/search.ts +4 -13
  235. package/src/console/ui/channels/taxonomy.ts +1 -3
  236. package/src/console/ui/clock/ClockA11yView.tsx +9 -26
  237. package/src/console/ui/clock/a11y.test.tsx +2 -5
  238. package/src/console/ui/clock/confirmation.test.ts +1 -3
  239. package/src/console/ui/clock/confirmation.ts +1 -4
  240. package/src/console/ui/clock/findings.ts +1 -4
  241. package/src/console/ui/clock/health.ts +2 -7
  242. package/src/console/ui/clock/index.ts +2 -10
  243. package/src/console/ui/clock/search.test.ts +1 -3
  244. package/src/console/ui/clock/search.ts +2 -6
  245. package/src/console/ui/clock/timeline.test.ts +1 -3
  246. package/src/console/ui/clock/waiting-on.test.ts +1 -5
  247. package/src/console/ui/clock/waiting-on.ts +2 -7
  248. package/src/console/ui/diff/DiffA11yView.tsx +8 -17
  249. package/src/console/ui/diff/a11y.test.tsx +2 -5
  250. package/src/console/ui/diff/group.test.ts +3 -13
  251. package/src/console/ui/diff/group.ts +2 -8
  252. package/src/console/ui/diff/index.ts +2 -8
  253. package/src/console/ui/diff/search.test.ts +1 -5
  254. package/src/console/ui/diff/search.ts +4 -16
  255. package/src/console/ui/diff/summary.ts +1 -2
  256. package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
  257. package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
  258. package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
  259. package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
  260. package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
  261. package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
  262. package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
  263. package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
  264. package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
  265. package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
  266. package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
  267. package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
  268. package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
  269. package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
  270. package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
  271. package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
  272. package/src/console/ui/dist/index.html +1 -1
  273. package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
  274. package/src/console/ui/flows/a11y.test.tsx +2 -8
  275. package/src/console/ui/flows/buffer.test.ts +3 -11
  276. package/src/console/ui/flows/buffer.ts +4 -11
  277. package/src/console/ui/flows/confirmation.ts +1 -3
  278. package/src/console/ui/flows/contract.test.ts +3 -7
  279. package/src/console/ui/flows/contract.ts +12 -36
  280. package/src/console/ui/flows/graph.test.ts +3 -11
  281. package/src/console/ui/flows/graph.ts +5 -15
  282. package/src/console/ui/flows/index.ts +1 -6
  283. package/src/console/ui/flows/save-as-test.ts +1 -3
  284. package/src/console/ui/flows/search.ts +8 -25
  285. package/src/console/ui/flows/tiers.ts +2 -9
  286. package/src/console/ui/gates/GatesA11yView.tsx +4 -13
  287. package/src/console/ui/gates/a11y.test.tsx +2 -5
  288. package/src/console/ui/gates/audit.ts +1 -3
  289. package/src/console/ui/gates/denial.test.ts +1 -3
  290. package/src/console/ui/gates/denial.ts +4 -12
  291. package/src/console/ui/gates/findings.ts +1 -3
  292. package/src/console/ui/gates/group.test.ts +3 -3
  293. package/src/console/ui/gates/group.ts +3 -11
  294. package/src/console/ui/gates/index.ts +2 -10
  295. package/src/console/ui/gates/search.ts +3 -10
  296. package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
  297. package/src/console/ui/overview/a11y.test.tsx +1 -2
  298. package/src/console/ui/overview/busiest.ts +1 -3
  299. package/src/console/ui/overview/compose.ts +1 -13
  300. package/src/console/ui/overview/cost.ts +34 -38
  301. package/src/console/ui/overview/fixture.ts +21 -26
  302. package/src/console/ui/overview/golden.ts +4 -14
  303. package/src/console/ui/overview/index.ts +2 -9
  304. package/src/console/ui/overview/rank.test.ts +3 -10
  305. package/src/console/ui/overview/rank.ts +2 -7
  306. package/src/console/ui/overview/slo.test.ts +5 -9
  307. package/src/console/ui/overview/slo.ts +6 -23
  308. package/src/console/ui/overview/verdict.ts +3 -10
  309. package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
  310. package/src/console/ui/plugins/a11y.test.tsx +1 -2
  311. package/src/console/ui/plugins/fixture.ts +2 -4
  312. package/src/console/ui/plugins/group.test.ts +1 -3
  313. package/src/console/ui/plugins/group.ts +1 -6
  314. package/src/console/ui/plugins/index.ts +3 -13
  315. package/src/console/ui/plugins/search.ts +7 -19
  316. package/src/console/ui/runs/RunsA11yView.tsx +5 -20
  317. package/src/console/ui/runs/a11y.test.tsx +2 -5
  318. package/src/console/ui/runs/explain.ts +2 -6
  319. package/src/console/ui/runs/group.ts +3 -12
  320. package/src/console/ui/runs/histogram.test.ts +2 -11
  321. package/src/console/ui/runs/histogram.ts +1 -4
  322. package/src/console/ui/runs/index.ts +4 -18
  323. package/src/console/ui/runs/project.ts +2 -6
  324. package/src/console/ui/runs/query.test.ts +1 -3
  325. package/src/console/ui/runs/query.ts +12 -35
  326. package/src/console/ui/runs/search.ts +5 -19
  327. package/src/console/ui/runs/trace-link.test.ts +2 -6
  328. package/src/console/ui/runs/trace-link.ts +4 -16
  329. package/src/console/ui/runs/types.ts +1 -3
  330. package/src/console/ui/shell/App.tsx +2 -10
  331. package/src/console/ui/shell/client.ts +22 -115
  332. package/src/console/ui/shell/components/ui.tsx +1 -4
  333. package/src/console/ui/shell/layout/Shell.tsx +2 -4
  334. package/src/console/ui/shell/main.tsx +31 -96
  335. package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
  336. package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
  337. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
  338. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
  339. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
  340. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
  341. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
  342. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
  343. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
  344. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
  345. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
  346. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
  347. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
  348. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
  349. package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
  350. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
  351. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
  352. package/src/console/ui/shell/setup/Wizard.tsx +3 -5
  353. package/src/console/ui/shell/styles.css +1 -2
  354. package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
  355. package/src/console/ui/signals/a11y.test.tsx +2 -5
  356. package/src/console/ui/signals/confirmation.test.ts +1 -5
  357. package/src/console/ui/signals/confirmation.ts +2 -6
  358. package/src/console/ui/signals/dry-run.ts +1 -3
  359. package/src/console/ui/signals/durable.ts +1 -3
  360. package/src/console/ui/signals/findings.ts +1 -3
  361. package/src/console/ui/signals/group.test.ts +2 -8
  362. package/src/console/ui/signals/group.ts +2 -10
  363. package/src/console/ui/signals/index.ts +1 -4
  364. package/src/console/ui/signals/monitor.ts +2 -7
  365. package/src/console/ui/signals/schema-form.test.ts +3 -14
  366. package/src/console/ui/signals/schema-form.ts +1 -4
  367. package/src/console/ui/signals/search.ts +4 -13
  368. package/src/console/ui/store/StoreA11yView.tsx +3 -9
  369. package/src/console/ui/store/a11y.test.tsx +2 -5
  370. package/src/console/ui/store/confirmation.test.ts +1 -3
  371. package/src/console/ui/store/confirmation.ts +1 -4
  372. package/src/console/ui/store/dry-run.ts +2 -5
  373. package/src/console/ui/store/fixture.ts +1 -2
  374. package/src/console/ui/store/group.test.ts +1 -6
  375. package/src/console/ui/store/group.ts +1 -4
  376. package/src/console/ui/store/index.ts +1 -5
  377. package/src/console/ui/store/search.ts +2 -6
  378. package/src/console/ui/store/will-not-fire.ts +1 -2
  379. package/src/console/ui/traces/TracesA11yView.tsx +10 -29
  380. package/src/console/ui/traces/a11y.test.tsx +1 -2
  381. package/src/console/ui/traces/chain.test.ts +5 -19
  382. package/src/console/ui/traces/chain.ts +1 -3
  383. package/src/console/ui/traces/critical-path.test.ts +1 -3
  384. package/src/console/ui/traces/critical-path.ts +2 -6
  385. package/src/console/ui/traces/filter.test.ts +2 -6
  386. package/src/console/ui/traces/filter.ts +5 -13
  387. package/src/console/ui/traces/fold.test.ts +4 -12
  388. package/src/console/ui/traces/fold.ts +1 -3
  389. package/src/console/ui/traces/mini.ts +1 -3
  390. package/src/console/ui/traces/replay.test.ts +1 -3
  391. package/src/console/ui/traces/replay.ts +1 -3
  392. package/src/console/ui/traces/sampling.ts +1 -4
  393. package/src/console/ui/traces/search.ts +4 -17
  394. package/src/console/ui/traces/tier.ts +1 -3
  395. package/src/console/ui/vault/VaultA11yView.tsx +5 -17
  396. package/src/console/ui/vault/a11y.test.tsx +1 -2
  397. package/src/console/ui/vault/blast-radius.ts +1 -3
  398. package/src/console/ui/vault/confirmation.test.ts +1 -5
  399. package/src/console/ui/vault/confirmation.ts +1 -4
  400. package/src/console/ui/vault/dormant.test.ts +1 -4
  401. package/src/console/ui/vault/export-safe.test.ts +1 -5
  402. package/src/console/ui/vault/export-safe.ts +1 -4
  403. package/src/console/ui/vault/fixture.ts +3 -3
  404. package/src/console/ui/vault/group.ts +1 -2
  405. package/src/console/ui/vault/index.ts +2 -10
  406. package/src/console/ui/vault/search.ts +2 -6
  407. package/src/console/ui/vault/types.ts +1 -1
  408. package/src/console/xss.gate.test.ts +1 -3
  409. package/src/docker/compose.ts +215 -27
  410. package/src/docker/derive.ts +6 -14
  411. package/src/docker/docker.test.ts +118 -15
  412. package/src/docker/dockerfile.integration.test.ts +12 -21
  413. package/src/docker/helpers.ts +5 -4
  414. package/src/docker/index.ts +9 -6
  415. package/src/docker/pin.ts +1 -9
  416. package/src/docker/recipes/index.ts +6 -6
  417. package/src/docker/recipes/mailpit.ts +22 -0
  418. package/src/docker/recipes/openbao.ts +47 -0
  419. package/src/docker/recipes/postgres.ts +17 -6
  420. package/src/docker/recipes/redis.ts +11 -2
  421. package/src/docker/recipes/rustfs.ts +32 -0
  422. package/src/docker/stack-id.test.ts +73 -5
  423. package/src/docker/stack-id.ts +124 -33
  424. package/src/docker/stack.integration.test.ts +6 -21
  425. package/src/docker/stack.ts +36 -4
  426. package/src/docker/types.ts +16 -4
  427. package/src/docs-origin.ts +4 -4
  428. package/src/drivers/ai-anthropic.ts +5 -14
  429. package/src/drivers/ai-mock.ts +2 -5
  430. package/src/drivers/ai-openai-compatible.ts +4 -10
  431. package/src/drivers/ai-providers.test.ts +6 -13
  432. package/src/drivers/bun-native-completeness.test.ts +6 -15
  433. package/src/drivers/channel-console.ts +6 -7
  434. package/src/drivers/channel-fcm.ts +20 -30
  435. package/src/drivers/channel-resend.ts +1 -3
  436. package/src/drivers/channel-smtp.ts +2 -6
  437. package/src/drivers/channel-types.ts +2 -12
  438. package/src/drivers/channel-unifonic.ts +2 -6
  439. package/src/drivers/channel-wa-cloud.ts +2 -6
  440. package/src/drivers/channel-webpush.ts +21 -60
  441. package/src/drivers/conformance.test.ts +2 -10
  442. package/src/drivers/conformance.ts +8 -21
  443. package/src/drivers/drizzle-dialect.test.ts +20 -0
  444. package/src/drivers/drizzle-dialect.ts +37 -0
  445. package/src/drivers/fs.ts +2 -8
  446. package/src/drivers/index.ts +12 -57
  447. package/src/drivers/memory.ts +287 -75
  448. package/src/drivers/pgvector.ts +7 -11
  449. package/src/drivers/postgres.ts +7 -13
  450. package/src/drivers/redis.ts +13 -37
  451. package/src/drivers/s3.ts +15 -18
  452. package/src/drivers/signal-engine.ts +12 -49
  453. package/src/drivers/signal-memory.ts +2 -8
  454. package/src/drivers/signal-nats.ts +4 -9
  455. package/src/drivers/signal-postgres.ts +62 -129
  456. package/src/drivers/signal-redis.ts +7 -21
  457. package/src/drivers/signal-types.ts +1 -4
  458. package/src/drivers/sqlite.ts +3 -12
  459. package/src/drivers/types.ts +4 -23
  460. package/src/drivers/vault-driver-removal.test.ts +55 -0
  461. package/src/drivers/vault-env.ts +2 -6
  462. package/src/drivers/vault-infisical.ts +1 -5
  463. package/src/drivers/vault-managed.ts +1 -5
  464. package/src/drivers/vault-memory.ts +1 -5
  465. package/src/drivers/vault-openbao.test.ts +97 -0
  466. package/src/drivers/vault-openbao.ts +103 -40
  467. package/src/drivers/vault-types.ts +3 -16
  468. package/src/elements/ai/declare.ts +4 -14
  469. package/src/elements/ai/eval.ts +2 -6
  470. package/src/elements/ai/pii.ts +1 -3
  471. package/src/elements/ai/runtime.ts +12 -50
  472. package/src/elements/ai/schema.ts +4 -15
  473. package/src/elements/ai.test.ts +13 -24
  474. package/src/elements/ai.ts +1 -5
  475. package/src/elements/channel/consent.ts +3 -12
  476. package/src/elements/channel/costs.ts +4 -15
  477. package/src/elements/channel/declare.ts +1 -4
  478. package/src/elements/channel/email-auth.ts +1 -4
  479. package/src/elements/channel/locale.ts +2 -10
  480. package/src/elements/channel/mask.ts +1 -3
  481. package/src/elements/channel/mime.ts +2 -12
  482. package/src/elements/channel/outcomes.test.ts +1 -5
  483. package/src/elements/channel/outcomes.ts +5 -15
  484. package/src/elements/channel/receipts.ts +2 -7
  485. package/src/elements/channel/runtime.ts +28 -74
  486. package/src/elements/channel/suppression.ts +8 -14
  487. package/src/elements/channel.test.ts +8 -31
  488. package/src/elements/channel.ts +3 -14
  489. package/src/elements/clock/actions.ts +6 -18
  490. package/src/elements/clock/declare.ts +1 -3
  491. package/src/elements/clock/dst.ts +1 -5
  492. package/src/elements/clock/durable.ts +4 -16
  493. package/src/elements/clock/health.ts +2 -7
  494. package/src/elements/clock/leader.ts +2 -9
  495. package/src/elements/clock/reconcile.ts +4 -15
  496. package/src/elements/clock/runtime.ts +2 -5
  497. package/src/elements/clock/schedule.ts +4 -20
  498. package/src/elements/clock.test.ts +2 -7
  499. package/src/elements/clock.ts +5 -23
  500. package/src/elements/gate/permissions.ts +1 -4
  501. package/src/elements/gate/runtime.ts +7 -28
  502. package/src/elements/gate.ts +1 -5
  503. package/src/elements/index.ts +9 -7
  504. package/src/elements/signal/declare.ts +2 -7
  505. package/src/elements/signal/reconcile.test.ts +1 -4
  506. package/src/elements/signal/runtime.ts +1 -3
  507. package/src/elements/signal.test.ts +3 -15
  508. package/src/elements/signal.ts +2 -8
  509. package/src/elements/store/cache.test.ts +46 -0
  510. package/src/elements/store/cache.ts +3 -11
  511. package/src/elements/store/classify.ts +5 -22
  512. package/src/elements/store/declare.ts +11 -17
  513. package/src/elements/store/domain-ddl.test.ts +86 -0
  514. package/src/elements/store/emit-drizzle.ts +363 -0
  515. package/src/elements/store/files-policy.test.ts +1 -5
  516. package/src/elements/store/files-policy.ts +4 -12
  517. package/src/elements/store/load-plugin-tables.ts +103 -0
  518. package/src/elements/store/missing-relation.test.ts +83 -0
  519. package/src/elements/store/missing-relation.ts +38 -0
  520. package/src/elements/store/replica.ts +1 -4
  521. package/src/elements/store/resource-list-docs.fixture.ts +56 -0
  522. package/src/elements/store/resource-list-docs.test.ts +79 -0
  523. package/src/elements/store/resource.test.ts +253 -0
  524. package/src/elements/store/resource.ts +786 -0
  525. package/src/elements/store/runtime.ts +25 -28
  526. package/src/elements/store/schema-decl.test.ts +227 -0
  527. package/src/elements/store/schema-decl.ts +516 -0
  528. package/src/elements/store/sql-condition.test.ts +132 -0
  529. package/src/elements/store/sql-condition.ts +293 -65
  530. package/src/elements/store/sql-session.test.ts +135 -0
  531. package/src/elements/store/sql-session.ts +241 -84
  532. package/src/elements/store/table.ts +69 -23
  533. package/src/elements/store.test.ts +17 -39
  534. package/src/elements/store.ts +53 -31
  535. package/src/elements/vault/chain.ts +34 -0
  536. package/src/elements/vault/declare.ts +22 -32
  537. package/src/elements/vault/fingerprint.ts +2 -7
  538. package/src/elements/vault/redact.ts +2 -6
  539. package/src/elements/vault/runtime.ts +19 -33
  540. package/src/elements/vault.test.ts +12 -55
  541. package/src/elements/vault.ts +9 -13
  542. package/src/index.ts +5 -2
  543. package/src/kernel/adopt-routes.ts +15 -29
  544. package/src/kernel/app.ts +92 -118
  545. package/src/kernel/auth-resolve.ts +2 -9
  546. package/src/kernel/boot-bind/ai.ts +1 -4
  547. package/src/kernel/boot-bind/channel.test.ts +60 -0
  548. package/src/kernel/boot-bind/channel.ts +61 -5
  549. package/src/kernel/boot-bind/clock.ts +2 -6
  550. package/src/kernel/boot-bind/gate.ts +2 -8
  551. package/src/kernel/boot-bind/runs.ts +1 -3
  552. package/src/kernel/boot-bind/signal.ts +3 -10
  553. package/src/kernel/boot-bind/store.test.ts +27 -18
  554. package/src/kernel/boot-bind/store.ts +93 -52
  555. package/src/kernel/boot-bind/vault.ts +2 -8
  556. package/src/kernel/boot.test.ts +4 -10
  557. package/src/kernel/boot.ts +30 -77
  558. package/src/kernel/budget.test.ts +1 -3
  559. package/src/kernel/capability.ts +3 -10
  560. package/src/kernel/dry-run.test.ts +1 -4
  561. package/src/kernel/dry-run.ts +3 -11
  562. package/src/kernel/edge.test.ts +68 -0
  563. package/src/kernel/effects.test.ts +1 -5
  564. package/src/kernel/effects.ts +4 -11
  565. package/src/kernel/errors.registry.test.ts +2 -8
  566. package/src/kernel/errors.ts +23 -32
  567. package/src/kernel/flow.test.ts +12 -25
  568. package/src/kernel/flow.ts +13 -25
  569. package/src/kernel/fx.test.ts +31 -40
  570. package/src/kernel/fx.ts +135 -90
  571. package/src/kernel/hook-timing.test.ts +3 -6
  572. package/src/kernel/hook-timing.ts +5 -14
  573. package/src/kernel/hooks.test.ts +43 -10
  574. package/src/kernel/hooks.ts +25 -12
  575. package/src/kernel/index.ts +11 -17
  576. package/src/kernel/journal.ts +7 -31
  577. package/src/kernel/on.ts +45 -9
  578. package/src/kernel/pipeline.test.ts +10 -19
  579. package/src/kernel/pipeline.ts +5 -17
  580. package/src/kernel/plug.ts +4 -11
  581. package/src/kernel/plugin/conflicts.test.ts +13 -25
  582. package/src/kernel/plugin/decorate.test.ts +8 -13
  583. package/src/kernel/plugin/scoping.test.ts +4 -11
  584. package/src/kernel/plugin.ts +81 -27
  585. package/src/kernel/registry-isolation.test.ts +74 -0
  586. package/src/kernel/registry.ts +102 -30
  587. package/src/kernel/router.test.ts +15 -13
  588. package/src/kernel/router.ts +9 -29
  589. package/src/kernel/routing-budget.test.ts +1 -3
  590. package/src/kernel/run-telemetry.ts +1 -3
  591. package/src/kernel/triggers.ts +63 -21
  592. package/src/manifest/diff.test.ts +26 -91
  593. package/src/manifest/diff.ts +95 -225
  594. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  595. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  596. package/src/manifest/index.ts +3 -10
  597. package/src/manifest/types.ts +30 -6
  598. package/src/manifest/undeclared.test.ts +4 -12
  599. package/src/manifest/undeclared.ts +1 -2
  600. package/src/manifest/validate.test.ts +2 -6
  601. package/src/manifest/validate.ts +5 -15
  602. package/src/mcp/authorization.ts +8 -27
  603. package/src/mcp/confirmation.ts +3 -10
  604. package/src/mcp/data.ts +2 -6
  605. package/src/mcp/docs-index.ts +4 -7
  606. package/src/mcp/docs-mcp.test.ts +3 -12
  607. package/src/mcp/docs-server.ts +7 -27
  608. package/src/mcp/docs-tools.ts +2 -6
  609. package/src/mcp/index.ts +1 -6
  610. package/src/mcp/injection.gate.test.ts +4 -18
  611. package/src/mcp/mcp.test.ts +18 -49
  612. package/src/mcp/protocol.ts +3 -10
  613. package/src/mcp/server.ts +11 -52
  614. package/src/mcp/session.ts +4 -14
  615. package/src/mcp/tools.ts +14 -50
  616. package/src/plugins/catalogue.test.ts +3 -7
  617. package/src/plugins/catalogue.ts +1 -3
  618. package/src/plugins/compression.test.ts +127 -0
  619. package/src/plugins/compression.ts +94 -0
  620. package/src/plugins/config-source.test.ts +204 -0
  621. package/src/plugins/config-source.ts +209 -0
  622. package/src/plugins/cors.test.ts +138 -0
  623. package/src/plugins/cors.ts +129 -0
  624. package/src/plugins/csrf.test.ts +102 -0
  625. package/src/plugins/csrf.ts +86 -0
  626. package/src/plugins/headers.ts +54 -0
  627. package/src/plugins/index.ts +26 -0
  628. package/src/plugins/ip-allowlist.test.ts +105 -0
  629. package/src/plugins/ip-allowlist.ts +76 -0
  630. package/src/plugins/maintenance-mode.test.ts +91 -0
  631. package/src/plugins/maintenance-mode.ts +85 -0
  632. package/src/plugins/node-import-scan.ts +2 -5
  633. package/src/plugins/security-headers.test.ts +243 -0
  634. package/src/plugins/security-headers.ts +255 -0
  635. package/src/plugins/supply-chain.ts +5 -17
  636. package/src/release/exports.ts +3 -8
  637. package/src/release/measure.exports.test.ts +1 -3
  638. package/src/release/measure.ts +16 -45
  639. package/src/runs/bench.test.ts +1 -3
  640. package/src/runs/collect.ts +8 -25
  641. package/src/runs/drivers/clickhouse.ts +2 -9
  642. package/src/runs/drivers/files.ts +9 -31
  643. package/src/runs/drivers/memory.ts +5 -22
  644. package/src/runs/drivers/postgres.ts +8 -20
  645. package/src/runs/duckdb.ts +2 -8
  646. package/src/runs/index.ts +3 -14
  647. package/src/runs/outlier.ts +3 -10
  648. package/src/runs/parquet.ts +8 -26
  649. package/src/runs/privacy.ts +2 -8
  650. package/src/runs/runs.test.ts +3 -9
  651. package/src/runs/runtime.ts +7 -32
  652. package/src/runs/shred.ts +10 -29
  653. package/src/runs/types.ts +1 -4
  654. package/src/runtime/bun.ts +4 -15
  655. package/src/runtime/cold-start.bench.ts +1 -3
  656. package/src/runtime/dev-request-log.test.ts +1 -4
  657. package/src/runtime/dev-request-log.ts +1 -4
  658. package/src/runtime/index.ts +1 -6
  659. package/src/runtime/primitives.ts +5 -4
  660. package/src/runtime/security.ts +3 -13
  661. package/src/runtime/serve.test.ts +4 -7
  662. package/src/runtime/types.ts +1 -4
  663. package/src/runtime/web-standard.ts +3 -15
  664. package/src/term.test.ts +4 -6
  665. package/src/term.ts +49 -98
  666. package/src/test/create-test-app.test.ts +4 -14
  667. package/src/test/create-test-app.ts +27 -33
  668. package/src/test/provisions.integration.test.ts +3 -11
  669. package/src/upgrade/codemods.test.ts +25 -6
  670. package/src/upgrade/codemods.ts +116 -3
  671. package/src/validation/standard-schema.test.ts +2 -5
  672. package/src/validation/standard-schema.ts +13 -33
  673. package/docs/spec/console.md +0 -739
  674. package/docs/spec/example.md +0 -1196
  675. package/docs/spec/four-applications.md +0 -1195
  676. package/docs/spec/unified-theory.md +0 -489
  677. package/src/cli/doc-drift.test.ts +0 -146
  678. package/src/cli/doc-drift.ts +0 -430
  679. package/src/cli/doctor-diff-examples.ts +0 -92
  680. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
  681. package/src/drivers/vault-sops.ts +0 -271
@@ -69,34 +69,23 @@ export function AiPanel() {
69
69
  );
70
70
  const promptName = search.prompt ?? prompts[0]?.name;
71
71
  const versions = useMemo(
72
- () =>
73
- promptName
74
- ? versionsForPrompt(data?.versions ?? [], promptName)
75
- : [],
72
+ () => (promptName ? versionsForPrompt(data?.versions ?? [], promptName) : []),
76
73
  [data?.versions, promptName],
77
74
  );
78
75
  const selectedVersion =
79
- versions.find((v) => v.version === search.version) ??
80
- versions[versions.length - 1];
81
- const baseline =
82
- versions.length >= 2
83
- ? versions[versions.length - 2]
84
- : versions[0];
76
+ versions.find((v) => v.version === search.version) ?? versions[versions.length - 1];
77
+ const baseline = versions.length >= 2 ? versions[versions.length - 2] : versions[0];
85
78
  const decision =
86
- baseline &&
87
- selectedVersion &&
88
- baseline.version !== selectedVersion.version
79
+ baseline && selectedVersion && baseline.version !== selectedVersion.version
89
80
  ? promotionDecision(baseline, selectedVersion)
90
81
  : null;
91
82
 
92
83
  const agentName = search.agent ?? agents[0]?.name;
93
84
  const agentRuns = useMemo(
94
- () =>
95
- agentName ? runsForAgent(data?.agentRuns ?? [], agentName) : [],
85
+ () => (agentName ? runsForAgent(data?.agentRuns ?? [], agentName) : []),
96
86
  [data?.agentRuns, agentName],
97
87
  );
98
- const openRun =
99
- agentRuns.find((r) => r.id === search.run) ?? agentRuns[0];
88
+ const openRun = agentRuns.find((r) => r.id === search.run) ?? agentRuns[0];
100
89
  const pii = allowPiiStanding(data?.allowPii ?? []);
101
90
  const cataloguePrompt = prompts.find((p) => p.name === promptName);
102
91
 
@@ -105,8 +94,8 @@ export function AiPanel() {
105
94
  <header className="shrink-0 border-b border-[var(--oke-line)] px-4 py-3">
106
95
  <h1 className="text-base font-medium text-[var(--oke-fg)]">AI</h1>
107
96
  <p className="text-sm text-[var(--oke-muted)]">
108
- Distributions per prompt version — cost, latency, eval score.
109
- Schema-invalid is its own class.
97
+ Distributions per prompt version — cost, latency, eval score. Schema-invalid is its own
98
+ class.
110
99
  </p>
111
100
  <label className="mt-2 flex max-w-sm flex-col gap-1 text-sm">
112
101
  <span className="text-[var(--oke-muted)]">Filter</span>
@@ -140,21 +129,11 @@ export function AiPanel() {
140
129
  ? "bg-[var(--oke-line)] text-[var(--oke-fg)]"
141
130
  : "text-[var(--oke-muted)]",
142
131
  )}
143
- onClick={() =>
144
- setSearch(
145
- openPromptVersion(
146
- search,
147
- p.name,
148
- p.version ?? 0,
149
- ),
150
- )
151
- }
132
+ onClick={() => setSearch(openPromptVersion(search, p.name, p.version ?? 0))}
152
133
  >
153
134
  {p.name}
154
135
  {p.version !== undefined ? (
155
- <span className="ml-1 font-mono text-xs">
156
- @{p.version}
157
- </span>
136
+ <span className="ml-1 font-mono text-xs">@{p.version}</span>
158
137
  ) : null}
159
138
  </button>
160
139
  </li>
@@ -162,9 +141,7 @@ export function AiPanel() {
162
141
  </ul>
163
142
  </section>
164
143
  <section aria-label="Agents" className="p-3">
165
- <h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">
166
- Agents
167
- </h2>
144
+ <h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">Agents</h2>
168
145
  <ul className="space-y-1">
169
146
  {agents.map((a) => (
170
147
  <li key={a.name}>
@@ -194,12 +171,8 @@ export function AiPanel() {
194
171
  </aside>
195
172
 
196
173
  <main id="ai-main" className="min-h-0 overflow-y-auto p-4">
197
- {listQuery.isLoading ? (
198
- <p className="text-[var(--oke-muted)]">Loading…</p>
199
- ) : null}
200
- {listQuery.isError ? (
201
- <p role="alert">Failed to load AI projection</p>
202
- ) : null}
174
+ {listQuery.isLoading ? <p className="text-[var(--oke-muted)]">Loading…</p> : null}
175
+ {listQuery.isError ? <p role="alert">Failed to load AI projection</p> : null}
203
176
 
204
177
  {selectedVersion ? (
205
178
  <VersionDistributions
@@ -209,23 +182,17 @@ export function AiPanel() {
209
182
  setSearch(openPromptVersion(search, selectedVersion.prompt, v))
210
183
  }
211
184
  catalogueHref={
212
- cataloguePrompt
213
- ? manifestDiffHref(cataloguePrompt.manifestDiffPath)
214
- : null
185
+ cataloguePrompt ? manifestDiffHref(cataloguePrompt.manifestDiffPath) : null
215
186
  }
216
187
  decision={decision}
217
188
  />
218
189
  ) : (
219
- <p className="text-[var(--oke-muted)]">
220
- No prompt versions with samples yet.
221
- </p>
190
+ <p className="text-[var(--oke-muted)]">No prompt versions with samples yet.</p>
222
191
  )}
223
192
 
224
193
  {openRun ? (
225
194
  <section aria-label="Agent run trail" className="mt-8">
226
- <h2 className="mb-2 text-sm font-medium">
227
- Agent run · {openRun.agent}
228
- </h2>
195
+ <h2 className="mb-2 text-sm font-medium">Agent run · {openRun.agent}</h2>
229
196
  <div className="mb-2 flex flex-wrap gap-2">
230
197
  {agentRuns.map((r) => (
231
198
  <button
@@ -234,13 +201,9 @@ export function AiPanel() {
234
201
  aria-pressed={r.id === openRun.id}
235
202
  className={clsx(
236
203
  "min-h-8 px-2 text-xs font-mono",
237
- r.id === openRun.id
238
- ? "bg-[var(--oke-line)]"
239
- : "text-[var(--oke-muted)]",
204
+ r.id === openRun.id ? "bg-[var(--oke-line)]" : "text-[var(--oke-muted)]",
240
205
  )}
241
- onClick={() =>
242
- setSearch(openAgentRun(search, r.agent, r.id))
243
- }
206
+ onClick={() => setSearch(openAgentRun(search, r.agent, r.id))}
244
207
  >
245
208
  {r.id}
246
209
  </button>
@@ -265,22 +228,17 @@ export function AiPanel() {
265
228
  {step.status === "denied" && step.denial ? (
266
229
  <p role="status" className="mt-1 text-[var(--oke-muted)]">
267
230
  DENIED by gate{" "}
268
- <span className="font-mono text-[var(--oke-fg)]">
269
- {step.denial.gate}
270
- </span>
271
- : {step.denial.reason}
231
+ <span className="font-mono text-[var(--oke-fg)]">{step.denial.gate}</span>:{" "}
232
+ {step.denial.reason}
272
233
  </p>
273
234
  ) : null}
274
235
  <ul className="mt-1 space-y-0.5 text-xs text-[var(--oke-muted)]">
275
236
  {step.effects.map((e) => (
276
237
  <li key={`${e.kind}:${e.resource}`}>
277
- <span className="font-mono">{e.kind}</span>{" "}
278
- {e.resource}
238
+ <span className="font-mono">{e.kind}</span> {e.resource}
279
239
  </li>
280
240
  ))}
281
- {step.effects.length === 0 ? (
282
- <li>no declared effects</li>
283
- ) : null}
241
+ {step.effects.length === 0 ? <li>no declared effects</li> : null}
284
242
  </ul>
285
243
  </li>
286
244
  ))}
@@ -291,9 +249,7 @@ export function AiPanel() {
291
249
  <section aria-label="Fallback chains" className="mt-8">
292
250
  <h2 className="mb-2 text-sm font-medium">Fallback chains</h2>
293
251
  {(data?.fallbackChains.length ?? 0) === 0 ? (
294
- <p className="text-sm text-[var(--oke-muted)]">
295
- No multi-model chains recorded.
296
- </p>
252
+ <p className="text-sm text-[var(--oke-muted)]">No multi-model chains recorded.</p>
297
253
  ) : (
298
254
  <ul className="space-y-2 text-sm">
299
255
  {(data?.fallbackChains ?? []).map((chain, i) => (
@@ -311,16 +267,12 @@ export function AiPanel() {
311
267
  {j > 0 ? " → " : ""}
312
268
  <span
313
269
  className={
314
- a.ok
315
- ? "text-[var(--oke-fg)]"
316
- : "text-[var(--oke-muted)] line-through"
270
+ a.ok ? "text-[var(--oke-fg)]" : "text-[var(--oke-muted)] line-through"
317
271
  }
318
272
  >
319
273
  {a.model}
320
274
  </span>
321
- {a.cost !== undefined
322
- ? ` (${formatCost(a.cost)})`
323
- : ""}
275
+ {a.cost !== undefined ? ` (${formatCost(a.cost)})` : ""}
324
276
  </span>
325
277
  ))}
326
278
  </div>
@@ -341,12 +293,9 @@ export function AiPanel() {
341
293
  aria-label="allowPii security review"
342
294
  className="min-h-0 overflow-y-auto border-t border-[var(--oke-line)] p-4 lg:border-l lg:border-t-0"
343
295
  >
344
- <h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">
345
- allowPii
346
- </h2>
296
+ <h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">allowPii</h2>
347
297
  <p className="mb-3 text-xs text-[var(--oke-muted)]">
348
- Standing security review — flows that acknowledge PII egress to a
349
- model.
298
+ Standing security review — flows that acknowledge PII egress to a model.
350
299
  </p>
351
300
  {pii.length === 0 ? (
352
301
  <p className="text-sm text-[var(--oke-muted)]">None declared.</p>
@@ -368,9 +317,7 @@ export function AiPanel() {
368
317
  <tbody>
369
318
  {pii.map((row) => (
370
319
  <tr key={row.flowId} className="align-top">
371
- <td className="py-1 pr-2 font-mono text-[var(--oke-fg)]">
372
- {row.flowId}
373
- </td>
320
+ <td className="py-1 pr-2 font-mono text-[var(--oke-fg)]">{row.flowId}</td>
374
321
  <td className="py-1 font-mono text-[var(--oke-muted)]">
375
322
  {row.asks.join(", ") || "—"}
376
323
  </td>
@@ -397,14 +344,10 @@ function VersionDistributions(props: {
397
344
  <section aria-label="Version distributions" aria-live="polite">
398
345
  <div className="mb-3 flex flex-wrap items-baseline gap-3">
399
346
  <h2 className="text-sm font-medium">
400
- {m.prompt}{" "}
401
- <span className="font-mono text-[var(--oke-muted)]">@{m.version}</span>
347
+ {m.prompt} <span className="font-mono text-[var(--oke-muted)]">@{m.version}</span>
402
348
  </h2>
403
349
  {props.catalogueHref ? (
404
- <a
405
- href={props.catalogueHref}
406
- className="text-xs text-[var(--oke-muted)] underline"
407
- >
350
+ <a href={props.catalogueHref} className="text-xs text-[var(--oke-muted)] underline">
408
351
  Manifest Diff — version bump is a deploy
409
352
  </a>
410
353
  ) : null}
@@ -418,9 +361,7 @@ function VersionDistributions(props: {
418
361
  aria-pressed={v.version === m.version}
419
362
  className={clsx(
420
363
  "min-h-8 px-2 font-mono text-xs",
421
- v.version === m.version
422
- ? "bg-[var(--oke-line)]"
423
- : "text-[var(--oke-muted)]",
364
+ v.version === m.version ? "bg-[var(--oke-line)]" : "text-[var(--oke-muted)]",
424
365
  )}
425
366
  onClick={() => props.onSelectVersion(v.version)}
426
367
  >
@@ -431,13 +372,7 @@ function VersionDistributions(props: {
431
372
 
432
373
  <DistributionBlock
433
374
  label="Cost"
434
- summary={distributionSummary(
435
- "Cost",
436
- m.cost.mean,
437
- m.cost.p50,
438
- m.cost.p95,
439
- formatCost,
440
- )}
375
+ summary={distributionSummary("Cost", m.cost.mean, m.cost.p50, m.cost.p95, formatCost)}
441
376
  buckets={m.cost.buckets}
442
377
  formatTick={formatCost}
443
378
  />
@@ -509,8 +444,7 @@ function VersionDistributions(props: {
509
444
  aria-label="Promotion gate"
510
445
  >
511
446
  <p className="text-sm font-medium">
512
- Promotion v{props.decision.from.version} → v
513
- {props.decision.to.version} blocked
447
+ Promotion v{props.decision.from.version} → v{props.decision.to.version} blocked
514
448
  </p>
515
449
  <ul className="mt-1 list-disc pl-5 text-sm text-[var(--oke-muted)]">
516
450
  {formatPromotionBlockers(props.decision).map((line) => (
@@ -520,8 +454,7 @@ function VersionDistributions(props: {
520
454
  </div>
521
455
  ) : props.decision?.allowed ? (
522
456
  <p className="mt-4 text-sm text-[var(--oke-muted)]" role="status">
523
- Promotion v{props.decision.from.version} → v
524
- {props.decision.to.version} allowed
457
+ Promotion v{props.decision.from.version} → v{props.decision.to.version} allowed
525
458
  {props.decision.evalImproved ? " (eval improved)" : ""}.
526
459
  </p>
527
460
  ) : null}
@@ -542,11 +475,7 @@ function DistributionBlock(props: {
542
475
  {props.label} distribution
543
476
  </h3>
544
477
  <p className="mb-2 text-sm">{props.summary}</p>
545
- <div
546
- role="img"
547
- aria-label={props.summary}
548
- className="flex h-16 items-end gap-px"
549
- >
478
+ <div role="img" aria-label={props.summary} className="flex h-16 items-end gap-px">
550
479
  {props.buckets.map((b, i) => (
551
480
  <div
552
481
  key={i}
@@ -61,10 +61,7 @@ export function ArchitecturePanel() {
61
61
  refetchInterval: 10_000,
62
62
  });
63
63
 
64
- const graph = useMemo(
65
- () => buildCausalityGraph(manifestQuery.data),
66
- [manifestQuery.data],
67
- );
64
+ const graph = useMemo(() => buildCausalityGraph(manifestQuery.data), [manifestQuery.data]);
68
65
 
69
66
  const layerFlags = layersOf(search);
70
67
  const view = useMemo(
@@ -93,23 +90,15 @@ export function ArchitecturePanel() {
93
90
  <div className="flex h-full min-h-0 flex-col">
94
91
  <header className="flex shrink-0 flex-wrap items-end gap-4 border-b border-[var(--oke-line)] px-6 py-4">
95
92
  <div className="flex flex-col gap-1">
96
- <p className="text-xs uppercase tracking-[0.2em] text-[var(--oke-muted)]">
97
- Architecture
98
- </p>
93
+ <p className="text-xs uppercase tracking-[0.2em] text-[var(--oke-muted)]">Architecture</p>
99
94
  <h1 className="text-xl font-semibold tracking-tight">System shape</h1>
100
95
  <p className="text-sm text-[var(--oke-muted)]">
101
96
  Clustered by unit · typed layers · traffic from Runs
102
97
  </p>
103
98
  </div>
104
- <p
105
- className="ml-auto font-mono text-sm"
106
- role="status"
107
- aria-live="polite"
108
- >
99
+ <p className="ml-auto font-mono text-sm" role="status" aria-live="polite">
109
100
  <span className="text-[var(--oke-muted)]">Boundary crossings</span>{" "}
110
- <span className="text-lg font-semibold tabular-nums">
111
- {view.boundaryCrossingCount}
112
- </span>
101
+ <span className="text-lg font-semibold tabular-nums">{view.boundaryCrossingCount}</span>
113
102
  </p>
114
103
  </header>
115
104
 
@@ -129,11 +118,7 @@ export function ArchitecturePanel() {
129
118
  <input
130
119
  type="checkbox"
131
120
  checked={layerFlags[layer]}
132
- onChange={(e) =>
133
- setSearch(
134
- setLayerSearch(search, layer, e.target.checked),
135
- )
136
- }
121
+ onChange={(e) => setSearch(setLayerSearch(search, layer, e.target.checked))}
137
122
  aria-label={`${LAYER_LABEL[layer]} layer`}
138
123
  />
139
124
  {LAYER_LABEL[layer]}
@@ -161,33 +146,18 @@ export function ArchitecturePanel() {
161
146
  </label>
162
147
  ))}
163
148
  </fieldset>
164
- <Button
165
- type="button"
166
- variant="ghost"
167
- onClick={() => setSearch(clearFocus(search))}
168
- >
149
+ <Button type="button" variant="ghost" onClick={() => setSearch(clearFocus(search))}>
169
150
  Clear focus
170
151
  </Button>
171
152
  </div>
172
153
  ) : (
173
- <p className="text-sm text-[var(--oke-muted)]">
174
- Select a unit to focus at depth 1–2
175
- </p>
154
+ <p className="text-sm text-[var(--oke-muted)]">Select a unit to focus at depth 1–2</p>
176
155
  )}
177
156
  </div>
178
157
 
179
- <section
180
- aria-label="System diagram"
181
- className="min-h-0 flex-1 overflow-auto px-4 py-4"
182
- >
183
- <div
184
- aria-hidden="true"
185
- className="mb-4 overflow-x-auto"
186
- >
187
- <svg
188
- className="h-auto w-full max-w-5xl text-[var(--oke-fg)]"
189
- viewBox="0 0 640 380"
190
- >
158
+ <section aria-label="System diagram" className="min-h-0 flex-1 overflow-auto px-4 py-4">
159
+ <div aria-hidden="true" className="mb-4 overflow-x-auto">
160
+ <svg className="h-auto w-full max-w-5xl text-[var(--oke-fg)]" viewBox="0 0 640 380">
191
161
  <rect
192
162
  x={SYSTEM_BOUNDARY.x}
193
163
  y={SYSTEM_BOUNDARY.y}
@@ -221,9 +191,7 @@ export function ArchitecturePanel() {
221
191
  x2={to.x}
222
192
  y2={to.y}
223
193
  stroke={
224
- edge.layer === "external"
225
- ? "var(--oke-external)"
226
- : "var(--oke-muted)"
194
+ edge.layer === "external" ? "var(--oke-external)" : "var(--oke-muted)"
227
195
  }
228
196
  strokeWidth={edge.thickness}
229
197
  strokeDasharray={edge.dashed ? "6 4" : undefined}
@@ -249,11 +217,7 @@ export function ArchitecturePanel() {
249
217
  ? "var(--oke-bg)"
250
218
  : "color-mix(in oklab, var(--oke-external) 25%, var(--oke-bg))"
251
219
  }
252
- stroke={
253
- node.insideBoundary
254
- ? "var(--oke-fg)"
255
- : "var(--oke-external)"
256
- }
220
+ stroke={node.insideBoundary ? "var(--oke-fg)" : "var(--oke-external)"}
257
221
  strokeWidth={node.focused ? 2.5 : 1.25}
258
222
  />
259
223
  <text
@@ -291,14 +255,10 @@ export function ArchitecturePanel() {
291
255
  >
292
256
  <span>{n.label}</span>
293
257
  {n.kind === "unit" && n.flowCount !== undefined ? (
294
- <span className="font-mono text-xs">
295
- {n.flowCount}
296
- </span>
258
+ <span className="font-mono text-xs">{n.flowCount}</span>
297
259
  ) : null}
298
260
  {!n.insideBoundary ? (
299
- <span className="text-xs text-[var(--oke-external)]">
300
- external
301
- </span>
261
+ <span className="text-xs text-[var(--oke-external)]">external</span>
302
262
  ) : null}
303
263
  </button>
304
264
  </li>
@@ -308,9 +268,7 @@ export function ArchitecturePanel() {
308
268
  {view.edges.map((e) => (
309
269
  <li key={e.id}>
310
270
  {e.from} → {e.to}
311
- {e.dashed
312
- ? " (declared, never traversed)"
313
- : ` · ${e.traversals} traversals`}
271
+ {e.dashed ? " (declared, never traversed)" : ` · ${e.traversals} traversals`}
314
272
  {` · ${e.layer}`}
315
273
  </li>
316
274
  ))}
@@ -329,9 +287,7 @@ export function ArchitecturePanel() {
329
287
  </p>
330
288
  </div>
331
289
  {view.findings.length === 0 ? (
332
- <p className="px-5 pb-4 text-sm text-[var(--oke-muted)]">
333
- No pathologies detected.
334
- </p>
290
+ <p className="px-5 pb-4 text-sm text-[var(--oke-muted)]">No pathologies detected.</p>
335
291
  ) : (
336
292
  <ul className="divide-y divide-[var(--oke-line)] border-t border-[var(--oke-line)]">
337
293
  {view.findings.map((f, i) => (
@@ -348,16 +304,12 @@ export function ArchitecturePanel() {
348
304
  />
349
305
  {f.title}
350
306
  </p>
351
- <p className="mt-1 text-sm text-[var(--oke-muted)]">
352
- {f.detail}
353
- </p>
307
+ <p className="mt-1 text-sm text-[var(--oke-muted)]">{f.detail}</p>
354
308
  {f.nodeIds[0] ? (
355
309
  <button
356
310
  type="button"
357
311
  className="mt-2 min-h-8 text-sm text-[var(--oke-accent)] underline-offset-2 hover:underline"
358
- onClick={() =>
359
- setSearch(focusNode(search, f.nodeIds[0]!))
360
- }
312
+ onClick={() => setSearch(focusNode(search, f.nodeIds[0]!))}
361
313
  >
362
314
  Focus
363
315
  </button>
@@ -61,18 +61,15 @@ export function ChannelsPanel() {
61
61
  () => filterTemplates(list?.templates ?? [], search.q ?? ""),
62
62
  [list?.templates, search.q],
63
63
  );
64
- const open = templates.find((t) => t.name === search.template) ??
64
+ const open =
65
+ templates.find((t) => t.name === search.template) ??
65
66
  list?.templates.find((t) => t.name === search.template);
66
67
  const outcomes = sortByConsequence(list?.outcomes ?? []);
67
68
  const production = list?.production ?? true;
68
69
  const sendConfirm = sendTestConfirmation({ production });
69
70
 
70
71
  const previewQuery = useQuery({
71
- queryKey: [
72
- "console.channel.preview",
73
- open?.name,
74
- previewLocale || search.locale,
75
- ],
72
+ queryKey: ["console.channel.preview", open?.name, previewLocale || search.locale],
76
73
  enabled: !!open,
77
74
  queryFn: async () => {
78
75
  if (!open) return null;
@@ -122,8 +119,7 @@ export function ChannelsPanel() {
122
119
  template: open.name,
123
120
  to: testTo,
124
121
  locale: previewLocale || open.locales[0],
125
- confirmation:
126
- sendConfirm.kind === "typed" ? sendConfirm.phrase : undefined,
122
+ confirmation: sendConfirm.kind === "typed" ? sendConfirm.phrase : undefined,
127
123
  reason: sendConfirm.kind === "typed" ? reason : undefined,
128
124
  });
129
125
  if (res.error) throw new Error(res.error.code);
@@ -169,9 +165,7 @@ export function ChannelsPanel() {
169
165
  aria-label="Templates"
170
166
  className="w-64 shrink-0 overflow-y-auto border-r border-[var(--oke-line)] p-3"
171
167
  >
172
- <h2 className="mb-2 text-xs tracking-wide text-[var(--oke-muted)]">
173
- Templates
174
- </h2>
168
+ <h2 className="mb-2 text-xs tracking-wide text-[var(--oke-muted)]">Templates</h2>
175
169
  {listQuery.isLoading ? (
176
170
  <p className="text-sm text-[var(--oke-muted)]">Loading…</p>
177
171
  ) : (
@@ -187,9 +181,7 @@ export function ChannelsPanel() {
187
181
  ? "bg-[var(--oke-line)] text-[var(--oke-fg)]"
188
182
  : "text-[var(--oke-muted)]",
189
183
  )}
190
- onClick={() =>
191
- setSearch(openTemplate(search, t.name))
192
- }
184
+ onClick={() => setSearch(openTemplate(search, t.name))}
193
185
  >
194
186
  <span>{t.name}</span>
195
187
  <span className="font-mono text-xs">{t.medium}</span>
@@ -200,33 +192,23 @@ export function ChannelsPanel() {
200
192
  )}
201
193
  </section>
202
194
 
203
- <main
204
- id="channels-main"
205
- className="min-w-0 flex-1 overflow-y-auto p-4"
206
- >
195
+ <main id="channels-main" className="min-w-0 flex-1 overflow-y-auto p-4">
207
196
  {list?.face === "inbox" ? (
208
197
  <section aria-label="Inbox" className="mb-8">
209
198
  <h2 className="text-base text-[var(--oke-fg)]">Inbox</h2>
210
199
  <ul className="mt-3 space-y-2">
211
200
  {(list.inbox ?? []).map((e) => (
212
- <li
213
- key={e.id}
214
- className="border-b border-[var(--oke-line)] pb-2 text-sm"
215
- >
201
+ <li key={e.id} className="border-b border-[var(--oke-line)] pb-2 text-sm">
216
202
  <div className="flex gap-2 text-[var(--oke-muted)]">
217
203
  <span>{e.medium}</span>
218
204
  <span>{e.toMasked}</span>
219
205
  {e.template ? <span>{e.template}</span> : null}
220
206
  </div>
221
- <p className="mt-1 text-[var(--oke-fg)]">
222
- {e.subject ?? e.text ?? "(empty)"}
223
- </p>
207
+ <p className="mt-1 text-[var(--oke-fg)]">{e.subject ?? e.text ?? "(empty)"}</p>
224
208
  </li>
225
209
  ))}
226
210
  {(list.inbox ?? []).length === 0 ? (
227
- <li className="text-sm text-[var(--oke-muted)]">
228
- No messages yet
229
- </li>
211
+ <li className="text-sm text-[var(--oke-muted)]">No messages yet</li>
230
212
  ) : null}
231
213
  </ul>
232
214
  </section>
@@ -235,9 +217,7 @@ export function ChannelsPanel() {
235
217
  <section aria-label="Did not arrive" className="mb-8">
236
218
  <h2 className="text-base text-[var(--oke-fg)]">Did not arrive</h2>
237
219
  <table className="mt-3 w-full text-left text-sm">
238
- <caption className="sr-only">
239
- Seven-state taxonomy with verdicts
240
- </caption>
220
+ <caption className="sr-only">Seven-state taxonomy with verdicts</caption>
241
221
  <thead>
242
222
  <tr className="text-[var(--oke-muted)]">
243
223
  <th scope="col" className="py-1 font-normal">
@@ -282,28 +262,21 @@ export function ChannelsPanel() {
282
262
  <section aria-label="Template detail" className="mb-8">
283
263
  <h2 className="text-base text-[var(--oke-fg)]">{open.name}</h2>
284
264
  <p className="mt-1 text-sm text-[var(--oke-muted)]">
285
- From {open.from ?? "unset"} · Locales{" "}
286
- {open.locales.join(", ") || "none"}
265
+ From {open.from ?? "unset"} · Locales {open.locales.join(", ") || "none"}
287
266
  </p>
288
267
 
289
268
  {open.from ? (
290
269
  <section aria-label="Email authentication" className="mt-4">
291
- <h3 className="text-sm text-[var(--oke-fg)]">
292
- SPF / DKIM / DMARC
293
- </h3>
270
+ <h3 className="text-sm text-[var(--oke-fg)]">SPF / DKIM / DMARC</h3>
294
271
  {authQuery.data ? (
295
272
  <ul className="mt-2 space-y-1 text-sm text-[var(--oke-muted)]">
296
273
  <li>SPF: {authQuery.data.spf}</li>
297
274
  <li>DKIM: {authQuery.data.dkim}</li>
298
275
  <li>DMARC: {authQuery.data.dmarc}</li>
299
- <li className="font-mono text-xs">
300
- {authQuery.data.domain}
301
- </li>
276
+ <li className="font-mono text-xs">{authQuery.data.domain}</li>
302
277
  </ul>
303
278
  ) : (
304
- <p className="mt-2 text-sm text-[var(--oke-muted)]">
305
- Checking…
306
- </p>
279
+ <p className="mt-2 text-sm text-[var(--oke-muted)]">Checking…</p>
307
280
  )}
308
281
  </section>
309
282
  ) : null}
@@ -318,10 +291,7 @@ export function ChannelsPanel() {
318
291
  value={previewLocale || open.locales[0] || "en"}
319
292
  onChange={(e) => setPreviewLocale(e.target.value)}
320
293
  >
321
- {(open.locales.length > 0
322
- ? open.locales
323
- : ["en"]
324
- ).map((l) => (
294
+ {(open.locales.length > 0 ? open.locales : ["en"]).map((l) => (
325
295
  <option key={l} value={l}>
326
296
  {l}
327
297
  </option>
@@ -331,8 +301,7 @@ export function ChannelsPanel() {
331
301
  {previewQuery.data ? (
332
302
  <>
333
303
  <p className="mt-2 text-xs text-[var(--oke-muted)]">
334
- Locale chain:{" "}
335
- {formatLocaleChainDisplay(previewQuery.data.localeChain)}
304
+ Locale chain: {formatLocaleChainDisplay(previewQuery.data.localeChain)}
336
305
  </p>
337
306
  <div
338
307
  className="mt-2 max-w-prose border border-[var(--oke-line)] p-3 text-sm text-[var(--oke-fg)]"
@@ -340,9 +309,7 @@ export function ChannelsPanel() {
340
309
  lang={previewQuery.data.locale}
341
310
  >
342
311
  {previewQuery.data.subject ? (
343
- <p className="mb-2 font-medium">
344
- {previewQuery.data.subject}
345
- </p>
312
+ <p className="mb-2 font-medium">{previewQuery.data.subject}</p>
346
313
  ) : null}
347
314
  <p>{previewQuery.data.text ?? previewQuery.data.html}</p>
348
315
  </div>
@@ -417,9 +384,7 @@ export function ChannelsPanel() {
417
384
  {s.subjectMasked} · {s.reason} · {s.medium}
418
385
  </li>
419
386
  ))}
420
- {(list?.suppression ?? []).length === 0 ? (
421
- <li>Empty</li>
422
- ) : null}
387
+ {(list?.suppression ?? []).length === 0 ? <li>Empty</li> : null}
423
388
  </ul>
424
389
  </section>
425
390
 
@@ -442,9 +407,7 @@ export function ChannelsPanel() {
442
407
  ) : null}
443
408
  </li>
444
409
  ))}
445
- {(list?.receipts ?? []).length === 0 ? (
446
- <li>No receipts yet</li>
447
- ) : null}
410
+ {(list?.receipts ?? []).length === 0 ? <li>No receipts yet</li> : null}
448
411
  </ul>
449
412
  </section>
450
413
  </main>