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,67 @@
1
+ /**
2
+ * Folded-time waterfall tests (console §9.3).
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { TRACES_FIXTURE } from "./fixture.ts";
7
+ import {
8
+ COLLAPSED_FOLD_DISPLAY_MS,
9
+ foldTimeline,
10
+ formatFoldLabel,
11
+ intervalsFromSpans,
12
+ } from "./fold.ts";
13
+
14
+ describe("foldTimeline", () => {
15
+ test("collapses multi-day idle into one labelled fold", () => {
16
+ const chain = TRACES_FIXTURE.filter(
17
+ (s) => s.id === "run-create-ok" || s.id === "run-fulfill",
18
+ );
19
+ const folded = foldTimeline(intervalsFromSpans(chain));
20
+ const folds = folded.segments.filter((s) => s.kind === "fold");
21
+ expect(folds.length).toBe(1);
22
+ const fold = folds[0];
23
+ expect(fold?.kind).toBe("fold");
24
+ if (fold?.kind !== "fold") return;
25
+ expect(fold.durationMs).toBeGreaterThan(6 * 24 * 60 * 60 * 1000);
26
+ expect(fold.label).toContain("d idle");
27
+ expect(fold.displayMs).toBe(COLLAPSED_FOLD_DISPLAY_MS);
28
+ expect(fold.expanded).toBe(false);
29
+ });
30
+
31
+ test("expanded fold restores proportional display weight", () => {
32
+ const chain = TRACES_FIXTURE.filter(
33
+ (s) => s.id === "run-create-ok" || s.id === "run-fulfill",
34
+ );
35
+ const intervals = intervalsFromSpans(chain);
36
+ const draft = foldTimeline(intervals);
37
+ const foldId = draft.segments.find((s) => s.kind === "fold")?.id;
38
+ expect(foldId).toBeDefined();
39
+ const folded = foldTimeline(intervals, {
40
+ expandedFolds: new Set([foldId!]),
41
+ });
42
+ const fold = folded.segments.find((s) => s.kind === "fold");
43
+ expect(fold?.kind).toBe("fold");
44
+ if (fold?.kind !== "fold") return;
45
+ expect(fold.expanded).toBe(true);
46
+ expect(fold.displayMs).toBe(fold.durationMs);
47
+ });
48
+
49
+ test("work stays proportional — display sum excludes collapsed dead time", () => {
50
+ const chain = TRACES_FIXTURE.filter(
51
+ (s) => s.id === "run-create-ok" || s.id === "run-fulfill",
52
+ );
53
+ const folded = foldTimeline(intervalsFromSpans(chain));
54
+ const workDisplay = folded.segments
55
+ .filter((s) => s.kind === "work")
56
+ .reduce((s, seg) => s + seg.displayMs, 0);
57
+ expect(folded.displayDurationMs).toBe(
58
+ workDisplay + COLLAPSED_FOLD_DISPLAY_MS,
59
+ );
60
+ expect(folded.wallDurationMs).toBeGreaterThan(folded.displayDurationMs);
61
+ });
62
+
63
+ test("formatFoldLabel uses human units", () => {
64
+ expect(formatFoldLabel(20)).toBe("20ms idle");
65
+ expect(formatFoldLabel(7 * 24 * 60 * 60 * 1000)).toBe("7d idle");
66
+ });
67
+ });
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Folded-time waterfall (console §9.3).
3
+ *
4
+ * Dead time collapses into a labelled, expandable bar the way a diff folds
5
+ * unchanged lines; real work stays exactly proportional. One linear scale
6
+ * serves a 20 ms trace and a week-long one — no modes, no log axis.
7
+ */
8
+
9
+ import { tierOfKind } from "./tier.ts";
10
+ import type { TimelineSegment, TraceSpan, WorkInterval } from "./types.ts";
11
+
12
+ /** Collapsed fold occupies this much of the display scale (ms-equivalent). */
13
+ export const COLLAPSED_FOLD_DISPLAY_MS = 40;
14
+
15
+ /** Gaps at or above this threshold become folds. */
16
+ export const DEFAULT_FOLD_THRESHOLD_MS = 50;
17
+
18
+ /** Options for {@link foldTimeline}. */
19
+ export interface FoldOptions {
20
+ /** Gap threshold before collapsing (default {@link DEFAULT_FOLD_THRESHOLD_MS}). */
21
+ readonly foldThresholdMs?: number;
22
+ /** Ids of folds the operator has expanded. */
23
+ readonly expandedFolds?: ReadonlySet<string>;
24
+ }
25
+
26
+ /** Result of folding a work timeline. */
27
+ export interface FoldedTimeline {
28
+ /** Ordered segments (work + folds). */
29
+ readonly segments: readonly TimelineSegment[];
30
+ /** Sum of display weights — denominator for proportional widths. */
31
+ readonly displayDurationMs: number;
32
+ /** Wall-clock span of the whole timeline. */
33
+ readonly wallDurationMs: number;
34
+ }
35
+
36
+ /**
37
+ * Format a duration for fold labels (`7d`, `2h`, `340ms`).
38
+ *
39
+ * @param ms - Duration in milliseconds
40
+ */
41
+ export function formatFoldLabel(ms: number): string {
42
+ const abs = Math.max(0, Math.round(ms));
43
+ if (abs < 1000) return `${abs}ms idle`;
44
+ const sec = abs / 1000;
45
+ if (sec < 60) return `${trim(sec)}s idle`;
46
+ const min = sec / 60;
47
+ if (min < 60) return `${trim(min)}m idle`;
48
+ const hr = min / 60;
49
+ if (hr < 48) return `${trim(hr)}h idle`;
50
+ const day = hr / 24;
51
+ return `${trim(day)}d idle`;
52
+ }
53
+
54
+ /**
55
+ * Fold dead time out of a sorted work timeline.
56
+ *
57
+ * @param intervals - Work intervals (any order; sorted internally)
58
+ * @param options - Fold threshold and expansion state
59
+ * @param criticalSpanIds - Spans on the critical path
60
+ */
61
+ export function foldTimeline(
62
+ intervals: readonly WorkInterval[],
63
+ options: FoldOptions = {},
64
+ criticalSpanIds: ReadonlySet<string> = new Set(),
65
+ ): FoldedTimeline {
66
+ const threshold = options.foldThresholdMs ?? DEFAULT_FOLD_THRESHOLD_MS;
67
+ const expanded = options.expandedFolds ?? new Set<string>();
68
+ const sorted = [...intervals].sort((a, b) => a.startMs - b.startMs);
69
+
70
+ if (sorted.length === 0) {
71
+ return { segments: [], displayDurationMs: 0, wallDurationMs: 0 };
72
+ }
73
+
74
+ const first = sorted[0];
75
+ const last = sorted[sorted.length - 1];
76
+ if (!first || !last) {
77
+ return { segments: [], displayDurationMs: 0, wallDurationMs: 0 };
78
+ }
79
+
80
+ const wallStart = first.startMs;
81
+ const wallEnd = Math.max(...sorted.map((i) => i.endMs));
82
+ const segments: TimelineSegment[] = [];
83
+ let cursor = wallStart;
84
+
85
+ for (const interval of sorted) {
86
+ const gap = interval.startMs - cursor;
87
+ if (gap >= threshold) {
88
+ const foldId = `fold:${cursor}:${interval.startMs}`;
89
+ const isExpanded = expanded.has(foldId);
90
+ const durationMs = gap;
91
+ segments.push({
92
+ kind: "fold",
93
+ id: foldId,
94
+ startMs: cursor,
95
+ endMs: interval.startMs,
96
+ durationMs,
97
+ label: formatFoldLabel(durationMs),
98
+ expanded: isExpanded,
99
+ displayMs: isExpanded ? durationMs : COLLAPSED_FOLD_DISPLAY_MS,
100
+ });
101
+ }
102
+
103
+ const durationMs = Math.max(0, interval.endMs - interval.startMs);
104
+ segments.push({
105
+ kind: "work",
106
+ id: interval.id,
107
+ label: interval.label,
108
+ startMs: interval.startMs,
109
+ endMs: interval.endMs,
110
+ durationMs,
111
+ tier: interval.tier,
112
+ spanId: interval.spanId,
113
+ critical: criticalSpanIds.has(interval.spanId),
114
+ failed: interval.failed === true,
115
+ displayMs: Math.max(1, durationMs),
116
+ });
117
+ cursor = Math.max(cursor, interval.endMs);
118
+ }
119
+
120
+ const displayDurationMs = segments.reduce((s, seg) => s + seg.displayMs, 0);
121
+ return {
122
+ segments,
123
+ displayDurationMs: Math.max(1, displayDurationMs),
124
+ wallDurationMs: wallEnd - wallStart,
125
+ };
126
+ }
127
+
128
+ /**
129
+ * Build work intervals from spans — one interval per span covering its
130
+ * active wall time. Prefer effect sub-intervals when present so intra-span
131
+ * idle (sleep) can fold too.
132
+ *
133
+ * @param spans - Spans in the open trace
134
+ */
135
+ export function intervalsFromSpans(spans: readonly TraceSpan[]): WorkInterval[] {
136
+ const out: WorkInterval[] = [];
137
+ for (const span of spans) {
138
+ if (span.effects.length > 0) {
139
+ for (const e of span.effects) {
140
+ out.push({
141
+ id: `${span.id}:${e.kind}:${e.resource}:${e.timestamp}`,
142
+ label: `${e.kind} ${e.resource}`,
143
+ startMs: e.timestamp,
144
+ endMs: e.timestamp + Math.max(1, e.duration),
145
+ tier: tierOfKind(e.kind),
146
+ spanId: span.id,
147
+ failed:
148
+ span.errorCode != null &&
149
+ e === span.effects[span.effects.length - 1],
150
+ });
151
+ }
152
+ } else {
153
+ out.push({
154
+ id: span.id,
155
+ label: span.flow,
156
+ startMs: span.startedAt,
157
+ endMs: span.endedAt,
158
+ tier: "none",
159
+ spanId: span.id,
160
+ failed: span.errorCode != null,
161
+ });
162
+ }
163
+ }
164
+ return out;
165
+ }
166
+
167
+ function trim(n: number): string {
168
+ const r = Math.round(n * 10) / 10;
169
+ return Number.isInteger(r) ? String(r) : r.toFixed(1);
170
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Traces panel — folded-time causal chain (console §9.3).
3
+ *
4
+ * Pure modules live here so `bun test src/console/ui/traces` gates behaviour
5
+ * without mounting the full SPA.
6
+ */
7
+
8
+ export {
9
+ buildCausalChain,
10
+ groupTraceRoots,
11
+ indexSpans,
12
+ initialFocusSpanId,
13
+ type CausalChain,
14
+ type TraceRoot,
15
+ } from "./chain.ts";
16
+ export { criticalPathSpanIds, workMs } from "./critical-path.ts";
17
+ export {
18
+ matchesEffectFilter,
19
+ parseEffectFilter,
20
+ serializeEffectFilter,
21
+ traceMatchesEffectFilter,
22
+ } from "./filter.ts";
23
+ export {
24
+ COLLAPSED_FOLD_DISPLAY_MS,
25
+ DEFAULT_FOLD_THRESHOLD_MS,
26
+ foldTimeline,
27
+ formatFoldLabel,
28
+ intervalsFromSpans,
29
+ type FoldedTimeline,
30
+ type FoldOptions,
31
+ } from "./fold.ts";
32
+ export { miniWaterfall, rootErrorCode } from "./mini.ts";
33
+ export { replayDecision, type ReplayDecision } from "./replay.ts";
34
+ export {
35
+ boostFlowFully,
36
+ DEFAULT_SAMPLING_LABEL,
37
+ FULL_TRACE_BOOST_MS,
38
+ pruneBoosts,
39
+ samplingLabel,
40
+ type FullTraceBoost,
41
+ } from "./sampling.ts";
42
+ export {
43
+ closeTrace,
44
+ effectFilterOf,
45
+ expandedFoldsOf,
46
+ openTrace,
47
+ parseTracesSearch,
48
+ serializeTracesSearch,
49
+ setEffectFilter,
50
+ toggleFold,
51
+ TracesSearchSchema,
52
+ type TracesSearch,
53
+ } from "./search.ts";
54
+ export { peakSpanTier, tierOfKind, traceHasExternal } from "./tier.ts";
55
+ export type {
56
+ EffectFilter,
57
+ MiniBar,
58
+ SampleReason,
59
+ SpanTier,
60
+ TimelineSegment,
61
+ TraceEffect,
62
+ TraceSpan,
63
+ WorkInterval,
64
+ } from "./types.ts";
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Inline mini-waterfall for list rows (console §9.3).
3
+ */
4
+
5
+ import { peakSpanTier, tierOfKind } from "./tier.ts";
6
+ import type { MiniBar, TraceSpan } from "./types.ts";
7
+
8
+ /**
9
+ * Build proportional mini-bars for a root row (connected spans).
10
+ *
11
+ * @param spans - Spans in the root's connected component
12
+ */
13
+ export function miniWaterfall(spans: readonly TraceSpan[]): MiniBar[] {
14
+ if (spans.length === 0) return [];
15
+ const start = Math.min(...spans.map((s) => s.startedAt));
16
+ const end = Math.max(...spans.map((s) => s.endedAt));
17
+ const wall = Math.max(1, end - start);
18
+
19
+ if (spans.every((s) => s.effects.length === 0)) {
20
+ return spans.map((s) => ({
21
+ start: (s.startedAt - start) / wall,
22
+ width: Math.max(0.02, s.durationMs / wall),
23
+ tier: peakSpanTier(s.effects),
24
+ failed: s.errorCode != null,
25
+ }));
26
+ }
27
+
28
+ const bars: MiniBar[] = [];
29
+ for (const s of spans) {
30
+ if (s.effects.length === 0) {
31
+ bars.push({
32
+ start: (s.startedAt - start) / wall,
33
+ width: Math.max(0.02, s.durationMs / wall),
34
+ tier: "none",
35
+ failed: s.errorCode != null,
36
+ });
37
+ continue;
38
+ }
39
+ for (let i = 0; i < s.effects.length; i++) {
40
+ const e = s.effects[i];
41
+ if (!e) continue;
42
+ bars.push({
43
+ start: (e.timestamp - start) / wall,
44
+ width: Math.max(0.02, e.duration / wall),
45
+ tier: tierOfKind(e.kind),
46
+ failed: s.errorCode != null && i === s.effects.length - 1,
47
+ });
48
+ }
49
+ }
50
+ return bars;
51
+ }
52
+
53
+ /**
54
+ * Typed error code for a root row — first failure in the chain, else null.
55
+ *
56
+ * @param spans - Connected spans
57
+ */
58
+ export function rootErrorCode(
59
+ spans: readonly TraceSpan[],
60
+ ): string | null {
61
+ for (const s of spans) {
62
+ if (s.errorCode) return s.errorCode;
63
+ }
64
+ return null;
65
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Replay reversibility tests (console §9.3).
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { TRACES_FIXTURE } from "./fixture.ts";
7
+ import { replayDecision } from "./replay.ts";
8
+
9
+ describe("replayDecision", () => {
10
+ test("offers dry-run when the trace has an external effect", () => {
11
+ const chain = TRACES_FIXTURE.filter(
12
+ (s) => s.id === "run-create-ok" || s.id === "run-fulfill",
13
+ );
14
+ const decision = replayDecision(chain);
15
+ expect(decision.mode).toBe("dry-run");
16
+ if (decision.mode !== "dry-run") return;
17
+ expect(decision.reason).toContain("external");
18
+ });
19
+
20
+ test("allows full replay when every effect is reversible", () => {
21
+ const fail = TRACES_FIXTURE.filter((s) => s.id === "run-create-fail");
22
+ expect(replayDecision(fail)).toEqual({ mode: "replay" });
23
+ });
24
+ });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Replay governed by reversibility (console §9.3 · §9.1 · §10.5).
3
+ *
4
+ * A trace containing an external effect offers a dry run with external
5
+ * effects stubbed — never a silent re-send of email / charge.
6
+ */
7
+
8
+ import { traceHasExternal } from "./tier.ts";
9
+ import type { TraceSpan } from "./types.ts";
10
+
11
+ /** Replay decision for a connected trace. */
12
+ export type ReplayDecision =
13
+ | { readonly mode: "replay" }
14
+ | {
15
+ readonly mode: "dry-run";
16
+ readonly reason: string;
17
+ };
18
+
19
+ /**
20
+ * Decide how Replay may proceed for the open trace.
21
+ *
22
+ * @param spans - Connected spans
23
+ */
24
+ export function replayDecision(
25
+ spans: readonly TraceSpan[],
26
+ ): ReplayDecision {
27
+ if (traceHasExternal(spans)) {
28
+ return {
29
+ mode: "dry-run",
30
+ reason:
31
+ "This trace contains an external effect. Replay runs as a dry run with external effects stubbed.",
32
+ };
33
+ }
34
+ return { mode: "replay" };
35
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Sampling honesty tests (console §9.3).
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import {
7
+ boostFlowFully,
8
+ DEFAULT_SAMPLING_LABEL,
9
+ FULL_TRACE_BOOST_MS,
10
+ pruneBoosts,
11
+ samplingLabel,
12
+ } from "./sampling.ts";
13
+
14
+ describe("sampling", () => {
15
+ test("default label states 10% + all errors", () => {
16
+ expect(samplingLabel([])).toBe(DEFAULT_SAMPLING_LABEL);
17
+ });
18
+
19
+ test("boost adds a 10-minute full-trace escape hatch", () => {
20
+ const now = 1_000_000;
21
+ const boosts = boostFlowFully([], "bookings.create", now);
22
+ expect(boosts[0]?.until).toBe(now + FULL_TRACE_BOOST_MS);
23
+ expect(samplingLabel(boosts, now)).toContain("bookings.create");
24
+ expect(pruneBoosts(boosts, now + FULL_TRACE_BOOST_MS + 1)).toEqual([]);
25
+ });
26
+ });
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Honest sampling labels + full-trace escape hatch (console §9.3).
3
+ *
4
+ * Sampling is stated in the list (10% + all errors) with a
5
+ * "trace this flow fully for 10 minutes" override.
6
+ */
7
+
8
+ /** Default sampling policy shown in the list header. */
9
+ export const DEFAULT_SAMPLING_LABEL = "10% + all errors";
10
+
11
+ /** Full-trace boost window (10 minutes). */
12
+ export const FULL_TRACE_BOOST_MS = 10 * 60 * 1000;
13
+
14
+ /** Active boost for one flow. */
15
+ export interface FullTraceBoost {
16
+ /** Flow name. */
17
+ readonly flow: string;
18
+ /** Epoch-ms when the boost expires. */
19
+ readonly until: number;
20
+ }
21
+
22
+ /**
23
+ * Sampling line for the list header, including active boosts.
24
+ *
25
+ * @param boosts - Active boosts
26
+ * @param now - Clock
27
+ */
28
+ export function samplingLabel(
29
+ boosts: readonly FullTraceBoost[],
30
+ now: number = Date.now(),
31
+ ): string {
32
+ const live = boosts.filter((b) => b.until > now);
33
+ if (live.length === 0) return DEFAULT_SAMPLING_LABEL;
34
+ const flows = live.map((b) => b.flow).join(", ");
35
+ return `${DEFAULT_SAMPLING_LABEL} · full: ${flows}`;
36
+ }
37
+
38
+ /**
39
+ * Create / refresh a 10-minute full-trace boost for a flow.
40
+ *
41
+ * @param boosts - Existing boosts
42
+ * @param flow - Flow to boost
43
+ * @param now - Clock
44
+ */
45
+ export function boostFlowFully(
46
+ boosts: readonly FullTraceBoost[],
47
+ flow: string,
48
+ now: number = Date.now(),
49
+ ): FullTraceBoost[] {
50
+ const until = now + FULL_TRACE_BOOST_MS;
51
+ const rest = boosts.filter((b) => b.flow !== flow && b.until > now);
52
+ return [...rest, { flow, until }];
53
+ }
54
+
55
+ /**
56
+ * Prune expired boosts.
57
+ *
58
+ * @param boosts - Boosts
59
+ * @param now - Clock
60
+ */
61
+ export function pruneBoosts(
62
+ boosts: readonly FullTraceBoost[],
63
+ now: number = Date.now(),
64
+ ): FullTraceBoost[] {
65
+ return boosts.filter((b) => b.until > now);
66
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Typed search params for the Traces panel (console §7 · §9.3).
3
+ *
4
+ * Pasted links reproduce the exact view — open trace, focus span, effect
5
+ * filter, expanded folds.
6
+ */
7
+
8
+ import { z } from "zod";
9
+ import {
10
+ parseEffectFilter,
11
+ serializeEffectFilter,
12
+ type EffectFilter,
13
+ } from "./filter.ts";
14
+
15
+ /** Zod schema for Traces URL search params. */
16
+ export const TracesSearchSchema = z.object({
17
+ /** Open root / connected-component id (usually the root span id). */
18
+ trace: z.string().optional(),
19
+ /** Focused span within the open trace. */
20
+ span: z.string().optional(),
21
+ /** Effect filter compact form (`wrote:sql:bookings`, `cost:0.05`, …). */
22
+ effect: z.string().optional(),
23
+ /** Free-text filter (dims, never hides). */
24
+ q: z.string().optional(),
25
+ /** Comma-separated expanded fold ids. */
26
+ folds: z.string().optional(),
27
+ /** Flow selected for the full-trace boost control (UI only). */
28
+ boost: z.string().optional(),
29
+ });
30
+
31
+ /** Parsed, typed Traces search state. */
32
+ export type TracesSearch = z.infer<typeof TracesSearchSchema>;
33
+
34
+ /**
35
+ * Parse unknown search params into a typed {@link TracesSearch}.
36
+ *
37
+ * @param raw - Router search object
38
+ */
39
+ export function parseTracesSearch(raw: unknown): TracesSearch {
40
+ const result = TracesSearchSchema.safeParse(raw ?? {});
41
+ if (result.success) return result.data;
42
+ return TracesSearchSchema.parse({});
43
+ }
44
+
45
+ /**
46
+ * Serialise typed search into a plain object suitable for TanStack Router.
47
+ *
48
+ * @param search - Typed search
49
+ */
50
+ export function serializeTracesSearch(
51
+ search: TracesSearch,
52
+ ): Record<string, string> {
53
+ const out: Record<string, string> = {};
54
+ if (search.trace) out.trace = search.trace;
55
+ if (search.span) out.span = search.span;
56
+ if (search.effect) out.effect = search.effect;
57
+ if (search.q) out.q = search.q;
58
+ if (search.folds) out.folds = search.folds;
59
+ if (search.boost) out.boost = search.boost;
60
+ return out;
61
+ }
62
+
63
+ /**
64
+ * Effect filter derived from search.
65
+ *
66
+ * @param search - Typed search
67
+ */
68
+ export function effectFilterOf(search: TracesSearch): EffectFilter | null {
69
+ return parseEffectFilter(search.effect);
70
+ }
71
+
72
+ /**
73
+ * Expanded fold ids from search.
74
+ *
75
+ * @param search - Typed search
76
+ */
77
+ export function expandedFoldsOf(search: TracesSearch): Set<string> {
78
+ if (!search.folds) return new Set();
79
+ return new Set(
80
+ search.folds
81
+ .split(",")
82
+ .map((s) => s.trim())
83
+ .filter(Boolean),
84
+ );
85
+ }
86
+
87
+ /**
88
+ * Open a trace (root id) and optional focus span.
89
+ *
90
+ * @param prev - Current search
91
+ * @param rootId - Root span id
92
+ * @param spanId - Optional focus span
93
+ */
94
+ export function openTrace(
95
+ prev: TracesSearch,
96
+ rootId: string,
97
+ spanId?: string,
98
+ ): TracesSearch {
99
+ return {
100
+ ...prev,
101
+ trace: rootId,
102
+ span: spanId,
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Close the detail view; stay on the Traces panel.
108
+ *
109
+ * @param prev - Current search
110
+ */
111
+ export function closeTrace(prev: TracesSearch): TracesSearch {
112
+ return {
113
+ ...prev,
114
+ trace: undefined,
115
+ span: undefined,
116
+ folds: undefined,
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Toggle a fold's expanded state in the URL.
122
+ *
123
+ * @param prev - Current search
124
+ * @param foldId - Fold segment id
125
+ */
126
+ export function toggleFold(prev: TracesSearch, foldId: string): TracesSearch {
127
+ const set = expandedFoldsOf(prev);
128
+ if (set.has(foldId)) set.delete(foldId);
129
+ else set.add(foldId);
130
+ const folds = [...set].join(",");
131
+ return { ...prev, folds: folds || undefined };
132
+ }
133
+
134
+ /**
135
+ * Set the effect filter (or clear with null).
136
+ *
137
+ * @param prev - Current search
138
+ * @param filter - Effect filter
139
+ */
140
+ export function setEffectFilter(
141
+ prev: TracesSearch,
142
+ filter: EffectFilter | null,
143
+ ): TracesSearch {
144
+ return {
145
+ ...prev,
146
+ effect: serializeEffectFilter(filter),
147
+ };
148
+ }