okengine 0.1.4

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 (674) hide show
  1. package/AGENTS.md +91 -0
  2. package/README.md +327 -0
  3. package/docs/spec/complete-example.md +1188 -0
  4. package/docs/spec/console.md +739 -0
  5. package/docs/spec/four-applications.md +1188 -0
  6. package/docs/spec/unified-theory.md +489 -0
  7. package/package.json +152 -0
  8. package/spec/manifest.v1.schema.json +624 -0
  9. package/src/auth/api-keys.ts +168 -0
  10. package/src/auth/attenuation.ts +116 -0
  11. package/src/auth/auth.test.ts +273 -0
  12. package/src/auth/cross-plane.ts +98 -0
  13. package/src/auth/index.ts +112 -0
  14. package/src/auth/invites.ts +66 -0
  15. package/src/auth/invoke-as.ts +49 -0
  16. package/src/auth/operator.ts +178 -0
  17. package/src/auth/planes.ts +102 -0
  18. package/src/auth/plugin.ts +44 -0
  19. package/src/auth/roles.ts +84 -0
  20. package/src/auth/sessions.ts +418 -0
  21. package/src/auth/tables.ts +131 -0
  22. package/src/cli/args.ts +50 -0
  23. package/src/cli/branch.ts +75 -0
  24. package/src/cli/build.ts +86 -0
  25. package/src/cli/client-add.test.ts +140 -0
  26. package/src/cli/client-add.ts +164 -0
  27. package/src/cli/completion.test.ts +58 -0
  28. package/src/cli/completion.ts +296 -0
  29. package/src/cli/dev-app-runner.ts +77 -0
  30. package/src/cli/dev.test.ts +435 -0
  31. package/src/cli/dev.ts +594 -0
  32. package/src/cli/doc-drift.test.ts +146 -0
  33. package/src/cli/doc-drift.ts +397 -0
  34. package/src/cli/docker-cli.test.ts +221 -0
  35. package/src/cli/docker.ts +127 -0
  36. package/src/cli/doctor-diff-examples.ts +92 -0
  37. package/src/cli/doctor-diff.test.ts +91 -0
  38. package/src/cli/doctor-diff.ts +274 -0
  39. package/src/cli/doctor-pii.test.ts +98 -0
  40. package/src/cli/doctor-pii.ts +151 -0
  41. package/src/cli/doctor.test.ts +150 -0
  42. package/src/cli/doctor.ts +223 -0
  43. package/src/cli/eval.ts +122 -0
  44. package/src/cli/exit.ts +19 -0
  45. package/src/cli/gates-list.test.ts +47 -0
  46. package/src/cli/gates-list.ts +84 -0
  47. package/src/cli/images.ts +277 -0
  48. package/src/cli/index.ts +99 -0
  49. package/src/cli/json-out.test.ts +129 -0
  50. package/src/cli/load-config.ts +71 -0
  51. package/src/cli/mcp-from-console.ts +50 -0
  52. package/src/cli/privacy-erase.ts +73 -0
  53. package/src/cli/registry.ts +455 -0
  54. package/src/cli/safe-defaults.test.ts +92 -0
  55. package/src/cli/schema.ts +196 -0
  56. package/src/cli/stack.ts +82 -0
  57. package/src/cli/start.ts +106 -0
  58. package/src/cli/upgrade.ts +105 -0
  59. package/src/cli/vault-cmd.ts +140 -0
  60. package/src/client/budget-entry.ts +34 -0
  61. package/src/client/budget.test.ts +17 -0
  62. package/src/client/create.test.ts +159 -0
  63. package/src/client/create.ts +152 -0
  64. package/src/client/errors.ts +60 -0
  65. package/src/client/index.ts +35 -0
  66. package/src/client/notes-contract.test.ts +289 -0
  67. package/src/client/transport.test.ts +123 -0
  68. package/src/client/transport.ts +254 -0
  69. package/src/client/types.ts +282 -0
  70. package/src/compiler/aot.test.ts +248 -0
  71. package/src/compiler/aot.ts +182 -0
  72. package/src/compiler/differential.test.ts +241 -0
  73. package/src/compiler/dynamic.ts +54 -0
  74. package/src/compiler/effects-infer.ts +541 -0
  75. package/src/compiler/emit.ts +40 -0
  76. package/src/compiler/extract.test.ts +177 -0
  77. package/src/compiler/extract.ts +1368 -0
  78. package/src/compiler/fixtures/raw/raw-unannotated.ts +28 -0
  79. package/src/compiler/fixtures/skyport/oke.config.ts +24 -0
  80. package/src/compiler/fixtures/skyport/src/ai.ts +15 -0
  81. package/src/compiler/fixtures/skyport/src/app.ts +10 -0
  82. package/src/compiler/fixtures/skyport/src/channels.ts +6 -0
  83. package/src/compiler/fixtures/skyport/src/core.ts +3 -0
  84. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +57 -0
  85. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +11 -0
  86. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +14 -0
  87. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +20 -0
  88. package/src/compiler/fixtures/skyport/src/gates.ts +14 -0
  89. package/src/compiler/fixtures/skyport/src/journeys.ts +9 -0
  90. package/src/compiler/fixtures/skyport/src/schema.ts +3 -0
  91. package/src/compiler/fixtures/skyport/src/vault.ts +6 -0
  92. package/src/compiler/fixtures/skyport.expected.json +241 -0
  93. package/src/compiler/fixtures/triggers/five-triggers.ts +69 -0
  94. package/src/compiler/http-parse.ts +214 -0
  95. package/src/compiler/index.ts +67 -0
  96. package/src/compiler/response.ts +89 -0
  97. package/src/compiler/sucrose.ts +238 -0
  98. package/src/config/index.ts +167 -0
  99. package/src/console/budget.test.ts +73 -0
  100. package/src/console/index.ts +30 -0
  101. package/src/console/server/access.test.ts +370 -0
  102. package/src/console/server/access.ts +777 -0
  103. package/src/console/server/ai.test.ts +172 -0
  104. package/src/console/server/ai.ts +632 -0
  105. package/src/console/server/app.ts +294 -0
  106. package/src/console/server/auth-rate.test.ts +81 -0
  107. package/src/console/server/auth-rate.ts +72 -0
  108. package/src/console/server/bind.ts +25 -0
  109. package/src/console/server/channels.test.ts +179 -0
  110. package/src/console/server/channels.ts +469 -0
  111. package/src/console/server/claim.test.ts +66 -0
  112. package/src/console/server/claim.ts +134 -0
  113. package/src/console/server/clock.test.ts +239 -0
  114. package/src/console/server/clock.ts +390 -0
  115. package/src/console/server/console.test.ts +338 -0
  116. package/src/console/server/diff.test.ts +299 -0
  117. package/src/console/server/diff.ts +352 -0
  118. package/src/console/server/dry-run.audit.test.ts +118 -0
  119. package/src/console/server/flows-invoke.test.ts +148 -0
  120. package/src/console/server/flows.ts +3633 -0
  121. package/src/console/server/gates.test.ts +360 -0
  122. package/src/console/server/gates.ts +869 -0
  123. package/src/console/server/index.ts +141 -0
  124. package/src/console/server/live.test.ts +30 -0
  125. package/src/console/server/live.ts +109 -0
  126. package/src/console/server/plugin.ts +50 -0
  127. package/src/console/server/plugins.test.ts +131 -0
  128. package/src/console/server/plugins.ts +429 -0
  129. package/src/console/server/runs-pii.ts +98 -0
  130. package/src/console/server/security-headers.ts +97 -0
  131. package/src/console/server/security.gate.test.ts +286 -0
  132. package/src/console/server/serve.ts +319 -0
  133. package/src/console/server/signals.test.ts +88 -0
  134. package/src/console/server/signals.ts +282 -0
  135. package/src/console/server/state.ts +982 -0
  136. package/src/console/server/store.test.ts +233 -0
  137. package/src/console/server/store.ts +861 -0
  138. package/src/console/server/structural.ts +95 -0
  139. package/src/console/server/vault.test.ts +251 -0
  140. package/src/console/server/vault.ts +430 -0
  141. package/src/console/ui/access/AccessA11yView.tsx +237 -0
  142. package/src/console/ui/access/a11y.test.tsx +122 -0
  143. package/src/console/ui/access/acknowledgement.test.ts +13 -0
  144. package/src/console/ui/access/acknowledgement.ts +35 -0
  145. package/src/console/ui/access/blast-radius.test.ts +26 -0
  146. package/src/console/ui/access/blast-radius.ts +40 -0
  147. package/src/console/ui/access/confirmation.test.ts +38 -0
  148. package/src/console/ui/access/confirmation.ts +36 -0
  149. package/src/console/ui/access/fixture.ts +203 -0
  150. package/src/console/ui/access/grantable.test.ts +17 -0
  151. package/src/console/ui/access/grantable.ts +36 -0
  152. package/src/console/ui/access/hygiene.test.ts +12 -0
  153. package/src/console/ui/access/hygiene.ts +39 -0
  154. package/src/console/ui/access/index.ts +54 -0
  155. package/src/console/ui/access/provenance.test.ts +12 -0
  156. package/src/console/ui/access/provenance.ts +29 -0
  157. package/src/console/ui/access/search.test.ts +17 -0
  158. package/src/console/ui/access/search.ts +72 -0
  159. package/src/console/ui/access/types.ts +111 -0
  160. package/src/console/ui/ai/AiA11yView.tsx +265 -0
  161. package/src/console/ui/ai/a11y.test.tsx +99 -0
  162. package/src/console/ui/ai/findings.ts +41 -0
  163. package/src/console/ui/ai/fixture.ts +182 -0
  164. package/src/console/ui/ai/format.ts +90 -0
  165. package/src/console/ui/ai/group.test.ts +37 -0
  166. package/src/console/ui/ai/group.ts +88 -0
  167. package/src/console/ui/ai/index.ts +66 -0
  168. package/src/console/ui/ai/promotion.test.ts +77 -0
  169. package/src/console/ui/ai/promotion.ts +150 -0
  170. package/src/console/ui/ai/search.test.ts +40 -0
  171. package/src/console/ui/ai/search.ts +89 -0
  172. package/src/console/ui/ai/types.ts +139 -0
  173. package/src/console/ui/architecture/ArchitectureA11yView.tsx +163 -0
  174. package/src/console/ui/architecture/a11y.test.tsx +97 -0
  175. package/src/console/ui/architecture/boundary.ts +42 -0
  176. package/src/console/ui/architecture/declared.ts +165 -0
  177. package/src/console/ui/architecture/fixture.ts +74 -0
  178. package/src/console/ui/architecture/index.ts +84 -0
  179. package/src/console/ui/architecture/layers.ts +64 -0
  180. package/src/console/ui/architecture/layout.ts +68 -0
  181. package/src/console/ui/architecture/pathologies.ts +260 -0
  182. package/src/console/ui/architecture/search.ts +145 -0
  183. package/src/console/ui/architecture/traffic.ts +102 -0
  184. package/src/console/ui/architecture/types.ts +144 -0
  185. package/src/console/ui/architecture/view.test.ts +165 -0
  186. package/src/console/ui/architecture/view.ts +516 -0
  187. package/src/console/ui/channels/ChannelsA11yView.tsx +180 -0
  188. package/src/console/ui/channels/a11y.test.tsx +96 -0
  189. package/src/console/ui/channels/confirmation.test.ts +37 -0
  190. package/src/console/ui/channels/confirmation.ts +27 -0
  191. package/src/console/ui/channels/fallback.test.ts +15 -0
  192. package/src/console/ui/channels/fallback.ts +20 -0
  193. package/src/console/ui/channels/findings.ts +38 -0
  194. package/src/console/ui/channels/fixture.ts +134 -0
  195. package/src/console/ui/channels/group.ts +25 -0
  196. package/src/console/ui/channels/index.ts +57 -0
  197. package/src/console/ui/channels/locale.test.ts +17 -0
  198. package/src/console/ui/channels/locale.ts +31 -0
  199. package/src/console/ui/channels/mask.test.ts +14 -0
  200. package/src/console/ui/channels/mask.ts +12 -0
  201. package/src/console/ui/channels/search.ts +58 -0
  202. package/src/console/ui/channels/taxonomy.test.ts +17 -0
  203. package/src/console/ui/channels/taxonomy.ts +49 -0
  204. package/src/console/ui/channels/types.ts +117 -0
  205. package/src/console/ui/clock/ClockA11yView.tsx +182 -0
  206. package/src/console/ui/clock/a11y.test.tsx +99 -0
  207. package/src/console/ui/clock/confirmation.test.ts +32 -0
  208. package/src/console/ui/clock/confirmation.ts +34 -0
  209. package/src/console/ui/clock/findings.ts +40 -0
  210. package/src/console/ui/clock/fixture.ts +111 -0
  211. package/src/console/ui/clock/health.test.ts +25 -0
  212. package/src/console/ui/clock/health.ts +61 -0
  213. package/src/console/ui/clock/index.ts +49 -0
  214. package/src/console/ui/clock/search.test.ts +39 -0
  215. package/src/console/ui/clock/search.ts +76 -0
  216. package/src/console/ui/clock/timeline.test.ts +44 -0
  217. package/src/console/ui/clock/timeline.ts +41 -0
  218. package/src/console/ui/clock/types.ts +78 -0
  219. package/src/console/ui/clock/waiting-on.test.ts +34 -0
  220. package/src/console/ui/clock/waiting-on.ts +83 -0
  221. package/src/console/ui/confirmation.unify.test.ts +92 -0
  222. package/src/console/ui/diff/DiffA11yView.tsx +85 -0
  223. package/src/console/ui/diff/a11y.test.tsx +99 -0
  224. package/src/console/ui/diff/fixture.ts +85 -0
  225. package/src/console/ui/diff/group.test.ts +58 -0
  226. package/src/console/ui/diff/group.ts +97 -0
  227. package/src/console/ui/diff/index.ts +38 -0
  228. package/src/console/ui/diff/search.test.ts +32 -0
  229. package/src/console/ui/diff/search.ts +75 -0
  230. package/src/console/ui/diff/summary.ts +74 -0
  231. package/src/console/ui/diff/types.ts +48 -0
  232. package/src/console/ui/dist/assets/index-B71Yl_SS.js +10 -0
  233. package/src/console/ui/dist/assets/panel-access-Dd37LU2c.js +64 -0
  234. package/src/console/ui/dist/assets/panel-ai-CC7LR6-J.js +1 -0
  235. package/src/console/ui/dist/assets/panel-architecture-B5b3iKCz.js +1 -0
  236. package/src/console/ui/dist/assets/panel-channels-CeNjTKXp.js +1 -0
  237. package/src/console/ui/dist/assets/panel-clock-DgFTLoHV.js +1 -0
  238. package/src/console/ui/dist/assets/panel-diff-DxehccqB.js +1 -0
  239. package/src/console/ui/dist/assets/panel-flows-BtrVn-Eg.js +45 -0
  240. package/src/console/ui/dist/assets/panel-gates-Z9MKRGdH.js +1 -0
  241. package/src/console/ui/dist/assets/panel-overview-Bd48d9km.js +1 -0
  242. package/src/console/ui/dist/assets/panel-plugins-DWd0TowH.js +1 -0
  243. package/src/console/ui/dist/assets/panel-runs-BwsWqKeB.js +1 -0
  244. package/src/console/ui/dist/assets/panel-signals-9najbZY2.js +1 -0
  245. package/src/console/ui/dist/assets/panel-store-OHkP2pDp.js +1 -0
  246. package/src/console/ui/dist/assets/panel-traces-tn2JoY8U.js +1 -0
  247. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +1 -0
  248. package/src/console/ui/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
  249. package/src/console/ui/dist/assets/style-Cnl7WLya.css +3 -0
  250. package/src/console/ui/dist/index.html +14 -0
  251. package/src/console/ui/flows/FlowsA11yView.tsx +155 -0
  252. package/src/console/ui/flows/a11y.test.tsx +105 -0
  253. package/src/console/ui/flows/buffer.test.ts +91 -0
  254. package/src/console/ui/flows/buffer.ts +118 -0
  255. package/src/console/ui/flows/confirmation.ts +131 -0
  256. package/src/console/ui/flows/contract.test.ts +89 -0
  257. package/src/console/ui/flows/contract.ts +353 -0
  258. package/src/console/ui/flows/fixture.ts +81 -0
  259. package/src/console/ui/flows/graph.test.ts +101 -0
  260. package/src/console/ui/flows/graph.ts +549 -0
  261. package/src/console/ui/flows/index.ts +87 -0
  262. package/src/console/ui/flows/save-as-test.test.ts +47 -0
  263. package/src/console/ui/flows/save-as-test.ts +99 -0
  264. package/src/console/ui/flows/search.ts +255 -0
  265. package/src/console/ui/flows/tiers.ts +140 -0
  266. package/src/console/ui/gates/GatesA11yView.tsx +192 -0
  267. package/src/console/ui/gates/a11y.test.tsx +116 -0
  268. package/src/console/ui/gates/audit.test.ts +40 -0
  269. package/src/console/ui/gates/audit.ts +63 -0
  270. package/src/console/ui/gates/denial.test.ts +36 -0
  271. package/src/console/ui/gates/denial.ts +51 -0
  272. package/src/console/ui/gates/findings.ts +19 -0
  273. package/src/console/ui/gates/fixture.ts +189 -0
  274. package/src/console/ui/gates/group.test.ts +30 -0
  275. package/src/console/ui/gates/group.ts +102 -0
  276. package/src/console/ui/gates/index.ts +47 -0
  277. package/src/console/ui/gates/search.test.ts +49 -0
  278. package/src/console/ui/gates/search.ts +115 -0
  279. package/src/console/ui/gates/types.ts +121 -0
  280. package/src/console/ui/overview/OverviewA11yView.tsx +152 -0
  281. package/src/console/ui/overview/a11y.test.tsx +113 -0
  282. package/src/console/ui/overview/busiest.ts +26 -0
  283. package/src/console/ui/overview/compose.ts +133 -0
  284. package/src/console/ui/overview/cost.test.ts +39 -0
  285. package/src/console/ui/overview/cost.ts +138 -0
  286. package/src/console/ui/overview/fixture.ts +161 -0
  287. package/src/console/ui/overview/golden.ts +57 -0
  288. package/src/console/ui/overview/index.ts +59 -0
  289. package/src/console/ui/overview/rank.test.ts +136 -0
  290. package/src/console/ui/overview/rank.ts +210 -0
  291. package/src/console/ui/overview/slo.test.ts +73 -0
  292. package/src/console/ui/overview/slo.ts +229 -0
  293. package/src/console/ui/overview/types.ts +121 -0
  294. package/src/console/ui/overview/verdict.ts +131 -0
  295. package/src/console/ui/plugins/PluginsA11yView.tsx +227 -0
  296. package/src/console/ui/plugins/a11y.test.tsx +97 -0
  297. package/src/console/ui/plugins/command.test.ts +22 -0
  298. package/src/console/ui/plugins/command.ts +27 -0
  299. package/src/console/ui/plugins/findings.ts +39 -0
  300. package/src/console/ui/plugins/fixture.ts +233 -0
  301. package/src/console/ui/plugins/group.test.ts +38 -0
  302. package/src/console/ui/plugins/group.ts +67 -0
  303. package/src/console/ui/plugins/index.ts +40 -0
  304. package/src/console/ui/plugins/search.ts +67 -0
  305. package/src/console/ui/plugins/types.ts +115 -0
  306. package/src/console/ui/runs/RunsA11yView.tsx +267 -0
  307. package/src/console/ui/runs/a11y.test.tsx +99 -0
  308. package/src/console/ui/runs/explain.test.ts +23 -0
  309. package/src/console/ui/runs/explain.ts +32 -0
  310. package/src/console/ui/runs/fixture.ts +189 -0
  311. package/src/console/ui/runs/group.test.ts +24 -0
  312. package/src/console/ui/runs/group.ts +85 -0
  313. package/src/console/ui/runs/histogram.test.ts +31 -0
  314. package/src/console/ui/runs/histogram.ts +85 -0
  315. package/src/console/ui/runs/index.ts +75 -0
  316. package/src/console/ui/runs/project.ts +122 -0
  317. package/src/console/ui/runs/query.test.ts +50 -0
  318. package/src/console/ui/runs/query.ts +283 -0
  319. package/src/console/ui/runs/search.test.ts +45 -0
  320. package/src/console/ui/runs/search.ts +141 -0
  321. package/src/console/ui/runs/trace-link.test.ts +30 -0
  322. package/src/console/ui/runs/trace-link.ts +99 -0
  323. package/src/console/ui/runs/types.ts +137 -0
  324. package/src/console/ui/shell/App.tsx +56 -0
  325. package/src/console/ui/shell/client.ts +1715 -0
  326. package/src/console/ui/shell/components/ui.tsx +110 -0
  327. package/src/console/ui/shell/index.html +12 -0
  328. package/src/console/ui/shell/layout/Shell.tsx +95 -0
  329. package/src/console/ui/shell/main.tsx +281 -0
  330. package/src/console/ui/shell/panels/Access.tsx +5 -0
  331. package/src/console/ui/shell/panels/Ai.tsx +5 -0
  332. package/src/console/ui/shell/panels/Architecture.tsx +5 -0
  333. package/src/console/ui/shell/panels/Channels.tsx +5 -0
  334. package/src/console/ui/shell/panels/Clock.tsx +5 -0
  335. package/src/console/ui/shell/panels/Diff.tsx +5 -0
  336. package/src/console/ui/shell/panels/Flows.tsx +5 -0
  337. package/src/console/ui/shell/panels/Gates.tsx +5 -0
  338. package/src/console/ui/shell/panels/Overview.tsx +6 -0
  339. package/src/console/ui/shell/panels/Plugins.tsx +5 -0
  340. package/src/console/ui/shell/panels/Runs.tsx +5 -0
  341. package/src/console/ui/shell/panels/Signals.tsx +5 -0
  342. package/src/console/ui/shell/panels/Store.tsx +5 -0
  343. package/src/console/ui/shell/panels/Traces.tsx +5 -0
  344. package/src/console/ui/shell/panels/Vault.tsx +5 -0
  345. package/src/console/ui/shell/panels/access/AccessPanel.tsx +813 -0
  346. package/src/console/ui/shell/panels/ai/AiPanel.tsx +563 -0
  347. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +377 -0
  348. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +454 -0
  349. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +479 -0
  350. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +275 -0
  351. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +301 -0
  352. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +350 -0
  353. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +502 -0
  354. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +482 -0
  355. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +428 -0
  356. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +413 -0
  357. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +649 -0
  358. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +840 -0
  359. package/src/console/ui/shell/panels/store/StorePanel.tsx +787 -0
  360. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +539 -0
  361. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +449 -0
  362. package/src/console/ui/shell/plugin/Sandbox.tsx +29 -0
  363. package/src/console/ui/shell/setup/Wizard.tsx +189 -0
  364. package/src/console/ui/shell/styles.css +75 -0
  365. package/src/console/ui/signals/SignalsA11yView.tsx +276 -0
  366. package/src/console/ui/signals/a11y.test.tsx +99 -0
  367. package/src/console/ui/signals/confirmation.test.ts +39 -0
  368. package/src/console/ui/signals/confirmation.ts +63 -0
  369. package/src/console/ui/signals/dry-run.test.ts +18 -0
  370. package/src/console/ui/signals/dry-run.ts +36 -0
  371. package/src/console/ui/signals/durable.test.ts +22 -0
  372. package/src/console/ui/signals/durable.ts +41 -0
  373. package/src/console/ui/signals/findings.ts +33 -0
  374. package/src/console/ui/signals/fixture.ts +242 -0
  375. package/src/console/ui/signals/group.test.ts +32 -0
  376. package/src/console/ui/signals/group.ts +49 -0
  377. package/src/console/ui/signals/index.ts +52 -0
  378. package/src/console/ui/signals/monitor.test.ts +30 -0
  379. package/src/console/ui/signals/monitor.ts +79 -0
  380. package/src/console/ui/signals/schema-form.test.ts +34 -0
  381. package/src/console/ui/signals/schema-form.ts +112 -0
  382. package/src/console/ui/signals/search.ts +102 -0
  383. package/src/console/ui/signals/types.ts +71 -0
  384. package/src/console/ui/store/StoreA11yView.tsx +199 -0
  385. package/src/console/ui/store/a11y.test.tsx +99 -0
  386. package/src/console/ui/store/cache-view.test.ts +13 -0
  387. package/src/console/ui/store/cache-view.ts +36 -0
  388. package/src/console/ui/store/confirmation.test.ts +38 -0
  389. package/src/console/ui/store/confirmation.ts +55 -0
  390. package/src/console/ui/store/dry-run.test.ts +15 -0
  391. package/src/console/ui/store/dry-run.ts +29 -0
  392. package/src/console/ui/store/fixture.ts +163 -0
  393. package/src/console/ui/store/group.test.ts +21 -0
  394. package/src/console/ui/store/group.ts +41 -0
  395. package/src/console/ui/store/index.ts +40 -0
  396. package/src/console/ui/store/search.ts +78 -0
  397. package/src/console/ui/store/types.ts +65 -0
  398. package/src/console/ui/store/will-not-fire.test.ts +19 -0
  399. package/src/console/ui/store/will-not-fire.ts +40 -0
  400. package/src/console/ui/traces/TracesA11yView.tsx +200 -0
  401. package/src/console/ui/traces/a11y.test.tsx +97 -0
  402. package/src/console/ui/traces/chain.test.ts +61 -0
  403. package/src/console/ui/traces/chain.ts +144 -0
  404. package/src/console/ui/traces/critical-path.test.ts +24 -0
  405. package/src/console/ui/traces/critical-path.ts +59 -0
  406. package/src/console/ui/traces/filter.test.ts +78 -0
  407. package/src/console/ui/traces/filter.ts +112 -0
  408. package/src/console/ui/traces/fixture.ts +126 -0
  409. package/src/console/ui/traces/fold.test.ts +67 -0
  410. package/src/console/ui/traces/fold.ts +170 -0
  411. package/src/console/ui/traces/index.ts +64 -0
  412. package/src/console/ui/traces/mini.ts +65 -0
  413. package/src/console/ui/traces/replay.test.ts +24 -0
  414. package/src/console/ui/traces/replay.ts +35 -0
  415. package/src/console/ui/traces/sampling.test.ts +26 -0
  416. package/src/console/ui/traces/sampling.ts +66 -0
  417. package/src/console/ui/traces/search.ts +148 -0
  418. package/src/console/ui/traces/tier.ts +72 -0
  419. package/src/console/ui/traces/types.ts +125 -0
  420. package/src/console/ui/tsconfig.json +20 -0
  421. package/src/console/ui/vault/VaultA11yView.tsx +177 -0
  422. package/src/console/ui/vault/a11y.test.tsx +97 -0
  423. package/src/console/ui/vault/blast-radius.test.ts +35 -0
  424. package/src/console/ui/vault/blast-radius.ts +55 -0
  425. package/src/console/ui/vault/confirmation.test.ts +41 -0
  426. package/src/console/ui/vault/confirmation.ts +39 -0
  427. package/src/console/ui/vault/dormant.test.ts +37 -0
  428. package/src/console/ui/vault/dormant.ts +28 -0
  429. package/src/console/ui/vault/export-safe.test.ts +30 -0
  430. package/src/console/ui/vault/export-safe.ts +65 -0
  431. package/src/console/ui/vault/fixture.ts +75 -0
  432. package/src/console/ui/vault/group.test.ts +25 -0
  433. package/src/console/ui/vault/group.ts +50 -0
  434. package/src/console/ui/vault/index.ts +45 -0
  435. package/src/console/ui/vault/search.ts +62 -0
  436. package/src/console/ui/vault/types.ts +57 -0
  437. package/src/console/ui/vite.config.ts +84 -0
  438. package/src/console/xss.gate.test.ts +118 -0
  439. package/src/docker/compose.ts +226 -0
  440. package/src/docker/credentials.ts +25 -0
  441. package/src/docker/derive.ts +83 -0
  442. package/src/docker/docker.test.ts +185 -0
  443. package/src/docker/dockerfile.integration.test.ts +170 -0
  444. package/src/docker/dockerfile.ts +39 -0
  445. package/src/docker/helpers.ts +103 -0
  446. package/src/docker/index.ts +52 -0
  447. package/src/docker/pin.ts +90 -0
  448. package/src/docker/recipes/index.ts +33 -0
  449. package/src/docker/recipes/postgres.ts +18 -0
  450. package/src/docker/recipes/redis.ts +18 -0
  451. package/src/docker/stack.integration.test.ts +140 -0
  452. package/src/docker/stack.ts +62 -0
  453. package/src/docker/types.ts +134 -0
  454. package/src/drivers/ai-anthropic.ts +128 -0
  455. package/src/drivers/ai-mock.ts +82 -0
  456. package/src/drivers/ai-openai-compatible.ts +139 -0
  457. package/src/drivers/ai-providers.test.ts +163 -0
  458. package/src/drivers/ai-types.ts +83 -0
  459. package/src/drivers/bun-native-completeness.test.ts +155 -0
  460. package/src/drivers/channel-console.ts +118 -0
  461. package/src/drivers/channel-fcm.ts +96 -0
  462. package/src/drivers/channel-resend.ts +27 -0
  463. package/src/drivers/channel-smtp.ts +33 -0
  464. package/src/drivers/channel-types.ts +160 -0
  465. package/src/drivers/channel-unifonic.ts +79 -0
  466. package/src/drivers/channel-wa-cloud.ts +84 -0
  467. package/src/drivers/channel-webpush.ts +317 -0
  468. package/src/drivers/conformance.test.ts +89 -0
  469. package/src/drivers/conformance.ts +162 -0
  470. package/src/drivers/fs.ts +73 -0
  471. package/src/drivers/index.ts +194 -0
  472. package/src/drivers/kv-lua.ts +222 -0
  473. package/src/drivers/memory.ts +472 -0
  474. package/src/drivers/pgvector.ts +130 -0
  475. package/src/drivers/postgres.ts +221 -0
  476. package/src/drivers/redis.ts +254 -0
  477. package/src/drivers/s3.ts +129 -0
  478. package/src/drivers/signal-engine.ts +690 -0
  479. package/src/drivers/signal-memory.ts +27 -0
  480. package/src/drivers/signal-nats.ts +131 -0
  481. package/src/drivers/signal-postgres.ts +1089 -0
  482. package/src/drivers/signal-redis.ts +275 -0
  483. package/src/drivers/signal-types.ts +328 -0
  484. package/src/drivers/sqlite.ts +53 -0
  485. package/src/drivers/types.ts +334 -0
  486. package/src/drivers/vault-dotenv-parse.ts +56 -0
  487. package/src/drivers/vault-env.ts +101 -0
  488. package/src/drivers/vault-infisical.ts +61 -0
  489. package/src/drivers/vault-managed.ts +42 -0
  490. package/src/drivers/vault-memory.ts +38 -0
  491. package/src/drivers/vault-openbao.ts +80 -0
  492. package/src/drivers/vault-sops.ts +252 -0
  493. package/src/drivers/vault-types.ts +84 -0
  494. package/src/elements/ai/declare.ts +206 -0
  495. package/src/elements/ai/eval.ts +113 -0
  496. package/src/elements/ai/pii.ts +108 -0
  497. package/src/elements/ai/runtime.ts +540 -0
  498. package/src/elements/ai/schema.ts +194 -0
  499. package/src/elements/ai.test.ts +393 -0
  500. package/src/elements/ai.ts +56 -0
  501. package/src/elements/channel/consent.ts +81 -0
  502. package/src/elements/channel/costs.test.ts +62 -0
  503. package/src/elements/channel/costs.ts +130 -0
  504. package/src/elements/channel/declare.ts +141 -0
  505. package/src/elements/channel/email-auth.test.ts +47 -0
  506. package/src/elements/channel/email-auth.ts +109 -0
  507. package/src/elements/channel/locale.ts +97 -0
  508. package/src/elements/channel/mask.test.ts +19 -0
  509. package/src/elements/channel/mask.ts +60 -0
  510. package/src/elements/channel/mime.ts +23 -0
  511. package/src/elements/channel/outcomes.test.ts +40 -0
  512. package/src/elements/channel/outcomes.ts +126 -0
  513. package/src/elements/channel/receipts.ts +121 -0
  514. package/src/elements/channel/runtime.ts +500 -0
  515. package/src/elements/channel/suppression.ts +136 -0
  516. package/src/elements/channel.test.ts +232 -0
  517. package/src/elements/channel.ts +109 -0
  518. package/src/elements/clock/actions.ts +170 -0
  519. package/src/elements/clock/declare.ts +58 -0
  520. package/src/elements/clock/dst.ts +197 -0
  521. package/src/elements/clock/durable.ts +140 -0
  522. package/src/elements/clock/duration.ts +29 -0
  523. package/src/elements/clock/health.test.ts +103 -0
  524. package/src/elements/clock/health.ts +112 -0
  525. package/src/elements/clock/leader.ts +127 -0
  526. package/src/elements/clock/reconcile.ts +241 -0
  527. package/src/elements/clock/runtime.ts +243 -0
  528. package/src/elements/clock/schedule.ts +262 -0
  529. package/src/elements/clock/time-travel.ts +53 -0
  530. package/src/elements/clock.test.ts +365 -0
  531. package/src/elements/clock.ts +80 -0
  532. package/src/elements/gate/declare.ts +134 -0
  533. package/src/elements/gate/permissions.ts +104 -0
  534. package/src/elements/gate/runtime.ts +177 -0
  535. package/src/elements/gate/strategies.ts +388 -0
  536. package/src/elements/gate.test.ts +145 -0
  537. package/src/elements/gate.ts +41 -0
  538. package/src/elements/index.ts +169 -0
  539. package/src/elements/signal/chaos-child.ts +47 -0
  540. package/src/elements/signal/declare.ts +77 -0
  541. package/src/elements/signal/dry-run-replay.test.ts +95 -0
  542. package/src/elements/signal/dry-run-write-isolation.test.ts +94 -0
  543. package/src/elements/signal/reconcile.test.ts +23 -0
  544. package/src/elements/signal/reconcile.ts +122 -0
  545. package/src/elements/signal/runtime.ts +94 -0
  546. package/src/elements/signal.test.ts +457 -0
  547. package/src/elements/signal.ts +26 -0
  548. package/src/elements/store/cache.ts +197 -0
  549. package/src/elements/store/classify.ts +125 -0
  550. package/src/elements/store/declare.ts +200 -0
  551. package/src/elements/store/files-policy.test.ts +31 -0
  552. package/src/elements/store/files-policy.ts +70 -0
  553. package/src/elements/store/replica.ts +68 -0
  554. package/src/elements/store/runtime.ts +393 -0
  555. package/src/elements/store/sql-condition.ts +205 -0
  556. package/src/elements/store/sql-session.ts +579 -0
  557. package/src/elements/store/table.ts +282 -0
  558. package/src/elements/store.test.ts +370 -0
  559. package/src/elements/store.ts +99 -0
  560. package/src/elements/vault/declare.ts +143 -0
  561. package/src/elements/vault/fingerprint.ts +30 -0
  562. package/src/elements/vault/redact.ts +52 -0
  563. package/src/elements/vault/runtime.ts +461 -0
  564. package/src/elements/vault.test.ts +296 -0
  565. package/src/elements/vault.ts +44 -0
  566. package/src/index.ts +183 -0
  567. package/src/kernel/adopt-routes.ts +194 -0
  568. package/src/kernel/app.ts +1068 -0
  569. package/src/kernel/auth-resolve.ts +93 -0
  570. package/src/kernel/boot.test.ts +173 -0
  571. package/src/kernel/boot.ts +439 -0
  572. package/src/kernel/budget-entry.ts +55 -0
  573. package/src/kernel/budget.test.ts +19 -0
  574. package/src/kernel/call.test.ts +83 -0
  575. package/src/kernel/capability.ts +113 -0
  576. package/src/kernel/dry-run.test.ts +64 -0
  577. package/src/kernel/dry-run.ts +171 -0
  578. package/src/kernel/effects.test.ts +89 -0
  579. package/src/kernel/effects.ts +140 -0
  580. package/src/kernel/errors.registry.test.ts +39 -0
  581. package/src/kernel/errors.ts +225 -0
  582. package/src/kernel/flow.test.ts +154 -0
  583. package/src/kernel/flow.ts +290 -0
  584. package/src/kernel/fx.test.ts +245 -0
  585. package/src/kernel/fx.ts +996 -0
  586. package/src/kernel/hook-timing.test.ts +72 -0
  587. package/src/kernel/hook-timing.ts +190 -0
  588. package/src/kernel/hooks.test.ts +181 -0
  589. package/src/kernel/hooks.ts +275 -0
  590. package/src/kernel/index.ts +278 -0
  591. package/src/kernel/journal.ts +405 -0
  592. package/src/kernel/journey.ts +75 -0
  593. package/src/kernel/on.ts +74 -0
  594. package/src/kernel/pipeline.test.ts +349 -0
  595. package/src/kernel/pipeline.ts +245 -0
  596. package/src/kernel/plug.ts +82 -0
  597. package/src/kernel/plugin/capabilities.test.ts +84 -0
  598. package/src/kernel/plugin/conflicts.test.ts +106 -0
  599. package/src/kernel/plugin/decorate.test.ts +111 -0
  600. package/src/kernel/plugin/scoping.test.ts +138 -0
  601. package/src/kernel/plugin.ts +485 -0
  602. package/src/kernel/rate-limit.ts +25 -0
  603. package/src/kernel/registry.ts +398 -0
  604. package/src/kernel/router.test.ts +114 -0
  605. package/src/kernel/router.ts +556 -0
  606. package/src/kernel/routing-budget.test.ts +19 -0
  607. package/src/kernel/run-telemetry.ts +70 -0
  608. package/src/kernel/triggers.ts +324 -0
  609. package/src/kernel/unit.ts +88 -0
  610. package/src/manifest/diff.test.ts +866 -0
  611. package/src/manifest/diff.ts +1670 -0
  612. package/src/manifest/fixtures/base.manifest.json +112 -0
  613. package/src/manifest/fixtures/skyport.excerpt.json +51 -0
  614. package/src/manifest/fixtures/skyport.manifest.json +153 -0
  615. package/src/manifest/index.ts +27 -0
  616. package/src/manifest/types.ts +358 -0
  617. package/src/manifest/undeclared.test.ts +82 -0
  618. package/src/manifest/undeclared.ts +65 -0
  619. package/src/manifest/validate.test.ts +105 -0
  620. package/src/manifest/validate.ts +174 -0
  621. package/src/mcp/authorization.ts +340 -0
  622. package/src/mcp/confirmation.ts +174 -0
  623. package/src/mcp/data.ts +90 -0
  624. package/src/mcp/index.ts +80 -0
  625. package/src/mcp/injection.gate.test.ts +176 -0
  626. package/src/mcp/mcp.test.ts +348 -0
  627. package/src/mcp/protocol.ts +172 -0
  628. package/src/mcp/server.ts +283 -0
  629. package/src/mcp/session.ts +139 -0
  630. package/src/mcp/tools.ts +391 -0
  631. package/src/plugins/catalogue.test.ts +48 -0
  632. package/src/plugins/catalogue.ts +113 -0
  633. package/src/plugins/node-import-scan.test.ts +28 -0
  634. package/src/plugins/node-import-scan.ts +98 -0
  635. package/src/plugins/supply-chain.test.ts +48 -0
  636. package/src/plugins/supply-chain.ts +460 -0
  637. package/src/release/index.ts +30 -0
  638. package/src/release/limits.ts +20 -0
  639. package/src/release/measure.ts +443 -0
  640. package/src/release/publish.ts +56 -0
  641. package/src/runs/bench.test.ts +93 -0
  642. package/src/runs/collect.ts +144 -0
  643. package/src/runs/drivers/clickhouse.ts +108 -0
  644. package/src/runs/drivers/files.ts +201 -0
  645. package/src/runs/drivers/memory.ts +94 -0
  646. package/src/runs/drivers/postgres.ts +110 -0
  647. package/src/runs/duckdb.ts +99 -0
  648. package/src/runs/index.ts +82 -0
  649. package/src/runs/outlier.ts +180 -0
  650. package/src/runs/parquet.ts +210 -0
  651. package/src/runs/privacy.ts +49 -0
  652. package/src/runs/runs.test.ts +324 -0
  653. package/src/runs/runtime.ts +229 -0
  654. package/src/runs/shred.ts +243 -0
  655. package/src/runs/telemetry.ts +10 -0
  656. package/src/runs/types.ts +179 -0
  657. package/src/runtime/bun.ts +140 -0
  658. package/src/runtime/cold-start.bench.ts +20 -0
  659. package/src/runtime/index.ts +46 -0
  660. package/src/runtime/primitives.ts +242 -0
  661. package/src/runtime/security.test.ts +170 -0
  662. package/src/runtime/security.ts +168 -0
  663. package/src/runtime/serve.test.ts +223 -0
  664. package/src/runtime/types.ts +217 -0
  665. package/src/runtime/web-standard.ts +77 -0
  666. package/src/test/create-test-app.test.ts +161 -0
  667. package/src/test/create-test-app.ts +533 -0
  668. package/src/test/index.ts +21 -0
  669. package/src/test/provisions.integration.test.ts +174 -0
  670. package/src/upgrade/codemods.test.ts +58 -0
  671. package/src/upgrade/codemods.ts +83 -0
  672. package/src/validation/index.ts +23 -0
  673. package/src/validation/standard-schema.test.ts +96 -0
  674. package/src/validation/standard-schema.ts +316 -0
@@ -0,0 +1,549 @@
1
+ /**
2
+ * Causality graph derived from the Manifest (console §9.1).
3
+ *
4
+ * Bidirectional: cause → flows → effects, or effect → flows → causes.
5
+ * Relations are compiler-derived from `fx` and cannot rot.
6
+ */
7
+
8
+ import type { Effects, Flow, Manifest, Trigger } from "../../../manifest/types.ts";
9
+ import {
10
+ hasExternalEffect,
11
+ peakEffectTier,
12
+ tierEffects,
13
+ type TieredEffect,
14
+ type UiEffectTier,
15
+ } from "./tiers.ts";
16
+
17
+ /** A cause shown in the left column. */
18
+ export interface CauseNode {
19
+ /** Stable id (`http:POST:/bookings`, `signal:order-placed`, `caller:payments.chargeBooking`). */
20
+ readonly id: string;
21
+ /** Cause kind. */
22
+ readonly kind: "http" | "signal" | "cron" | "every" | "cdc" | "caller";
23
+ /** Human label. */
24
+ readonly label: string;
25
+ /** Flow ids this cause triggers (or calls, for callers). */
26
+ readonly flowIds: readonly string[];
27
+ }
28
+
29
+ /** Centre-column flow row. */
30
+ export interface FlowNode {
31
+ /** Flow id (`bookings.create`). */
32
+ readonly id: string;
33
+ /** Unit prefix (`bookings`). */
34
+ readonly unit: string;
35
+ /** Action suffix (`create`). */
36
+ readonly action: string;
37
+ /** Plane. */
38
+ readonly plane: "user" | "operator";
39
+ /** Cause ids that trigger / call this flow. */
40
+ readonly causeIds: readonly string[];
41
+ /** Effect refs this flow touches. */
42
+ readonly effectRefs: readonly string[];
43
+ /** Ranked effect rows. */
44
+ readonly effects: readonly TieredEffect[];
45
+ /** Peak tier for flags / confirmation. */
46
+ readonly peakTier: UiEffectTier | "none";
47
+ /** Has irreversible external effect. */
48
+ readonly external: boolean;
49
+ /** Exception-only flags. */
50
+ readonly flags: {
51
+ readonly durable: boolean;
52
+ readonly live: boolean;
53
+ readonly cached: boolean;
54
+ readonly costsMoney: boolean;
55
+ readonly readsSecret: boolean;
56
+ readonly touchesPii: boolean;
57
+ readonly external: boolean;
58
+ };
59
+ /** Declared input schema (object form when available). */
60
+ readonly inSchema: Record<string, unknown> | null;
61
+ /** Declared output schema. */
62
+ readonly outSchema: Record<string, unknown> | null;
63
+ /** Typed error names. */
64
+ readonly errorNames: readonly string[];
65
+ /** Source deep-link. */
66
+ readonly source: string | undefined;
67
+ /** Deprecation marker. */
68
+ readonly deprecated: boolean;
69
+ /** Raw Manifest flow. */
70
+ readonly raw: Flow;
71
+ }
72
+
73
+ /** An effect / resource in the right column (or idle inventory). */
74
+ export interface EffectNode {
75
+ /** Resource ref (`sql:bookings`, `signal:order-placed`, `channel:booking-confirmed`). */
76
+ readonly ref: string;
77
+ /** Display tier. */
78
+ readonly tier: UiEffectTier;
79
+ /** Flow ids that touch this resource. */
80
+ readonly flowIds: readonly string[];
81
+ /** Touch count (= flowIds.length). */
82
+ readonly touchCount: number;
83
+ /** Fan-out for signals. */
84
+ readonly fanOut: number;
85
+ }
86
+
87
+ /** Full causality index for one Manifest. */
88
+ export interface CausalityGraph {
89
+ readonly causes: readonly CauseNode[];
90
+ readonly flows: readonly FlowNode[];
91
+ readonly effects: readonly EffectNode[];
92
+ readonly causeById: ReadonlyMap<string, CauseNode>;
93
+ readonly flowById: ReadonlyMap<string, FlowNode>;
94
+ readonly effectByRef: ReadonlyMap<string, EffectNode>;
95
+ }
96
+
97
+ /**
98
+ * Unit of a flow id (`bookings.create` → `bookings`).
99
+ *
100
+ * @param flowId - Flow id
101
+ */
102
+ export function unitOf(flowId: string): string {
103
+ const i = flowId.indexOf(".");
104
+ return i === -1 ? flowId : flowId.slice(0, i);
105
+ }
106
+
107
+ /**
108
+ * Action of a flow id (`bookings.create` → `create`).
109
+ *
110
+ * @param flowId - Flow id
111
+ */
112
+ export function actionOf(flowId: string): string {
113
+ const i = flowId.indexOf(".");
114
+ return i === -1 ? flowId : flowId.slice(i + 1);
115
+ }
116
+
117
+ /**
118
+ * Stable cause id from a trigger or caller.
119
+ *
120
+ * @param trigger - Flow trigger
121
+ * @param flowId - Owning flow (for caller fallback)
122
+ * @param callers - Flows that call this one
123
+ */
124
+ export function causeIdsFor(
125
+ trigger: Trigger | undefined,
126
+ flowId: string,
127
+ callers: readonly string[],
128
+ ): CauseNode[] {
129
+ const nodes: CauseNode[] = [];
130
+ if (trigger?.http) {
131
+ const id = `http:${trigger.http.method}:${trigger.http.path}`;
132
+ nodes.push({
133
+ id,
134
+ kind: "http",
135
+ label: `${trigger.http.method} ${trigger.http.path}`,
136
+ flowIds: [flowId],
137
+ });
138
+ }
139
+ if (trigger?.signal) {
140
+ nodes.push({
141
+ id: `signal:${trigger.signal}`,
142
+ kind: "signal",
143
+ label: trigger.signal,
144
+ flowIds: [flowId],
145
+ });
146
+ }
147
+ if (trigger?.cron) {
148
+ nodes.push({
149
+ id: `cron:${trigger.cron}`,
150
+ kind: "cron",
151
+ label: trigger.cron,
152
+ flowIds: [flowId],
153
+ });
154
+ }
155
+ if (trigger?.every) {
156
+ nodes.push({
157
+ id: `every:${trigger.every}`,
158
+ kind: "every",
159
+ label: `every ${trigger.every}`,
160
+ flowIds: [flowId],
161
+ });
162
+ }
163
+ if (trigger?.cdc) {
164
+ const col = trigger.cdc.column ? `.${trigger.cdc.column}` : "";
165
+ const id = `cdc:${trigger.cdc.table}${col}`;
166
+ nodes.push({
167
+ id,
168
+ kind: "cdc",
169
+ label: `cdc ${trigger.cdc.table}${col}`,
170
+ flowIds: [flowId],
171
+ });
172
+ }
173
+ if (nodes.length === 0) {
174
+ for (const caller of callers) {
175
+ nodes.push({
176
+ id: `caller:${caller}`,
177
+ kind: "caller",
178
+ label: caller,
179
+ flowIds: [flowId],
180
+ });
181
+ }
182
+ }
183
+ return nodes;
184
+ }
185
+
186
+ /**
187
+ * Flatten effect refs with kind prefixes for inventory keys.
188
+ *
189
+ * @param effects - Flow effects
190
+ */
191
+ export function effectRefsOf(effects: Effects | undefined): string[] {
192
+ if (!effects) return [];
193
+ const refs: string[] = [];
194
+ for (const r of effects.reads ?? []) refs.push(r);
195
+ for (const r of effects.writes ?? []) refs.push(r);
196
+ for (const r of effects.emits ?? []) refs.push(`signal:${r}`);
197
+ for (const r of effects.sends ?? []) refs.push(`channel:${r}`);
198
+ for (const r of effects.asks ?? []) refs.push(`ai:${r}`);
199
+ for (const r of effects.secrets ?? []) refs.push(`secret:${r}`);
200
+ for (const r of effects.calls ?? []) refs.push(`flow:${r}`);
201
+ return refs;
202
+ }
203
+
204
+ function schemaObject(
205
+ schema: string | Record<string, unknown> | undefined,
206
+ ): Record<string, unknown> | null {
207
+ if (!schema || typeof schema === "string") return null;
208
+ return schema;
209
+ }
210
+
211
+ function errorNamesOf(flow: Flow): string[] {
212
+ if (!flow.errors) return [];
213
+ if (Array.isArray(flow.errors)) return [...flow.errors];
214
+ return Object.keys(flow.errors);
215
+ }
216
+
217
+ /**
218
+ * Build the causality graph from a Manifest snapshot.
219
+ *
220
+ * @param manifest - Manifest (or null → empty graph)
221
+ */
222
+ export function buildCausalityGraph(
223
+ manifest: Manifest | null | undefined,
224
+ ): CausalityGraph {
225
+ const flowsMap = manifest?.flows ?? {};
226
+ const flowIds = Object.keys(flowsMap).sort();
227
+
228
+ // Reverse index: callee → callers
229
+ const callersOf = new Map<string, string[]>();
230
+ for (const id of flowIds) {
231
+ const calls = flowsMap[id]?.effects?.calls ?? [];
232
+ for (const callee of calls) {
233
+ const list = callersOf.get(callee) ?? [];
234
+ list.push(id);
235
+ callersOf.set(callee, list);
236
+ }
237
+ }
238
+
239
+ // Signal consumers (fan-out)
240
+ const signalConsumers = new Map<string, string[]>();
241
+ for (const id of flowIds) {
242
+ const sig = flowsMap[id]?.trigger?.signal;
243
+ if (!sig) continue;
244
+ const list = signalConsumers.get(sig) ?? [];
245
+ list.push(id);
246
+ signalConsumers.set(sig, list);
247
+ }
248
+
249
+ const causeMerge = new Map<string, CauseNode>();
250
+ const effectMerge = new Map<
251
+ string,
252
+ { tier: UiEffectTier; flowIds: string[]; fanOut: number }
253
+ >();
254
+ const flowNodes: FlowNode[] = [];
255
+
256
+ for (const id of flowIds) {
257
+ const raw = flowsMap[id];
258
+ if (!raw) continue;
259
+ const callers = callersOf.get(id) ?? [];
260
+ const causes = causeIdsFor(raw.trigger, id, callers);
261
+ for (const c of causes) {
262
+ const existing = causeMerge.get(c.id);
263
+ if (existing) {
264
+ causeMerge.set(c.id, {
265
+ ...existing,
266
+ flowIds: [...new Set([...existing.flowIds, id])],
267
+ });
268
+ } else {
269
+ causeMerge.set(c.id, c);
270
+ }
271
+ }
272
+
273
+ const touchCounts = new Map<string, number>();
274
+ const emitFanOut = new Map<string, number>();
275
+ for (const sig of raw.effects?.emits ?? []) {
276
+ emitFanOut.set(sig, signalConsumers.get(sig)?.length ?? 0);
277
+ }
278
+
279
+ const tiered = tierEffects(raw.effects, { touchCounts, emitFanOut });
280
+ const refs = effectRefsOf(raw.effects);
281
+
282
+ for (const row of tiered) {
283
+ const key =
284
+ row.kind === "emit"
285
+ ? `signal:${row.ref}`
286
+ : row.kind === "send"
287
+ ? `channel:${row.ref}`
288
+ : row.kind === "ask"
289
+ ? `ai:${row.ref}`
290
+ : row.kind === "secret"
291
+ ? `secret:${row.ref}`
292
+ : row.kind === "call"
293
+ ? `flow:${row.ref}`
294
+ : row.ref;
295
+ const existing = effectMerge.get(key);
296
+ if (existing) {
297
+ existing.flowIds.push(id);
298
+ existing.fanOut = Math.max(existing.fanOut, row.fanOut ?? 0);
299
+ } else {
300
+ effectMerge.set(key, {
301
+ tier: row.tier,
302
+ flowIds: [id],
303
+ fanOut: row.fanOut ?? 0,
304
+ });
305
+ }
306
+ }
307
+
308
+ // Also index store tables declared but maybe only read via classification
309
+ flowNodes.push({
310
+ id,
311
+ unit: unitOf(id),
312
+ action: actionOf(id),
313
+ plane: raw.plane ?? "user",
314
+ causeIds: causes.map((c) => c.id),
315
+ effectRefs: refs,
316
+ effects: tiered,
317
+ peakTier: peakEffectTier(raw.effects),
318
+ external: hasExternalEffect(raw.effects),
319
+ flags: {
320
+ durable: raw.durable === true,
321
+ live: raw.live === true,
322
+ cached: raw.cache !== undefined && raw.cache !== false,
323
+ costsMoney: (raw.cost?.estimatePerCall ?? 0) > 0,
324
+ readsSecret: (raw.effects?.secrets?.length ?? 0) > 0,
325
+ touchesPii: raw.pii !== undefined || raw.allowPii === true,
326
+ external: hasExternalEffect(raw.effects),
327
+ },
328
+ inSchema: schemaObject(raw.in),
329
+ outSchema: schemaObject(raw.out),
330
+ errorNames: errorNamesOf(raw),
331
+ source: raw.source,
332
+ deprecated: Boolean(raw.deprecated),
333
+ raw,
334
+ });
335
+ }
336
+
337
+ // Idle inventory: also include declared stores / signals / channels / vault / ai
338
+ if (manifest?.stores) {
339
+ for (const store of Object.values(manifest.stores)) {
340
+ if (store.facet === "sql" && store.tables) {
341
+ for (const table of Object.keys(store.tables)) {
342
+ const ref = `sql:${table}`;
343
+ if (!effectMerge.has(ref)) {
344
+ effectMerge.set(ref, { tier: "reads", flowIds: [], fanOut: 0 });
345
+ }
346
+ }
347
+ }
348
+ }
349
+ }
350
+ if (manifest?.signals) {
351
+ for (const name of Object.keys(manifest.signals)) {
352
+ const ref = `signal:${name}`;
353
+ if (!effectMerge.has(ref)) {
354
+ effectMerge.set(ref, { tier: "emits", flowIds: [], fanOut: 0 });
355
+ }
356
+ }
357
+ }
358
+ if (manifest?.channels) {
359
+ for (const name of Object.keys(manifest.channels)) {
360
+ const ref = `channel:${name}`;
361
+ if (!effectMerge.has(ref)) {
362
+ effectMerge.set(ref, { tier: "external", flowIds: [], fanOut: 0 });
363
+ }
364
+ }
365
+ }
366
+ if (manifest?.vault) {
367
+ for (const name of Object.keys(manifest.vault)) {
368
+ const ref = `secret:${name}`;
369
+ if (!effectMerge.has(ref)) {
370
+ effectMerge.set(ref, {
371
+ tier: "capabilities",
372
+ flowIds: [],
373
+ fanOut: 0,
374
+ });
375
+ }
376
+ }
377
+ }
378
+
379
+ const causes = [...causeMerge.values()].sort((a, b) =>
380
+ a.label.localeCompare(b.label),
381
+ );
382
+ const effects: EffectNode[] = [...effectMerge.entries()]
383
+ .map(([ref, v]) => ({
384
+ ref,
385
+ tier: v.tier,
386
+ flowIds: [...new Set(v.flowIds)].sort(),
387
+ touchCount: new Set(v.flowIds).size,
388
+ fanOut: v.fanOut,
389
+ }))
390
+ .sort((a, b) => b.touchCount - a.touchCount || a.ref.localeCompare(b.ref));
391
+
392
+ const causeById = new Map(causes.map((c) => [c.id, c]));
393
+ const flowById = new Map(flowNodes.map((f) => [f.id, f]));
394
+ const effectByRef = new Map(effects.map((e) => [e.ref, e]));
395
+
396
+ return {
397
+ causes,
398
+ flows: flowNodes,
399
+ effects,
400
+ causeById,
401
+ flowById,
402
+ effectByRef,
403
+ };
404
+ }
405
+
406
+ /**
407
+ * Flows visible in the centre column given the current selection.
408
+ * Dim-never-hide: returns all flows with a `match` flag.
409
+ *
410
+ * @param graph - Causality graph
411
+ * @param selection - Selection kind + ids
412
+ * @param query - Free-text filter
413
+ */
414
+ export function centreFlows(
415
+ graph: CausalityGraph,
416
+ selection: {
417
+ readonly sel: "none" | "cause" | "flow" | "effect";
418
+ readonly cause?: string;
419
+ readonly flow?: string;
420
+ readonly effect?: string;
421
+ readonly q?: string;
422
+ readonly unit?: string;
423
+ },
424
+ ): Array<FlowNode & { readonly match: boolean; readonly related: boolean }> {
425
+ let relatedIds: Set<string> | null = null;
426
+
427
+ if (selection.sel === "cause" && selection.cause) {
428
+ const cause = graph.causeById.get(selection.cause);
429
+ relatedIds = new Set(cause?.flowIds ?? []);
430
+ } else if (selection.sel === "effect" && selection.effect) {
431
+ const effect = graph.effectByRef.get(selection.effect);
432
+ relatedIds = new Set(effect?.flowIds ?? []);
433
+ } else if (selection.sel === "flow" && selection.flow) {
434
+ relatedIds = new Set([selection.flow]);
435
+ }
436
+
437
+ return graph.flows.map((f) => {
438
+ const related = relatedIds === null ? true : relatedIds.has(f.id);
439
+ const textMatch = matchesFlowQuery(f, selection.q);
440
+ const unitMatch = !selection.unit || f.unit === selection.unit;
441
+ const match = related && textMatch && unitMatch;
442
+ return { ...f, match, related };
443
+ });
444
+ }
445
+
446
+ /**
447
+ * Causes for the left column given selection.
448
+ *
449
+ * @param graph - Graph
450
+ * @param selection - Selection
451
+ * @param query - Filter
452
+ */
453
+ export function leftCauses(
454
+ graph: CausalityGraph,
455
+ selection: {
456
+ readonly sel: "none" | "cause" | "flow" | "effect";
457
+ readonly flow?: string;
458
+ readonly effect?: string;
459
+ readonly q?: string;
460
+ },
461
+ ): Array<CauseNode & { readonly match: boolean; readonly related: boolean }> {
462
+ let relatedIds: Set<string> | null = null;
463
+
464
+ if (selection.sel === "flow" && selection.flow) {
465
+ const flow = graph.flowById.get(selection.flow);
466
+ relatedIds = new Set(flow?.causeIds ?? []);
467
+ } else if (selection.sel === "effect" && selection.effect) {
468
+ const effect = graph.effectByRef.get(selection.effect);
469
+ const causeIds = new Set<string>();
470
+ for (const fid of effect?.flowIds ?? []) {
471
+ const flow = graph.flowById.get(fid);
472
+ for (const c of flow?.causeIds ?? []) causeIds.add(c);
473
+ }
474
+ relatedIds = causeIds;
475
+ }
476
+
477
+ return graph.causes.map((c) => {
478
+ const related = relatedIds === null ? true : relatedIds.has(c.id);
479
+ const textMatch =
480
+ !selection.q ||
481
+ c.label.toLowerCase().includes(selection.q.toLowerCase()) ||
482
+ c.id.toLowerCase().includes(selection.q.toLowerCase());
483
+ return { ...c, match: related && textMatch, related };
484
+ });
485
+ }
486
+
487
+ /**
488
+ * Effects for the right column given selection.
489
+ *
490
+ * @param graph - Graph
491
+ * @param selection - Selection
492
+ * @param query - Filter
493
+ * @param hideUbiquitous - Filter high-touch resources from prominence
494
+ * @param ubiquitousThreshold - Touch-count threshold
495
+ */
496
+ export function rightEffects(
497
+ graph: CausalityGraph,
498
+ selection: {
499
+ readonly sel: "none" | "cause" | "flow" | "effect";
500
+ readonly cause?: string;
501
+ readonly flow?: string;
502
+ readonly q?: string;
503
+ },
504
+ options: {
505
+ readonly hideUbiquitous?: boolean;
506
+ readonly ubiquitousThreshold?: number;
507
+ } = {},
508
+ ): Array<EffectNode & { readonly match: boolean; readonly related: boolean }> {
509
+ let relatedIds: Set<string> | null = null;
510
+
511
+ if (selection.sel === "flow" && selection.flow) {
512
+ const flow = graph.flowById.get(selection.flow);
513
+ relatedIds = new Set(flow?.effectRefs ?? []);
514
+ } else if (selection.sel === "cause" && selection.cause) {
515
+ const cause = graph.causeById.get(selection.cause);
516
+ const refs = new Set<string>();
517
+ for (const fid of cause?.flowIds ?? []) {
518
+ const flow = graph.flowById.get(fid);
519
+ for (const r of flow?.effectRefs ?? []) refs.add(r);
520
+ }
521
+ relatedIds = refs;
522
+ }
523
+
524
+ const threshold = options.ubiquitousThreshold ?? 8;
525
+
526
+ return graph.effects.map((e) => {
527
+ const related = relatedIds === null ? true : relatedIds.has(e.ref);
528
+ const textMatch =
529
+ !selection.q ||
530
+ e.ref.toLowerCase().includes(selection.q.toLowerCase());
531
+ const ubiquityOk =
532
+ !options.hideUbiquitous || e.touchCount < threshold || relatedIds !== null;
533
+ return {
534
+ ...e,
535
+ match: related && textMatch && ubiquityOk,
536
+ related,
537
+ };
538
+ });
539
+ }
540
+
541
+ function matchesFlowQuery(flow: FlowNode, q: string | undefined): boolean {
542
+ if (!q?.trim()) return true;
543
+ const needle = q.toLowerCase();
544
+ return (
545
+ flow.id.toLowerCase().includes(needle) ||
546
+ flow.unit.toLowerCase().includes(needle) ||
547
+ flow.action.toLowerCase().includes(needle)
548
+ );
549
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Flows panel — causality view logic (console §9.1 · §9.2).
3
+ *
4
+ * Pure modules live here so `bun test src/console/ui/flows` gates behaviour
5
+ * without mounting the full SPA.
6
+ */
7
+
8
+ export {
9
+ createRowBuffer,
10
+ matchesQuery,
11
+ type BufferedRow,
12
+ type RowBuffer,
13
+ } from "./buffer.ts";
14
+ export {
15
+ confirmationFor,
16
+ createUndoStack,
17
+ UNDO_WINDOW_MS,
18
+ validateTypedConfirm,
19
+ type ConfirmationPattern,
20
+ type TypedConfirmErrors,
21
+ type TypedConfirmInput,
22
+ type UndoEntry,
23
+ } from "./confirmation.ts";
24
+ export {
25
+ diffAgainstSchema,
26
+ fieldsFromSchema,
27
+ getAtPath,
28
+ parseJsonEditor,
29
+ seedFromSchema,
30
+ setAtPath,
31
+ validateContract,
32
+ valueToJsonText,
33
+ type ContractValidation,
34
+ type FieldError,
35
+ type FormField,
36
+ } from "./contract.ts";
37
+ export {
38
+ actionOf,
39
+ buildCausalityGraph,
40
+ causeIdsFor,
41
+ centreFlows,
42
+ effectRefsOf,
43
+ leftCauses,
44
+ rightEffects,
45
+ unitOf,
46
+ type CauseNode,
47
+ type CausalityGraph,
48
+ type EffectNode,
49
+ type FlowNode,
50
+ } from "./graph.ts";
51
+ export {
52
+ emitSaveAsTest,
53
+ saveAsTestPath,
54
+ writeSaveAsTest,
55
+ type SaveAsTestInput,
56
+ } from "./save-as-test.ts";
57
+ export {
58
+ closeDrawer,
59
+ FlowsSearchSchema,
60
+ joinPath,
61
+ openDrawer,
62
+ parseFlowsSearch,
63
+ parsePath,
64
+ selectCause,
65
+ selectEffect,
66
+ selectFlow,
67
+ serializeFlowsSearch,
68
+ type AttentionFilter,
69
+ type CauseGrouping,
70
+ type CauseKind,
71
+ type Density,
72
+ type DrawerMode,
73
+ type EffectKindKey,
74
+ type FlowGrouping,
75
+ type FlowsSearch,
76
+ type FlowsSelectionKind,
77
+ } from "./search.ts";
78
+ export {
79
+ EXTERNAL_ACCENT_VAR,
80
+ hasExternalEffect,
81
+ peakEffectTier,
82
+ TIER_LABEL,
83
+ TIER_ORDER,
84
+ tierEffects,
85
+ type TieredEffect,
86
+ type UiEffectTier,
87
+ } from "./tiers.ts";
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Save-as-test emits a passing bun test file (console §9.2).
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { mkdtemp, rm } from "node:fs/promises";
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ import { emitSaveAsTest, writeSaveAsTest } from "./save-as-test.ts";
10
+
11
+ describe("save-as-test", () => {
12
+ test("emits a bun test source with request/response assertions", () => {
13
+ const src = emitSaveAsTest({
14
+ flowId: "bookings.create",
15
+ request: { flightId: "SK1", seats: 2 },
16
+ response: { id: "b_1" },
17
+ asUserId: "user_1",
18
+ });
19
+ expect(src).toContain('from "bun:test"');
20
+ expect(src).toContain("bookings.create");
21
+ expect(src).toContain('"flightId": "SK1"');
22
+ expect(src).toContain('"id": "b_1"');
23
+ expect(src).toContain("asUserId");
24
+ });
25
+
26
+ test("written file passes bun test", async () => {
27
+ const dir = await mkdtemp(join(tmpdir(), "oke-save-as-test-"));
28
+ try {
29
+ const { path } = await writeSaveAsTest(dir, {
30
+ flowId: "bookings.create",
31
+ request: { flightId: "SK1", seats: 2 },
32
+ response: { id: "b_1" },
33
+ });
34
+ const proc = Bun.spawnSync(["bun", "test", path], {
35
+ stdout: "pipe",
36
+ stderr: "pipe",
37
+ });
38
+ if (proc.exitCode !== 0) {
39
+ console.error(proc.stdout.toString());
40
+ console.error(proc.stderr.toString());
41
+ }
42
+ expect(proc.exitCode).toBe(0);
43
+ } finally {
44
+ await rm(dir, { recursive: true, force: true });
45
+ }
46
+ });
47
+ });