okengine 0.2.5 → 0.2.8

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 (584) hide show
  1. package/AGENTS.md +24 -23
  2. package/README.md +52 -346
  3. package/docs/spec/console.md +165 -142
  4. package/docs/spec/example.md +490 -312
  5. package/docs/spec/four-applications.md +495 -314
  6. package/docs/spec/unified-theory.md +184 -175
  7. package/package.json +46 -38
  8. package/spec/manifest.v1.schema.json +40 -9
  9. package/src/auth/api-keys.ts +2 -5
  10. package/src/auth/attenuation.ts +2 -6
  11. package/src/auth/auth.test.ts +53 -31
  12. package/src/auth/invoke-as.ts +1 -3
  13. package/src/auth/operator.ts +8 -26
  14. package/src/auth/planes.ts +2 -7
  15. package/src/auth/plugin.ts +4 -7
  16. package/src/auth/roles.ts +1 -5
  17. package/src/auth/sessions.ts +10 -39
  18. package/src/cli/args.ts +1 -5
  19. package/src/cli/ask-dev-mode.ts +40 -0
  20. package/src/cli/build.ts +1 -2
  21. package/src/cli/client-add.test.ts +8 -15
  22. package/src/cli/client-add.ts +5 -14
  23. package/src/cli/completion.test.ts +1 -5
  24. package/src/cli/completion.ts +4 -17
  25. package/src/cli/db-auto-push.test.ts +64 -0
  26. package/src/cli/db-auto-push.ts +72 -0
  27. package/src/cli/db.test.ts +189 -0
  28. package/src/cli/db.ts +386 -0
  29. package/src/cli/dev-app-runner.ts +2 -8
  30. package/src/cli/dev-db-push.test.ts +163 -0
  31. package/src/cli/dev-mode.test.ts +45 -0
  32. package/src/cli/dev-mode.ts +78 -0
  33. package/src/cli/dev.test.ts +148 -21
  34. package/src/cli/dev.ts +208 -134
  35. package/src/cli/doc-drift.test.ts +3 -2
  36. package/src/cli/doc-drift.ts +21 -50
  37. package/src/cli/doc-staleness.test.ts +69 -0
  38. package/src/cli/docker-cli.test.ts +7 -8
  39. package/src/cli/docker.ts +1 -3
  40. package/src/cli/doctor-diff-examples.ts +1 -3
  41. package/src/cli/doctor-diff.test.ts +1 -5
  42. package/src/cli/doctor-diff.ts +17 -46
  43. package/src/cli/doctor-pii.ts +2 -7
  44. package/src/cli/doctor.test.ts +26 -4
  45. package/src/cli/doctor.ts +35 -11
  46. package/src/cli/eval.ts +4 -14
  47. package/src/cli/gates-list.ts +1 -4
  48. package/src/cli/hero-meta.test.ts +17 -19
  49. package/src/cli/hero-meta.ts +20 -30
  50. package/src/cli/images.ts +3 -8
  51. package/src/cli/index.ts +11 -2
  52. package/src/cli/load-config.images.test.ts +14 -14
  53. package/src/cli/load-config.ts +41 -47
  54. package/src/cli/mcp-from-console.ts +1 -4
  55. package/src/cli/mode.ts +45 -0
  56. package/src/cli/ports.test.ts +4 -13
  57. package/src/cli/ports.ts +1 -3
  58. package/src/cli/privacy-erase.ts +1 -3
  59. package/src/cli/registry.ts +75 -25
  60. package/src/cli/schema.ts +3 -10
  61. package/src/cli/stack.ts +2 -7
  62. package/src/cli/start.ts +4 -15
  63. package/src/cli/upgrade.ts +1 -4
  64. package/src/client/budget-entry.ts +1 -6
  65. package/src/client/create.test.ts +6 -12
  66. package/src/client/create.ts +2 -8
  67. package/src/client/errors.ts +1 -4
  68. package/src/client/index.ts +1 -6
  69. package/src/client/notes-contract.test.ts +4 -13
  70. package/src/client/transport.ts +9 -30
  71. package/src/client/types.ts +8 -29
  72. package/src/compiler/aot.test.ts +2 -9
  73. package/src/compiler/aot.ts +1 -4
  74. package/src/compiler/differential.test.ts +3 -11
  75. package/src/compiler/dynamic.ts +1 -4
  76. package/src/compiler/effects-infer.ts +8 -34
  77. package/src/compiler/emit.ts +1 -3
  78. package/src/compiler/extract.test.ts +96 -30
  79. package/src/compiler/extract.ts +362 -156
  80. package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
  81. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
  82. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
  83. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
  84. package/src/compiler/fixtures/skyport.expected.json +24 -83
  85. package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
  86. package/src/compiler/http-parse.ts +2 -9
  87. package/src/compiler/index.ts +1 -5
  88. package/src/compiler/response.ts +4 -7
  89. package/src/compiler/sucrose.ts +11 -31
  90. package/src/config/define-config.test.ts +57 -34
  91. package/src/config/index.ts +181 -37
  92. package/src/config/resolve-driver.test.ts +28 -17
  93. package/src/console/budget.test.ts +1 -4
  94. package/src/console/index.ts +1 -4
  95. package/src/console/server/access.test.ts +15 -43
  96. package/src/console/server/access.ts +19 -49
  97. package/src/console/server/ai.test.ts +3 -11
  98. package/src/console/server/ai.ts +23 -46
  99. package/src/console/server/app.ts +14 -45
  100. package/src/console/server/auth-rate.test.ts +4 -12
  101. package/src/console/server/bind.ts +1 -5
  102. package/src/console/server/channels.test.ts +2 -6
  103. package/src/console/server/channels.ts +10 -35
  104. package/src/console/server/claim.ts +2 -8
  105. package/src/console/server/clock.test.ts +2 -6
  106. package/src/console/server/clock.ts +8 -26
  107. package/src/console/server/console.test.ts +1 -3
  108. package/src/console/server/diff.test.ts +5 -17
  109. package/src/console/server/diff.ts +10 -31
  110. package/src/console/server/dry-run.audit.test.ts +2 -8
  111. package/src/console/server/flows.ts +64 -233
  112. package/src/console/server/gates.test.ts +14 -50
  113. package/src/console/server/gates.ts +13 -48
  114. package/src/console/server/index.ts +2 -9
  115. package/src/console/server/live.ts +3 -12
  116. package/src/console/server/operator-db.test.ts +4 -15
  117. package/src/console/server/operator-db.ts +13 -32
  118. package/src/console/server/plugin.ts +50 -53
  119. package/src/console/server/plugins.test.ts +2 -6
  120. package/src/console/server/plugins.ts +17 -56
  121. package/src/console/server/runs-pii.ts +2 -7
  122. package/src/console/server/security.gate.test.ts +18 -40
  123. package/src/console/server/serve.ts +10 -25
  124. package/src/console/server/signals.test.ts +1 -3
  125. package/src/console/server/signals.ts +17 -40
  126. package/src/console/server/state.ts +21 -59
  127. package/src/console/server/store.test.ts +20 -22
  128. package/src/console/server/store.ts +31 -76
  129. package/src/console/server/vault.test.ts +12 -29
  130. package/src/console/server/vault.ts +23 -60
  131. package/src/console/ui/access/AccessA11yView.tsx +6 -21
  132. package/src/console/ui/access/a11y.test.tsx +3 -12
  133. package/src/console/ui/access/acknowledgement.test.ts +1 -4
  134. package/src/console/ui/access/acknowledgement.ts +1 -3
  135. package/src/console/ui/access/blast-radius.ts +1 -3
  136. package/src/console/ui/access/confirmation.test.ts +1 -5
  137. package/src/console/ui/access/confirmation.ts +1 -4
  138. package/src/console/ui/access/fixture.ts +1 -5
  139. package/src/console/ui/access/grantable.test.ts +1 -3
  140. package/src/console/ui/access/grantable.ts +2 -7
  141. package/src/console/ui/access/index.ts +2 -9
  142. package/src/console/ui/access/provenance.test.ts +1 -3
  143. package/src/console/ui/access/provenance.ts +2 -6
  144. package/src/console/ui/access/search.test.ts +1 -5
  145. package/src/console/ui/access/search.ts +2 -6
  146. package/src/console/ui/ai/AiA11yView.tsx +6 -17
  147. package/src/console/ui/ai/a11y.test.tsx +2 -5
  148. package/src/console/ui/ai/fixture.ts +2 -7
  149. package/src/console/ui/ai/format.ts +1 -3
  150. package/src/console/ui/ai/group.test.ts +1 -3
  151. package/src/console/ui/ai/group.ts +4 -12
  152. package/src/console/ui/ai/index.ts +2 -9
  153. package/src/console/ui/ai/promotion.test.ts +2 -7
  154. package/src/console/ui/ai/promotion.ts +4 -13
  155. package/src/console/ui/ai/search.test.ts +2 -11
  156. package/src/console/ui/ai/search.ts +3 -13
  157. package/src/console/ui/ai/types.ts +1 -8
  158. package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
  159. package/src/console/ui/architecture/a11y.test.tsx +1 -2
  160. package/src/console/ui/architecture/declared.ts +1 -5
  161. package/src/console/ui/architecture/index.ts +7 -35
  162. package/src/console/ui/architecture/layout.ts +1 -3
  163. package/src/console/ui/architecture/pathologies.ts +10 -19
  164. package/src/console/ui/architecture/search.ts +6 -15
  165. package/src/console/ui/architecture/traffic.ts +4 -14
  166. package/src/console/ui/architecture/types.ts +2 -10
  167. package/src/console/ui/architecture/view.test.ts +7 -19
  168. package/src/console/ui/architecture/view.ts +9 -36
  169. package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
  170. package/src/console/ui/channels/a11y.test.tsx +1 -2
  171. package/src/console/ui/channels/confirmation.test.ts +1 -4
  172. package/src/console/ui/channels/confirmation.ts +1 -4
  173. package/src/console/ui/channels/findings.ts +1 -5
  174. package/src/console/ui/channels/index.ts +2 -8
  175. package/src/console/ui/channels/locale.test.ts +1 -3
  176. package/src/console/ui/channels/locale.ts +2 -8
  177. package/src/console/ui/channels/search.ts +4 -13
  178. package/src/console/ui/channels/taxonomy.ts +1 -3
  179. package/src/console/ui/clock/ClockA11yView.tsx +9 -26
  180. package/src/console/ui/clock/a11y.test.tsx +2 -5
  181. package/src/console/ui/clock/confirmation.test.ts +1 -3
  182. package/src/console/ui/clock/confirmation.ts +1 -4
  183. package/src/console/ui/clock/findings.ts +1 -4
  184. package/src/console/ui/clock/health.ts +2 -7
  185. package/src/console/ui/clock/index.ts +2 -10
  186. package/src/console/ui/clock/search.test.ts +1 -3
  187. package/src/console/ui/clock/search.ts +2 -6
  188. package/src/console/ui/clock/timeline.test.ts +1 -3
  189. package/src/console/ui/clock/waiting-on.test.ts +1 -5
  190. package/src/console/ui/clock/waiting-on.ts +2 -7
  191. package/src/console/ui/diff/DiffA11yView.tsx +8 -17
  192. package/src/console/ui/diff/a11y.test.tsx +2 -5
  193. package/src/console/ui/diff/group.test.ts +3 -13
  194. package/src/console/ui/diff/group.ts +2 -8
  195. package/src/console/ui/diff/index.ts +2 -8
  196. package/src/console/ui/diff/search.test.ts +1 -5
  197. package/src/console/ui/diff/search.ts +4 -16
  198. package/src/console/ui/diff/summary.ts +1 -2
  199. package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
  200. package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
  201. package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
  202. package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
  203. package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
  204. package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
  205. package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
  206. package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
  207. package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
  208. package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
  209. package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
  210. package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
  211. package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
  212. package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
  213. package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
  214. package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
  215. package/src/console/ui/dist/index.html +1 -1
  216. package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
  217. package/src/console/ui/flows/a11y.test.tsx +2 -8
  218. package/src/console/ui/flows/buffer.test.ts +3 -11
  219. package/src/console/ui/flows/buffer.ts +4 -11
  220. package/src/console/ui/flows/confirmation.ts +1 -3
  221. package/src/console/ui/flows/contract.test.ts +3 -7
  222. package/src/console/ui/flows/contract.ts +12 -36
  223. package/src/console/ui/flows/graph.test.ts +3 -11
  224. package/src/console/ui/flows/graph.ts +5 -15
  225. package/src/console/ui/flows/index.ts +1 -6
  226. package/src/console/ui/flows/save-as-test.ts +1 -3
  227. package/src/console/ui/flows/search.ts +8 -25
  228. package/src/console/ui/flows/tiers.ts +2 -9
  229. package/src/console/ui/gates/GatesA11yView.tsx +4 -13
  230. package/src/console/ui/gates/a11y.test.tsx +2 -5
  231. package/src/console/ui/gates/audit.ts +1 -3
  232. package/src/console/ui/gates/denial.test.ts +1 -3
  233. package/src/console/ui/gates/denial.ts +4 -12
  234. package/src/console/ui/gates/findings.ts +1 -3
  235. package/src/console/ui/gates/group.test.ts +3 -3
  236. package/src/console/ui/gates/group.ts +3 -11
  237. package/src/console/ui/gates/index.ts +2 -10
  238. package/src/console/ui/gates/search.ts +3 -10
  239. package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
  240. package/src/console/ui/overview/a11y.test.tsx +1 -2
  241. package/src/console/ui/overview/busiest.ts +1 -3
  242. package/src/console/ui/overview/compose.ts +1 -13
  243. package/src/console/ui/overview/cost.ts +34 -38
  244. package/src/console/ui/overview/fixture.ts +21 -26
  245. package/src/console/ui/overview/golden.ts +4 -14
  246. package/src/console/ui/overview/index.ts +2 -9
  247. package/src/console/ui/overview/rank.test.ts +3 -10
  248. package/src/console/ui/overview/rank.ts +2 -7
  249. package/src/console/ui/overview/slo.test.ts +5 -9
  250. package/src/console/ui/overview/slo.ts +6 -23
  251. package/src/console/ui/overview/verdict.ts +3 -10
  252. package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
  253. package/src/console/ui/plugins/a11y.test.tsx +1 -2
  254. package/src/console/ui/plugins/fixture.ts +2 -4
  255. package/src/console/ui/plugins/group.test.ts +1 -3
  256. package/src/console/ui/plugins/group.ts +1 -6
  257. package/src/console/ui/plugins/index.ts +3 -13
  258. package/src/console/ui/plugins/search.ts +7 -19
  259. package/src/console/ui/runs/RunsA11yView.tsx +5 -20
  260. package/src/console/ui/runs/a11y.test.tsx +2 -5
  261. package/src/console/ui/runs/explain.ts +2 -6
  262. package/src/console/ui/runs/group.ts +3 -12
  263. package/src/console/ui/runs/histogram.test.ts +2 -11
  264. package/src/console/ui/runs/histogram.ts +1 -4
  265. package/src/console/ui/runs/index.ts +4 -18
  266. package/src/console/ui/runs/project.ts +2 -6
  267. package/src/console/ui/runs/query.test.ts +1 -3
  268. package/src/console/ui/runs/query.ts +12 -35
  269. package/src/console/ui/runs/search.ts +5 -19
  270. package/src/console/ui/runs/trace-link.test.ts +2 -6
  271. package/src/console/ui/runs/trace-link.ts +4 -16
  272. package/src/console/ui/runs/types.ts +1 -3
  273. package/src/console/ui/shell/App.tsx +2 -10
  274. package/src/console/ui/shell/client.ts +22 -115
  275. package/src/console/ui/shell/components/ui.tsx +1 -4
  276. package/src/console/ui/shell/layout/Shell.tsx +2 -4
  277. package/src/console/ui/shell/main.tsx +31 -96
  278. package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
  279. package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
  280. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
  281. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
  282. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
  283. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
  284. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
  285. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
  286. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
  287. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
  288. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
  289. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
  290. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
  291. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
  292. package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
  293. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
  294. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
  295. package/src/console/ui/shell/setup/Wizard.tsx +3 -5
  296. package/src/console/ui/shell/styles.css +1 -2
  297. package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
  298. package/src/console/ui/signals/a11y.test.tsx +2 -5
  299. package/src/console/ui/signals/confirmation.test.ts +1 -5
  300. package/src/console/ui/signals/confirmation.ts +2 -6
  301. package/src/console/ui/signals/dry-run.ts +1 -3
  302. package/src/console/ui/signals/durable.ts +1 -3
  303. package/src/console/ui/signals/findings.ts +1 -3
  304. package/src/console/ui/signals/group.test.ts +2 -8
  305. package/src/console/ui/signals/group.ts +2 -10
  306. package/src/console/ui/signals/index.ts +1 -4
  307. package/src/console/ui/signals/monitor.ts +2 -7
  308. package/src/console/ui/signals/schema-form.test.ts +3 -14
  309. package/src/console/ui/signals/schema-form.ts +1 -4
  310. package/src/console/ui/signals/search.ts +4 -13
  311. package/src/console/ui/store/StoreA11yView.tsx +3 -9
  312. package/src/console/ui/store/a11y.test.tsx +2 -5
  313. package/src/console/ui/store/confirmation.test.ts +1 -3
  314. package/src/console/ui/store/confirmation.ts +1 -4
  315. package/src/console/ui/store/dry-run.ts +2 -5
  316. package/src/console/ui/store/fixture.ts +1 -2
  317. package/src/console/ui/store/group.test.ts +1 -6
  318. package/src/console/ui/store/group.ts +1 -4
  319. package/src/console/ui/store/index.ts +1 -5
  320. package/src/console/ui/store/search.ts +2 -6
  321. package/src/console/ui/store/will-not-fire.ts +1 -2
  322. package/src/console/ui/traces/TracesA11yView.tsx +10 -29
  323. package/src/console/ui/traces/a11y.test.tsx +1 -2
  324. package/src/console/ui/traces/chain.test.ts +5 -19
  325. package/src/console/ui/traces/chain.ts +1 -3
  326. package/src/console/ui/traces/critical-path.test.ts +1 -3
  327. package/src/console/ui/traces/critical-path.ts +2 -6
  328. package/src/console/ui/traces/filter.test.ts +2 -6
  329. package/src/console/ui/traces/filter.ts +5 -13
  330. package/src/console/ui/traces/fold.test.ts +4 -12
  331. package/src/console/ui/traces/fold.ts +1 -3
  332. package/src/console/ui/traces/mini.ts +1 -3
  333. package/src/console/ui/traces/replay.test.ts +1 -3
  334. package/src/console/ui/traces/replay.ts +1 -3
  335. package/src/console/ui/traces/sampling.ts +1 -4
  336. package/src/console/ui/traces/search.ts +4 -17
  337. package/src/console/ui/traces/tier.ts +1 -3
  338. package/src/console/ui/vault/VaultA11yView.tsx +5 -17
  339. package/src/console/ui/vault/a11y.test.tsx +1 -2
  340. package/src/console/ui/vault/blast-radius.ts +1 -3
  341. package/src/console/ui/vault/confirmation.test.ts +1 -5
  342. package/src/console/ui/vault/confirmation.ts +1 -4
  343. package/src/console/ui/vault/dormant.test.ts +1 -4
  344. package/src/console/ui/vault/export-safe.test.ts +1 -5
  345. package/src/console/ui/vault/export-safe.ts +1 -4
  346. package/src/console/ui/vault/fixture.ts +3 -3
  347. package/src/console/ui/vault/group.ts +1 -2
  348. package/src/console/ui/vault/index.ts +2 -10
  349. package/src/console/ui/vault/search.ts +2 -6
  350. package/src/console/ui/vault/types.ts +1 -1
  351. package/src/console/xss.gate.test.ts +1 -3
  352. package/src/docker/compose.ts +112 -20
  353. package/src/docker/derive.ts +5 -19
  354. package/src/docker/docker.test.ts +15 -15
  355. package/src/docker/dockerfile.integration.test.ts +12 -21
  356. package/src/docker/helpers.ts +5 -4
  357. package/src/docker/index.ts +4 -11
  358. package/src/docker/pin.ts +1 -9
  359. package/src/docker/recipes/index.ts +5 -6
  360. package/src/docker/recipes/mailpit.ts +22 -0
  361. package/src/docker/recipes/postgres.ts +17 -6
  362. package/src/docker/recipes/redis.ts +6 -1
  363. package/src/docker/recipes/rustfs.ts +33 -0
  364. package/src/docker/stack-id.test.ts +33 -0
  365. package/src/docker/stack-id.ts +25 -13
  366. package/src/docker/stack.integration.test.ts +6 -21
  367. package/src/docker/types.ts +13 -4
  368. package/src/drivers/ai-anthropic.ts +5 -14
  369. package/src/drivers/ai-mock.ts +2 -5
  370. package/src/drivers/ai-openai-compatible.ts +4 -10
  371. package/src/drivers/ai-providers.test.ts +6 -13
  372. package/src/drivers/bun-native-completeness.test.ts +6 -15
  373. package/src/drivers/channel-console.ts +6 -7
  374. package/src/drivers/channel-fcm.ts +20 -30
  375. package/src/drivers/channel-resend.ts +1 -3
  376. package/src/drivers/channel-smtp.ts +2 -6
  377. package/src/drivers/channel-types.ts +2 -12
  378. package/src/drivers/channel-unifonic.ts +2 -6
  379. package/src/drivers/channel-wa-cloud.ts +2 -6
  380. package/src/drivers/channel-webpush.ts +21 -60
  381. package/src/drivers/conformance.test.ts +2 -10
  382. package/src/drivers/conformance.ts +8 -21
  383. package/src/drivers/fs.ts +2 -8
  384. package/src/drivers/index.ts +12 -56
  385. package/src/drivers/memory.ts +14 -41
  386. package/src/drivers/pgvector.ts +7 -11
  387. package/src/drivers/postgres.ts +7 -13
  388. package/src/drivers/redis.ts +13 -37
  389. package/src/drivers/s3.ts +5 -17
  390. package/src/drivers/signal-engine.ts +12 -49
  391. package/src/drivers/signal-memory.ts +2 -8
  392. package/src/drivers/signal-nats.ts +4 -9
  393. package/src/drivers/signal-postgres.ts +62 -129
  394. package/src/drivers/signal-redis.ts +7 -21
  395. package/src/drivers/signal-types.ts +1 -4
  396. package/src/drivers/sqlite.ts +3 -12
  397. package/src/drivers/types.ts +4 -23
  398. package/src/drivers/vault-env.ts +2 -6
  399. package/src/drivers/vault-infisical.ts +1 -5
  400. package/src/drivers/vault-managed.ts +1 -5
  401. package/src/drivers/vault-memory.ts +1 -5
  402. package/src/drivers/vault-openbao.ts +1 -5
  403. package/src/drivers/vault-sops.ts +10 -35
  404. package/src/drivers/vault-types.ts +1 -7
  405. package/src/elements/ai/declare.ts +4 -14
  406. package/src/elements/ai/eval.ts +2 -6
  407. package/src/elements/ai/pii.ts +1 -3
  408. package/src/elements/ai/runtime.ts +12 -50
  409. package/src/elements/ai/schema.ts +4 -15
  410. package/src/elements/ai.test.ts +13 -24
  411. package/src/elements/ai.ts +1 -5
  412. package/src/elements/channel/consent.ts +3 -12
  413. package/src/elements/channel/costs.ts +4 -15
  414. package/src/elements/channel/declare.ts +1 -4
  415. package/src/elements/channel/email-auth.ts +1 -4
  416. package/src/elements/channel/locale.ts +2 -10
  417. package/src/elements/channel/mask.ts +1 -3
  418. package/src/elements/channel/mime.ts +2 -12
  419. package/src/elements/channel/outcomes.test.ts +1 -5
  420. package/src/elements/channel/outcomes.ts +5 -15
  421. package/src/elements/channel/receipts.ts +2 -7
  422. package/src/elements/channel/runtime.ts +28 -74
  423. package/src/elements/channel/suppression.ts +8 -14
  424. package/src/elements/channel.test.ts +8 -31
  425. package/src/elements/channel.ts +3 -14
  426. package/src/elements/clock/actions.ts +6 -18
  427. package/src/elements/clock/declare.ts +1 -3
  428. package/src/elements/clock/dst.ts +1 -5
  429. package/src/elements/clock/durable.ts +4 -16
  430. package/src/elements/clock/health.ts +2 -7
  431. package/src/elements/clock/leader.ts +2 -9
  432. package/src/elements/clock/reconcile.ts +4 -15
  433. package/src/elements/clock/runtime.ts +2 -5
  434. package/src/elements/clock/schedule.ts +4 -20
  435. package/src/elements/clock.test.ts +2 -7
  436. package/src/elements/clock.ts +5 -23
  437. package/src/elements/gate/permissions.ts +1 -4
  438. package/src/elements/gate/runtime.ts +7 -28
  439. package/src/elements/gate.ts +1 -5
  440. package/src/elements/index.ts +9 -7
  441. package/src/elements/signal/declare.ts +2 -7
  442. package/src/elements/signal/reconcile.test.ts +1 -4
  443. package/src/elements/signal/runtime.ts +1 -3
  444. package/src/elements/signal.test.ts +3 -15
  445. package/src/elements/signal.ts +2 -8
  446. package/src/elements/store/cache.test.ts +46 -0
  447. package/src/elements/store/cache.ts +3 -11
  448. package/src/elements/store/classify.ts +5 -22
  449. package/src/elements/store/declare.ts +8 -17
  450. package/src/elements/store/domain-ddl.test.ts +86 -0
  451. package/src/elements/store/emit-drizzle.ts +363 -0
  452. package/src/elements/store/files-policy.test.ts +1 -5
  453. package/src/elements/store/files-policy.ts +4 -12
  454. package/src/elements/store/load-plugin-tables.ts +103 -0
  455. package/src/elements/store/missing-relation.test.ts +83 -0
  456. package/src/elements/store/missing-relation.ts +38 -0
  457. package/src/elements/store/replica.ts +1 -4
  458. package/src/elements/store/runtime.ts +25 -28
  459. package/src/elements/store/schema-decl.test.ts +227 -0
  460. package/src/elements/store/schema-decl.ts +516 -0
  461. package/src/elements/store/sql-condition.ts +11 -21
  462. package/src/elements/store/sql-session.test.ts +50 -0
  463. package/src/elements/store/sql-session.ts +60 -63
  464. package/src/elements/store/table.ts +35 -19
  465. package/src/elements/store.test.ts +17 -39
  466. package/src/elements/store.ts +37 -31
  467. package/src/elements/vault/chain.ts +34 -0
  468. package/src/elements/vault/declare.ts +22 -32
  469. package/src/elements/vault/fingerprint.ts +2 -7
  470. package/src/elements/vault/redact.ts +2 -6
  471. package/src/elements/vault/runtime.ts +18 -32
  472. package/src/elements/vault.test.ts +12 -28
  473. package/src/elements/vault.ts +8 -12
  474. package/src/index.ts +5 -2
  475. package/src/kernel/adopt-routes.ts +15 -29
  476. package/src/kernel/app.ts +34 -94
  477. package/src/kernel/auth-resolve.ts +2 -9
  478. package/src/kernel/boot-bind/ai.ts +1 -4
  479. package/src/kernel/boot-bind/channel.ts +2 -8
  480. package/src/kernel/boot-bind/clock.ts +2 -6
  481. package/src/kernel/boot-bind/gate.ts +2 -8
  482. package/src/kernel/boot-bind/runs.ts +1 -3
  483. package/src/kernel/boot-bind/signal.ts +3 -10
  484. package/src/kernel/boot-bind/store.test.ts +17 -17
  485. package/src/kernel/boot-bind/store.ts +44 -50
  486. package/src/kernel/boot-bind/vault.ts +2 -8
  487. package/src/kernel/boot.test.ts +4 -9
  488. package/src/kernel/boot.ts +29 -76
  489. package/src/kernel/budget.test.ts +1 -3
  490. package/src/kernel/capability.ts +3 -10
  491. package/src/kernel/dry-run.test.ts +1 -4
  492. package/src/kernel/dry-run.ts +3 -11
  493. package/src/kernel/effects.test.ts +1 -5
  494. package/src/kernel/effects.ts +4 -11
  495. package/src/kernel/errors.registry.test.ts +2 -8
  496. package/src/kernel/errors.ts +23 -32
  497. package/src/kernel/flow.test.ts +12 -25
  498. package/src/kernel/flow.ts +5 -25
  499. package/src/kernel/fx.test.ts +15 -44
  500. package/src/kernel/fx.ts +27 -79
  501. package/src/kernel/hook-timing.test.ts +3 -6
  502. package/src/kernel/hook-timing.ts +5 -14
  503. package/src/kernel/hooks.test.ts +10 -10
  504. package/src/kernel/hooks.ts +3 -12
  505. package/src/kernel/index.ts +4 -17
  506. package/src/kernel/journal.ts +7 -31
  507. package/src/kernel/on.ts +1 -6
  508. package/src/kernel/pipeline.test.ts +10 -19
  509. package/src/kernel/pipeline.ts +5 -17
  510. package/src/kernel/plug.ts +4 -11
  511. package/src/kernel/plugin/conflicts.test.ts +13 -25
  512. package/src/kernel/plugin/decorate.test.ts +8 -13
  513. package/src/kernel/plugin/scoping.test.ts +4 -11
  514. package/src/kernel/plugin.ts +48 -24
  515. package/src/kernel/registry.ts +80 -29
  516. package/src/kernel/router.test.ts +15 -13
  517. package/src/kernel/router.ts +9 -29
  518. package/src/kernel/routing-budget.test.ts +1 -3
  519. package/src/kernel/run-telemetry.ts +1 -3
  520. package/src/kernel/triggers.ts +4 -21
  521. package/src/manifest/diff.test.ts +26 -91
  522. package/src/manifest/diff.ts +95 -225
  523. package/src/manifest/index.ts +2 -9
  524. package/src/manifest/types.ts +29 -5
  525. package/src/manifest/undeclared.test.ts +4 -12
  526. package/src/manifest/undeclared.ts +1 -2
  527. package/src/manifest/validate.test.ts +2 -6
  528. package/src/manifest/validate.ts +4 -14
  529. package/src/mcp/authorization.ts +8 -27
  530. package/src/mcp/confirmation.ts +3 -10
  531. package/src/mcp/data.ts +2 -6
  532. package/src/mcp/docs-index.ts +4 -7
  533. package/src/mcp/docs-mcp.test.ts +3 -12
  534. package/src/mcp/docs-server.ts +7 -27
  535. package/src/mcp/docs-tools.ts +2 -6
  536. package/src/mcp/index.ts +1 -6
  537. package/src/mcp/injection.gate.test.ts +4 -18
  538. package/src/mcp/mcp.test.ts +18 -49
  539. package/src/mcp/protocol.ts +3 -10
  540. package/src/mcp/server.ts +11 -52
  541. package/src/mcp/session.ts +4 -14
  542. package/src/mcp/tools.ts +14 -50
  543. package/src/plugins/catalogue.test.ts +3 -7
  544. package/src/plugins/catalogue.ts +1 -3
  545. package/src/plugins/node-import-scan.ts +2 -5
  546. package/src/plugins/supply-chain.ts +5 -17
  547. package/src/release/exports.ts +3 -8
  548. package/src/release/measure.exports.test.ts +1 -3
  549. package/src/release/measure.ts +15 -43
  550. package/src/runs/bench.test.ts +1 -3
  551. package/src/runs/collect.ts +8 -25
  552. package/src/runs/drivers/clickhouse.ts +2 -9
  553. package/src/runs/drivers/files.ts +9 -31
  554. package/src/runs/drivers/memory.ts +5 -22
  555. package/src/runs/drivers/postgres.ts +8 -20
  556. package/src/runs/duckdb.ts +2 -8
  557. package/src/runs/index.ts +3 -14
  558. package/src/runs/outlier.ts +3 -10
  559. package/src/runs/parquet.ts +8 -26
  560. package/src/runs/privacy.ts +2 -8
  561. package/src/runs/runs.test.ts +3 -9
  562. package/src/runs/runtime.ts +7 -32
  563. package/src/runs/shred.ts +10 -29
  564. package/src/runs/types.ts +1 -4
  565. package/src/runtime/bun.ts +4 -15
  566. package/src/runtime/cold-start.bench.ts +1 -3
  567. package/src/runtime/dev-request-log.test.ts +1 -4
  568. package/src/runtime/dev-request-log.ts +1 -4
  569. package/src/runtime/index.ts +1 -6
  570. package/src/runtime/primitives.ts +5 -4
  571. package/src/runtime/security.ts +3 -13
  572. package/src/runtime/serve.test.ts +4 -7
  573. package/src/runtime/types.ts +1 -4
  574. package/src/runtime/web-standard.ts +3 -15
  575. package/src/term.test.ts +4 -6
  576. package/src/term.ts +49 -98
  577. package/src/test/create-test-app.test.ts +4 -14
  578. package/src/test/create-test-app.ts +13 -31
  579. package/src/test/provisions.integration.test.ts +3 -11
  580. package/src/upgrade/codemods.test.ts +25 -6
  581. package/src/upgrade/codemods.ts +116 -3
  582. package/src/validation/standard-schema.test.ts +2 -5
  583. package/src/validation/standard-schema.ts +13 -33
  584. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
@@ -81,13 +81,12 @@ async function loadMermaid(): Promise<typeof import("mermaid").default> {
81
81
  }
82
82
 
83
83
  /** App section heading → example package directory name. */
84
- const APP_SECTIONS: ReadonlyArray<{ readonly re: RegExp; readonly app: string }> =
85
- [
86
- { re: /^# 1 · BASICNotes\b/m, app: "notes" },
87
- { re: /^# 2 · INTERMEDIATELinkly\b/m, app: "linkly" },
88
- { re: /^# 3 · ADVANCEDProvisions\b/m, app: "provisions" },
89
- { re: /^# 4 · COMPLEX — Skyport\b/m, app: "skyport" },
90
- ];
84
+ const APP_SECTIONS: ReadonlyArray<{ readonly re: RegExp; readonly app: string }> = [
85
+ { re: /^# 1 · BASIC — Notes\b/m, app: "notes" },
86
+ { re: /^# 2 · INTERMEDIATELinkly\b/m, app: "linkly" },
87
+ { re: /^# 3 · ADVANCEDProvisions\b/m, app: "provisions" },
88
+ { re: /^# 4 · COMPLEXSkyport\b/m, app: "skyport" },
89
+ ];
91
90
 
92
91
  /**
93
92
  * Normalize TypeScript source for containment comparison.
@@ -95,12 +94,9 @@ const APP_SECTIONS: ReadonlyArray<{ readonly re: RegExp; readonly app: string }>
95
94
  * @param text - Raw source
96
95
  */
97
96
  export function normalizeTs(text: string): string {
98
- return text
99
- .replace(/\r\n/g, "\n")
100
- .split("\n")
101
- .map((line) => line.replace(/[ \t]+$/g, ""))
102
- .join("\n")
103
- .trim();
97
+ // Collapse all whitespace so claimed fences match sources regardless of
98
+ // indent (e.g. oxfmt-formatted bodies inside `test(...)` callbacks).
99
+ return text.replace(/\s+/g, " ").trim();
104
100
  }
105
101
 
106
102
  /** One claimed fence extracted from a markdown document. */
@@ -136,9 +132,7 @@ export function parseMermaidFences(markdown: string): MermaidFence[] {
136
132
  i++;
137
133
  }
138
134
  if (i >= lines.length || !lines[i]!.startsWith("```")) {
139
- throw new Error(
140
- `doc-drift: unclosed mermaid fence (line ${startLine})`,
141
- );
135
+ throw new Error(`doc-drift: unclosed mermaid fence (line ${startLine})`);
142
136
  }
143
137
  fences.push({ body: bodyLines.join("\n").trim(), startLine });
144
138
  }
@@ -165,15 +159,11 @@ export async function checkMermaidSyntax(
165
159
  try {
166
160
  const result = await mermaid.parse(fence.body);
167
161
  if (!result) {
168
- failures.push(
169
- `mermaid: parse returned false (line ${fence.startLine})`,
170
- );
162
+ failures.push(`mermaid: parse returned false (line ${fence.startLine})`);
171
163
  }
172
164
  } catch (err) {
173
165
  const detail = err instanceof Error ? err.message : String(err);
174
- failures.push(
175
- `mermaid: invalid syntax (line ${fence.startLine}): ${detail.split("\n")[0]}`,
176
- );
166
+ failures.push(`mermaid: invalid syntax (line ${fence.startLine}): ${detail.split("\n")[0]}`);
177
167
  }
178
168
  }
179
169
 
@@ -280,10 +270,7 @@ export function parseClaimedFences(markdown: string): ClaimedFence[] {
280
270
  * @param targetPath - File or directory (`tests/`)
281
271
  * @param expected - Normalized fence body
282
272
  */
283
- async function containsFence(
284
- targetPath: string,
285
- expected: string,
286
- ): Promise<boolean> {
273
+ async function containsFence(targetPath: string, expected: string): Promise<boolean> {
287
274
  const direct = Bun.file(targetPath);
288
275
  if (await direct.exists()) {
289
276
  const st = await direct.stat();
@@ -293,9 +280,7 @@ async function containsFence(
293
280
  }
294
281
 
295
282
  // Directory claim (`### \`tests/\``) — any nested file may contain the fence.
296
- const dirPath = targetPath.endsWith("/")
297
- ? targetPath.slice(0, -1)
298
- : targetPath;
283
+ const dirPath = targetPath.endsWith("/") ? targetPath.slice(0, -1) : targetPath;
299
284
  try {
300
285
  const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx}");
301
286
  for await (const rel of glob.scan({ cwd: dirPath, onlyFiles: true })) {
@@ -354,9 +339,7 @@ export async function runDocDrift(
354
339
 
355
340
  for (const path of paths) {
356
341
  const abs = resolve(ROOT, path);
357
- const label = abs.startsWith(ROOT + "/")
358
- ? abs.slice(ROOT.length + 1)
359
- : abs;
342
+ const label = abs.startsWith(ROOT + "/") ? abs.slice(ROOT.length + 1) : abs;
360
343
  const requireClaimed = !label.startsWith("site/");
361
344
  const markdown = await Bun.file(abs).text();
362
345
  const fences = parseClaimedFences(markdown);
@@ -371,14 +354,10 @@ export async function runDocDrift(
371
354
  total += fences.length;
372
355
  if (!result.ok) {
373
356
  ok = false;
374
- messages.push(
375
- `doc-drift: ${result.failures.length} failure(s) in ${label}`,
376
- );
357
+ messages.push(`doc-drift: ${result.failures.length} failure(s) in ${label}`);
377
358
  for (const f of result.failures) messages.push(` · ${f}`);
378
359
  } else {
379
- messages.push(
380
- `doc-drift: ok — ${fences.length} claimed fence(s) in ${label}`,
381
- );
360
+ messages.push(`doc-drift: ok — ${fences.length} claimed fence(s) in ${label}`);
382
361
  }
383
362
  }
384
363
 
@@ -388,21 +367,16 @@ export async function runDocDrift(
388
367
  const mermaidResult = await checkMermaidSyntax(mermaidFences);
389
368
  if (!mermaidResult.ok) {
390
369
  ok = false;
391
- messages.push(
392
- `doc-drift: ${mermaidResult.failures.length} mermaid failure(s) in ${label}`,
393
- );
370
+ messages.push(`doc-drift: ${mermaidResult.failures.length} mermaid failure(s) in ${label}`);
394
371
  for (const f of mermaidResult.failures) messages.push(` · ${f}`);
395
372
  } else {
396
- messages.push(
397
- `doc-drift: ok — ${mermaidFences.length} mermaid fence(s) in ${label}`,
398
- );
373
+ messages.push(`doc-drift: ok — ${mermaidFences.length} mermaid fence(s) in ${label}`);
399
374
  }
400
375
  }
401
376
  }
402
377
 
403
378
  if (ok && checkedFiles > 1) {
404
- const mermaidNote =
405
- mermaidTotal > 0 ? ` · ${mermaidTotal} mermaid fence(s)` : "";
379
+ const mermaidNote = mermaidTotal > 0 ? ` · ${mermaidTotal} mermaid fence(s)` : "";
406
380
  messages.push(
407
381
  `doc-drift: ok — ${total} claimed fence(s) across ${checkedFiles} file(s)${mermaidNote}`,
408
382
  );
@@ -413,10 +387,7 @@ export async function runDocDrift(
413
387
 
414
388
  async function main(): Promise<number> {
415
389
  const args = process.argv.slice(2);
416
- const paths =
417
- args.length > 0
418
- ? args
419
- : [...REQUIRED_DOCS, ...(await discoverSiteDocs(ROOT))];
390
+ const paths = args.length > 0 ? args : [...REQUIRED_DOCS, ...(await discoverSiteDocs(ROOT))];
420
391
  const { ok, messages } = await runDocDrift(paths);
421
392
  for (const m of messages) {
422
393
  if (ok) console.log(m);
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Gate: removed legacy stack-mode soft-compat stays gone.
3
+ *
4
+ * Mirrors {@link ../drivers/vault-driver-removal.test.ts} — `git grep` over the
5
+ * tracked tree must find zero hits (changelog history may still document the
6
+ * rename; upgrade codemods may still rewrite the old tokens).
7
+ */
8
+
9
+ import { describe, expect, test } from "bun:test";
10
+ import { join } from "node:path";
11
+
12
+ const ROOT = join(import.meta.dir, "../..");
13
+
14
+ /** Forbidden CLI flag, split so this file does not match itself. */
15
+ const FORBIDDEN_STACK_FLAG = ["--", "stack"].join("");
16
+ /** Forbidden compose env filename. */
17
+ const FORBIDDEN_ENV_STACK = [".env.", "stack"].join("");
18
+ /** Forbidden env var — name avoids the contiguous token so this file is clean. */
19
+ const FORBIDDEN_LEGACY_ENV = ["OKE_", "STACK"].join("");
20
+ /** Forbidden vault helper. */
21
+ const FORBIDDEN_FROM_STACK = ["from", "Stack"].join("");
22
+
23
+ /**
24
+ * Run `git grep -F` and assert zero matches after ignoring allow-listed paths.
25
+ *
26
+ * @param pattern - Fixed-string pattern
27
+ * @param ignorePrefixes - Path prefixes to ignore (`path:line:` hits)
28
+ */
29
+ function assertZeroGitGrep(pattern: string, ignorePrefixes: readonly string[] = []): void {
30
+ const proc = Bun.spawnSync(["git", "grep", "-F", "-n", "-e", pattern, "--"], {
31
+ cwd: ROOT,
32
+ stdout: "pipe",
33
+ stderr: "pipe",
34
+ });
35
+ // git grep exits 1 when there are no matches.
36
+ if (proc.exitCode === 1) {
37
+ expect(proc.stdout.toString()).toBe("");
38
+ return;
39
+ }
40
+ const hits = proc.stdout
41
+ .toString()
42
+ .trim()
43
+ .split("\n")
44
+ .filter((line) => line.length > 0)
45
+ .filter((line) => !ignorePrefixes.some((prefix) => line.startsWith(prefix)));
46
+ expect(hits.join("\n")).toBe("");
47
+ }
48
+
49
+ describe("legacy stack-mode removal gate", () => {
50
+ test("tracked tree has zero legacy docker-mode flag outside changelog", () => {
51
+ assertZeroGitGrep(FORBIDDEN_STACK_FLAG, ["docs/changelog.md:"]);
52
+ });
53
+
54
+ test("tracked tree has zero legacy compose env filename outside changelog", () => {
55
+ assertZeroGitGrep(FORBIDDEN_ENV_STACK, ["docs/changelog.md:"]);
56
+ });
57
+
58
+ test("tracked tree has zero legacy OKE env outside changelog", () => {
59
+ assertZeroGitGrep(FORBIDDEN_LEGACY_ENV, ["docs/changelog.md:"]);
60
+ });
61
+
62
+ test("tracked tree has zero legacy vault helper outside changelog + upgrade", () => {
63
+ assertZeroGitGrep(FORBIDDEN_FROM_STACK, [
64
+ "docs/changelog.md:",
65
+ "src/upgrade/codemods.ts:",
66
+ "src/upgrade/codemods.test.ts:",
67
+ ]);
68
+ });
69
+ });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `oke docker` / `oke stack` / `oke images pin` / `oke schema` / `oke dev --stack`.
2
+ * `oke docker` / `oke stack` / `oke images pin` / `oke schema` / `oke dev --docker`.
3
3
  */
4
4
 
5
5
  import { describe, expect, test } from "bun:test";
@@ -39,12 +39,10 @@ describe("oke docker CLI", () => {
39
39
  expect(code).toBe(0);
40
40
  expect(result).toBeDefined();
41
41
  expect(await Bun.file(join(dir, "docker/Dockerfile")).exists()).toBe(true);
42
- expect(
43
- await Bun.file(join(dir, "docker/compose.store.sql.yml")).exists(),
44
- ).toBe(true);
42
+ expect(await Bun.file(join(dir, "docker/compose.store.sql.yml")).exists()).toBe(true);
45
43
  const yml = await Bun.file(join(dir, "docker/compose.store.sql.yml")).text();
46
44
  expect(yml).not.toContain("test-password-not-in-yaml");
47
- expect(yml).toContain("../.env.stack");
45
+ expect(yml).toContain(".env.docker");
48
46
  expect(logs.join("")).toContain("docker/compose.override.yml");
49
47
  });
50
48
  });
@@ -149,13 +147,14 @@ describe("oke schema generate", () => {
149
147
  });
150
148
  });
151
149
 
152
- describe("oke dev --stack", () => {
153
- test("plans stack with postgres and writes nothing on dryRun", async () => {
150
+ describe("oke dev --docker", () => {
151
+ test("plans docker with postgres and writes nothing on dryRun", async () => {
154
152
  const dir = await mkdtemp(join(tmpdir(), "oke-cli-dev-dry-"));
155
153
  await Bun.write(join(dir, "src/app.ts"), "export {}\n");
156
154
  const { code, plan } = await runDev({
155
+ stdinIsTTY: false,
157
156
  cwd: dir,
158
- stack: ["store.sql"],
157
+ docker: ["store.sql"],
159
158
  images,
160
159
  credentials,
161
160
  dryRun: true,
package/src/cli/docker.ts CHANGED
@@ -93,9 +93,7 @@ export async function runDockerDerive(
93
93
  write(
94
94
  `compose merge order (cwd ${composeDir}/):\n${result.composeFiles.map((f) => ` -f ${f}`).join("\n")}\n`,
95
95
  );
96
- write(
97
- `(${composeDir}/compose.override.yml is layer 4 — user-owned, never written by oke)\n`,
98
- );
96
+ write(`(${composeDir}/compose.override.yml is layer 4 — user-owned, never written by oke)\n`);
99
97
  return { code: 0, result };
100
98
  } catch (err) {
101
99
  console.error(err instanceof Error ? err.message : String(err));
@@ -47,9 +47,7 @@ export async function runDoctorDiffExamples(): Promise<number> {
47
47
  }
48
48
 
49
49
  if (failed > 0) {
50
- console.log(
51
- "Acknowledge intentional breaks with `breaking: true` on the owning flow.",
52
- );
50
+ console.log("Acknowledge intentional breaks with `breaking: true` on the owning flow.");
53
51
  }
54
52
  return failed > 0 ? 1 : 0;
55
53
  }
@@ -9,10 +9,7 @@ import type { Manifest } from "../manifest/types.ts";
9
9
  import { parseManifest } from "../manifest/validate.ts";
10
10
  import { runDoctorDiff } from "./doctor-diff.ts";
11
11
 
12
- const baseUrl = new URL(
13
- "../manifest/fixtures/base.manifest.json",
14
- import.meta.url,
15
- );
12
+ const baseUrl = new URL("../manifest/fixtures/base.manifest.json", import.meta.url);
16
13
 
17
14
  async function loadBase(): Promise<Manifest> {
18
15
  return parseManifest(await Bun.file(baseUrl).text());
@@ -88,4 +85,3 @@ describe("oke doctor --diff", () => {
88
85
  }
89
86
  });
90
87
  });
91
-
@@ -34,10 +34,7 @@ export interface DoctorDiffOptions {
34
34
  * @param cwd - Repo root
35
35
  * @param baseBranch - Preferred base
36
36
  */
37
- readonly resolveMergeBase?: (
38
- cwd: string,
39
- baseBranch?: string,
40
- ) => Promise<string | null>;
37
+ readonly resolveMergeBase?: (cwd: string, baseBranch?: string) => Promise<string | null>;
41
38
  /**
42
39
  * Read a file at a git revision (tests).
43
40
  *
@@ -45,11 +42,7 @@ export interface DoctorDiffOptions {
45
42
  * @param rev - Commit-ish
46
43
  * @param path - Path relative to repo root
47
44
  */
48
- readonly readAtRevision?: (
49
- cwd: string,
50
- rev: string,
51
- path: string,
52
- ) => Promise<string | null>;
45
+ readonly readAtRevision?: (cwd: string, rev: string, path: string) => Promise<string | null>;
53
46
  /** Manifest relative path when using git (default: auto-detect). */
54
47
  readonly manifestPath?: string;
55
48
  readonly write?: (text: string) => void;
@@ -67,9 +60,7 @@ export interface DoctorDiffResult {
67
60
  *
68
61
  * @param options - Paths / injections / git helpers
69
62
  */
70
- export async function runDoctorDiff(
71
- options: DoctorDiffOptions = {},
72
- ): Promise<DoctorDiffResult> {
63
+ export async function runDoctorDiff(options: DoctorDiffOptions = {}): Promise<DoctorDiffResult> {
73
64
  const write = options.write ?? ((t) => process.stdout.write(t));
74
65
  const cwd = options.cwd ?? process.cwd();
75
66
 
@@ -86,15 +77,11 @@ export async function runDoctorDiff(
86
77
  return { code: EXIT_OK, undeclared, allChanges: all };
87
78
  }
88
79
 
89
- write(
90
- `oke doctor --diff: ${undeclared.length} undeclared contract-breaking change(s)\n`,
91
- );
80
+ write(`oke doctor --diff: ${undeclared.length} undeclared contract-breaking change(s)\n`);
92
81
  for (const c of undeclared) {
93
82
  write(` [contract-breaking] ${c.path}: ${c.summary}\n`);
94
83
  }
95
- write(
96
- "Acknowledge intentional breaks with `breaking: true` on the owning flow.\n",
97
- );
84
+ write("Acknowledge intentional breaks with `breaking: true` on the owning flow.\n");
98
85
  return { code: EXIT_RUNTIME, undeclared, allChanges: all };
99
86
  }
100
87
 
@@ -125,20 +112,16 @@ async function resolveManifests(
125
112
  );
126
113
  }
127
114
 
128
- const rel =
129
- options.manifestPath ??
130
- (await detectManifestRel(cwd));
115
+ const rel = options.manifestPath ?? (await detectManifestRel(cwd));
131
116
  if (!rel) {
132
117
  throw new Error(
133
118
  "oke doctor --diff: no oke.manifest.json or manifest.oke.json in cwd — pass --before/--after",
134
119
  );
135
120
  }
136
121
 
137
- const after =
138
- options.after ?? (await loadManifest(resolve(cwd, rel)));
122
+ const after = options.after ?? (await loadManifest(resolve(cwd, rel)));
139
123
 
140
- const resolveBase =
141
- options.resolveMergeBase ?? gitMergeBase;
124
+ const resolveBase = options.resolveMergeBase ?? gitMergeBase;
142
125
  const readAt = options.readAtRevision ?? gitShow;
143
126
  const mergeBase = await resolveBase(cwd, options.baseBranch);
144
127
  if (!mergeBase) {
@@ -177,23 +160,18 @@ async function detectManifestRel(cwd: string): Promise<string | null> {
177
160
  * @param cwd - Repo root
178
161
  * @param baseBranch - Preferred base
179
162
  */
180
- export async function gitMergeBase(
181
- cwd: string,
182
- baseBranch?: string,
183
- ): Promise<string | null> {
163
+ export async function gitMergeBase(cwd: string, baseBranch?: string): Promise<string | null> {
184
164
  const candidates = baseBranch
185
165
  ? [baseBranch, ...BASE_BRANCH_CANDIDATES.filter((b) => b !== baseBranch)]
186
166
  : [...BASE_BRANCH_CANDIDATES];
187
167
 
188
168
  for (const base of candidates) {
189
- const proc = Bun.spawn(
190
- ["git", "merge-base", "HEAD", base],
191
- { cwd, stdout: "pipe", stderr: "pipe" },
192
- );
193
- const [stdout, exitCode] = await Promise.all([
194
- new Response(proc.stdout).text(),
195
- proc.exited,
196
- ]);
169
+ const proc = Bun.spawn(["git", "merge-base", "HEAD", base], {
170
+ cwd,
171
+ stdout: "pipe",
172
+ stderr: "pipe",
173
+ });
174
+ const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
197
175
  if (exitCode === 0) {
198
176
  const rev = stdout.trim();
199
177
  if (rev.length > 0) return rev;
@@ -209,20 +187,13 @@ export async function gitMergeBase(
209
187
  * @param rev - Commit-ish
210
188
  * @param path - Path relative to repo root
211
189
  */
212
- export async function gitShow(
213
- cwd: string,
214
- rev: string,
215
- path: string,
216
- ): Promise<string | null> {
190
+ export async function gitShow(cwd: string, rev: string, path: string): Promise<string | null> {
217
191
  const proc = Bun.spawn(["git", "show", `${rev}:${path}`], {
218
192
  cwd,
219
193
  stdout: "pipe",
220
194
  stderr: "pipe",
221
195
  });
222
- const [stdout, exitCode] = await Promise.all([
223
- new Response(proc.stdout).text(),
224
- proc.exited,
225
- ]);
196
+ const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
226
197
  if (exitCode !== 0) return null;
227
198
  return stdout;
228
199
  }
@@ -4,10 +4,7 @@
4
4
  * Reuses {@link assertAllowPiiForAsk} — does not reimplement matching.
5
5
  */
6
6
 
7
- import {
8
- AiPiiBuildError,
9
- assertAllowPiiForAsk,
10
- } from "../elements/ai/pii.ts";
7
+ import { AiPiiBuildError, assertAllowPiiForAsk } from "../elements/ai/pii.ts";
11
8
  import type {
12
9
  AiPrompt,
13
10
  ClassificationValue,
@@ -23,9 +20,7 @@ import type { DoctorFinding } from "./doctor.ts";
23
20
  *
24
21
  * @param manifest - Extracted Manifest
25
22
  */
26
- export function checkManifestPiiAsks(
27
- manifest: Manifest,
28
- ): readonly DoctorFinding[] {
23
+ export function checkManifestPiiAsks(manifest: Manifest): readonly DoctorFinding[] {
29
24
  const findings: DoctorFinding[] = [];
30
25
  const classifications = collectClassifications(manifest);
31
26
  const flows = manifest.flows ?? {};
@@ -14,13 +14,12 @@ describe("oke doctor", () => {
14
14
  ports: [],
15
15
  currentSchemaFingerprint: null,
16
16
  expectedSchemaFingerprint: undefined,
17
+ skipDbDrift: true,
17
18
  write: () => {},
18
19
  });
19
20
  expect(code).toBe(2);
20
21
  expect(findings.some((f) => f.code === "missing_secret")).toBe(true);
21
- expect(
22
- findings.find((f) => f.message.includes("STRIPE_KEY")),
23
- ).toBeDefined();
22
+ expect(findings.find((f) => f.message.includes("STRIPE_KEY"))).toBeDefined();
24
23
  });
25
24
 
26
25
  test("catches a port conflict", async () => {
@@ -30,6 +29,7 @@ describe("oke doctor", () => {
30
29
  isPortInUse: async (p) => p === 6530,
31
30
  currentSchemaFingerprint: "abc",
32
31
  expectedSchemaFingerprint: "abc",
32
+ skipDbDrift: true,
33
33
  write: () => {},
34
34
  });
35
35
  expect(code).toBe(2);
@@ -37,17 +37,36 @@ describe("oke doctor", () => {
37
37
  expect(findings[0]!.message).toContain("6530");
38
38
  });
39
39
 
40
- test("catches schema drift", async () => {
40
+ test("catches core stub schema drift", async () => {
41
41
  const { code, findings } = await runDoctor({
42
42
  secrets: [],
43
43
  ports: [],
44
44
  isPortInUse: async () => false,
45
45
  expectedSchemaFingerprint: "aaa",
46
46
  currentSchemaFingerprint: "bbb",
47
+ skipDbDrift: true,
47
48
  write: () => {},
48
49
  });
49
50
  expect(code).toBe(2);
50
51
  expect(findings.some((f) => f.code === "schema_drift")).toBe(true);
52
+ expect(findings.find((f) => f.code === "schema_drift")?.message).toContain(
53
+ "oke schema generate",
54
+ );
55
+ });
56
+
57
+ test("catches domain db_drift from drizzle-kit probe", async () => {
58
+ const { code, findings } = await runDoctor({
59
+ secrets: [],
60
+ ports: [],
61
+ isPortInUse: async () => false,
62
+ currentSchemaFingerprint: null,
63
+ skipDbDrift: false,
64
+ detectDbDrift: async () => ({ drifted: true, detail: "pending migrations" }),
65
+ write: () => {},
66
+ });
67
+ expect(code).toBe(2);
68
+ expect(findings.some((f) => f.code === "db_drift")).toBe(true);
69
+ expect(findings.find((f) => f.code === "db_drift")?.message).toContain("pending");
51
70
  });
52
71
 
53
72
  test("ok when secrets present, ports free, schema matches", async () => {
@@ -58,6 +77,7 @@ describe("oke doctor", () => {
58
77
  isPortInUse: async () => false,
59
78
  expectedSchemaFingerprint: "same",
60
79
  currentSchemaFingerprint: "same",
80
+ skipDbDrift: true,
61
81
  write: () => {},
62
82
  });
63
83
  expect(code).toBe(0);
@@ -99,6 +119,7 @@ describe("oke doctor", () => {
99
119
  secrets: [],
100
120
  ports: [],
101
121
  currentSchemaFingerprint: null,
122
+ skipDbDrift: true,
102
123
  write: () => {},
103
124
  });
104
125
 
@@ -142,6 +163,7 @@ describe("oke doctor", () => {
142
163
  ports: [],
143
164
  expectedSchemaFingerprint: "same",
144
165
  currentSchemaFingerprint: "same",
166
+ skipDbDrift: true,
145
167
  write: () => {},
146
168
  });
147
169
  expect(code).toBe(0);
package/src/cli/doctor.ts CHANGED
@@ -20,6 +20,7 @@ export interface DoctorFinding {
20
20
  | "missing_secret"
21
21
  | "port_conflict"
22
22
  | "schema_drift"
23
+ | "db_drift"
23
24
  | "tenancy"
24
25
  | "driver"
25
26
  | "pii_ask";
@@ -44,6 +45,16 @@ export interface DoctorOptions {
44
45
  readonly expectedSchemaFingerprint?: string;
45
46
  /** Current schema fingerprint (tests). */
46
47
  readonly currentSchemaFingerprint?: string | null;
48
+ /**
49
+ * Inject domain DB drift probe (tests). When unset, runs drizzle-kit
50
+ * push explain when `drizzle.config.ts` exists.
51
+ */
52
+ readonly detectDbDrift?: () => Promise<{
53
+ readonly drifted: boolean;
54
+ readonly detail?: string;
55
+ }>;
56
+ /** Skip live DB drift probe (default false). */
57
+ readonly skipDbDrift?: boolean;
47
58
  readonly write?: (text: string) => void;
48
59
  /** Write hints / progress (defaults to stderr). */
49
60
  readonly writeErr?: (text: string) => void;
@@ -79,9 +90,7 @@ export async function runDoctor(options: DoctorOptions = {}): Promise<{
79
90
  }
80
91
 
81
92
  const env = options.env ?? ((k) => Bun.env[k] ?? process.env[k]);
82
- const secretNames =
83
- options.secrets ??
84
- (manifest?.vault ? Object.keys(manifest.vault) : []);
93
+ const secretNames = options.secrets ?? (manifest?.vault ? Object.keys(manifest.vault) : []);
85
94
 
86
95
  for (const name of secretNames) {
87
96
  const value = env(name);
@@ -90,9 +99,7 @@ export async function runDoctor(options: DoctorOptions = {}): Promise<{
90
99
  findings.push({
91
100
  code: "missing_secret",
92
101
  severity: "error",
93
- message: description
94
- ? `missing secret ${name}: ${description}`
95
- : `missing secret ${name}`,
102
+ message: description ? `missing secret ${name}: ${description}` : `missing secret ${name}`,
96
103
  });
97
104
  }
98
105
  }
@@ -120,24 +127,42 @@ export async function runDoctor(options: DoctorOptions = {}): Promise<{
120
127
  options.currentSchemaFingerprint !== undefined
121
128
  ) {
122
129
  const expected =
123
- options.expectedSchemaFingerprint ??
124
- (await schemaFingerprint(cwd).catch(() => null));
130
+ options.expectedSchemaFingerprint ?? (await schemaFingerprint(cwd).catch(() => null));
125
131
  if (expected !== null && current !== null && expected !== current) {
126
132
  findings.push({
127
133
  code: "schema_drift",
128
134
  severity: "error",
129
135
  message:
130
- "schema drift detected — run `oke schema generate` (or --check in CI)",
136
+ "core stub schema drift — run `oke schema generate` (schema/oke.ts; not domain migrations)",
131
137
  });
132
138
  } else if (expected !== null && current === null) {
133
139
  findings.push({
134
140
  code: "schema_drift",
135
141
  severity: "error",
136
- message: "schema/oke.ts missing — run `oke schema generate`",
142
+ message: "schema/oke.ts missing — run `oke schema generate` (core/plugin stubs)",
137
143
  });
138
144
  }
139
145
  }
140
146
 
147
+ // Domain schema ↔ live DB — drizzle-kit is the single source of truth.
148
+ if (!options.skipDbDrift) {
149
+ const drizzleConfig = Bun.file(resolve(cwd, "drizzle.config.ts"));
150
+ if (options.detectDbDrift || (await drizzleConfig.exists())) {
151
+ const { detectDbDrift } = await import("./db.ts");
152
+ const probe = options.detectDbDrift ?? (() => detectDbDrift({ cwd }));
153
+ const drift = await probe();
154
+ if (drift.drifted) {
155
+ findings.push({
156
+ code: "db_drift",
157
+ severity: "error",
158
+ message:
159
+ drift.detail ??
160
+ "domain schema differs from the database — run `oke db generate` then `oke db migrate` (or `oke db push` in local)",
161
+ });
162
+ }
163
+ }
164
+ }
165
+
141
166
  if (manifest?.tenancy?.isolation) {
142
167
  // Structural tenancy check is compile-time; doctor warns when isolation
143
168
  // is set but no tenant resolver string is recorded on the Manifest.
@@ -205,4 +230,3 @@ Verify secrets, ports, schema drift, and PII→model egress before serving.
205
230
  const { code } = await runDoctor({ manifestPath, json });
206
231
  return code;
207
232
  }
208
-