@crvouga/atlas 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +178 -604
  3. package/dist/bun/src/driver.d.ts +41 -7
  4. package/dist/bun/src/driver.js +47 -6
  5. package/dist/bun/src/index.d.ts +8 -0
  6. package/dist/bun/src/index.js +8 -0
  7. package/dist/core/src/cli.d.ts +14 -1
  8. package/dist/core/src/cli.js +30 -1
  9. package/dist/core/src/config.d.ts +70 -4
  10. package/dist/core/src/config.js +62 -3
  11. package/dist/core/src/events/cloudevents.d.ts +54 -9
  12. package/dist/core/src/events/cloudevents.js +60 -9
  13. package/dist/core/src/graph.d.ts +21 -0
  14. package/dist/core/src/graph.js +26 -0
  15. package/dist/core/src/index.d.ts +11 -0
  16. package/dist/core/src/index.js +11 -0
  17. package/dist/core/src/lint.d.ts +30 -0
  18. package/dist/core/src/lint.js +13 -0
  19. package/dist/core/src/plan.d.ts +39 -1
  20. package/dist/core/src/plan.js +28 -1
  21. package/dist/core/src/privacy.d.ts +29 -2
  22. package/dist/core/src/privacy.js +19 -2
  23. package/dist/core/src/report/formats.d.ts +34 -4
  24. package/dist/core/src/report/formats.js +24 -4
  25. package/dist/core/src/report/markdown.d.ts +15 -0
  26. package/dist/core/src/report/markdown.js +8 -0
  27. package/dist/core/src/run/clients.d.ts +44 -5
  28. package/dist/core/src/run/clients.js +46 -2
  29. package/dist/core/src/run/execute.d.ts +69 -16
  30. package/dist/core/src/run/execute.js +67 -16
  31. package/dist/core/src/run/frames.d.ts +13 -4
  32. package/dist/core/src/run/frames.js +19 -4
  33. package/dist/core/src/run/http.d.ts +34 -1
  34. package/dist/core/src/run/http.js +14 -1
  35. package/dist/core/src/run/types.d.ts +76 -3
  36. package/dist/core/src/run/types.js +19 -3
  37. package/dist/core/src/signals.d.ts +49 -5
  38. package/dist/core/src/signals.js +22 -5
  39. package/dist/core/src/spec/compose.d.ts +23 -1
  40. package/dist/core/src/spec/compose.js +10 -1
  41. package/dist/core/src/spec/index.d.ts +9 -1
  42. package/dist/core/src/spec/index.js +9 -1
  43. package/dist/core/src/spec/load.d.ts +22 -1
  44. package/dist/core/src/spec/load.js +31 -1
  45. package/dist/core/src/spec/parse.d.ts +16 -2
  46. package/dist/core/src/spec/parse.js +25 -2
  47. package/dist/core/src/spec/scxml.d.ts +25 -4
  48. package/dist/core/src/spec/scxml.js +36 -4
  49. package/dist/core/src/spec/types.d.ts +52 -1
  50. package/dist/core/src/spec/types.js +24 -0
  51. package/dist/detox/src/index.d.ts +54 -11
  52. package/dist/detox/src/index.js +45 -7
  53. package/dist/playwright/src/driver.d.ts +39 -3
  54. package/dist/playwright/src/driver.js +27 -3
  55. package/dist/playwright/src/index.d.ts +10 -0
  56. package/dist/playwright/src/index.js +10 -0
  57. package/dist/playwright/src/media.d.ts +50 -4
  58. package/dist/playwright/src/media.js +55 -4
  59. package/dist/playwright/src/signals.d.ts +44 -5
  60. package/dist/playwright/src/signals.js +29 -5
  61. package/dist/reports/src/attachment-files.d.ts +44 -0
  62. package/dist/reports/src/attachment-files.js +121 -0
  63. package/dist/reports/src/attachment-response.d.ts +31 -0
  64. package/dist/reports/src/attachment-response.js +55 -0
  65. package/dist/reports/src/aws-credentials.d.ts +48 -0
  66. package/dist/reports/src/aws-credentials.js +221 -0
  67. package/dist/reports/src/browser-navigation.d.ts +14 -0
  68. package/dist/reports/src/browser-navigation.js +7 -0
  69. package/dist/reports/src/bundle.d.ts +34 -2
  70. package/dist/reports/src/bundle.js +38 -2
  71. package/dist/reports/src/catalog.d.ts +34 -3
  72. package/dist/reports/src/catalog.js +17 -3
  73. package/dist/reports/src/cli-stores.d.ts +36 -0
  74. package/dist/reports/src/cli-stores.js +73 -0
  75. package/dist/reports/src/clock.d.ts +7 -2
  76. package/dist/reports/src/clock.js +5 -2
  77. package/dist/reports/src/completion-order.d.ts +18 -5
  78. package/dist/reports/src/completion-order.js +18 -5
  79. package/dist/reports/src/compose.d.ts +80 -0
  80. package/dist/reports/src/compose.js +117 -0
  81. package/dist/reports/src/copy-store.d.ts +29 -0
  82. package/dist/reports/src/copy-store.js +52 -0
  83. package/dist/reports/src/directory-outline.d.ts +38 -0
  84. package/dist/reports/src/directory-outline.js +103 -0
  85. package/dist/reports/src/directory-store.d.ts +20 -0
  86. package/dist/reports/src/directory-store.js +166 -0
  87. package/dist/reports/src/doctor.d.ts +29 -0
  88. package/dist/reports/src/doctor.js +83 -0
  89. package/dist/reports/src/effective-delta.d.ts +34 -0
  90. package/dist/reports/src/effective-delta.js +25 -0
  91. package/dist/reports/src/evidence-detail.d.ts +64 -0
  92. package/dist/reports/src/evidence-detail.js +92 -0
  93. package/dist/reports/src/evidence-live.d.ts +40 -4
  94. package/dist/reports/src/evidence-live.js +52 -4
  95. package/dist/reports/src/evidence-types.d.ts +70 -1
  96. package/dist/reports/src/evidence-types.js +5 -1
  97. package/dist/reports/src/evidence-view.d.ts +58 -6
  98. package/dist/reports/src/evidence-view.js +44 -5
  99. package/dist/reports/src/explorer-types.d.ts +40 -3
  100. package/dist/reports/src/explorer-types.js +8 -0
  101. package/dist/reports/src/explorer-versions.d.ts +9 -1
  102. package/dist/reports/src/explorer-versions.js +18 -1
  103. package/dist/reports/src/export-evidence.d.ts +16 -1
  104. package/dist/reports/src/export-evidence.js +52 -1
  105. package/dist/reports/src/fetcher.d.ts +27 -3
  106. package/dist/reports/src/fetcher.js +11 -3
  107. package/dist/reports/src/format-date.d.ts +6 -0
  108. package/dist/reports/src/format-date.js +6 -0
  109. package/dist/reports/src/format.d.ts +16 -0
  110. package/dist/reports/src/format.js +10 -0
  111. package/dist/reports/src/frames.d.ts +36 -3
  112. package/dist/reports/src/frames.js +22 -3
  113. package/dist/reports/src/hash.d.ts +18 -0
  114. package/dist/reports/src/hash.js +13 -0
  115. package/dist/reports/src/host.d.ts +29 -0
  116. package/dist/reports/src/host.js +64 -0
  117. package/dist/reports/src/html-frame.d.ts +5 -6
  118. package/dist/reports/src/html-frame.js +12 -1
  119. package/dist/reports/src/http-store.d.ts +52 -0
  120. package/dist/reports/src/http-store.js +145 -0
  121. package/dist/reports/src/http.d.ts +7 -0
  122. package/dist/reports/src/http.js +6 -0
  123. package/dist/reports/src/ingest.d.ts +54 -0
  124. package/dist/reports/src/ingest.js +210 -0
  125. package/dist/reports/src/init.d.ts +40 -0
  126. package/dist/reports/src/init.js +364 -0
  127. package/dist/reports/src/junit.d.ts +33 -6
  128. package/dist/reports/src/junit.js +87 -21
  129. package/dist/reports/src/keyboard.d.ts +20 -0
  130. package/dist/reports/src/keyboard.js +11 -0
  131. package/dist/reports/src/keys.d.ts +21 -3
  132. package/dist/reports/src/keys.js +21 -3
  133. package/dist/reports/src/layer-axes.d.ts +48 -0
  134. package/dist/reports/src/layer-axes.js +71 -0
  135. package/dist/reports/src/layer-catalog.d.ts +28 -1
  136. package/dist/reports/src/layer-catalog.js +19 -2
  137. package/dist/reports/src/layer-merge.d.ts +98 -9
  138. package/dist/reports/src/layer-merge.js +154 -33
  139. package/dist/reports/src/layer-source.d.ts +18 -0
  140. package/dist/reports/src/layer-source.js +14 -0
  141. package/dist/reports/src/layer-store.d.ts +42 -0
  142. package/dist/reports/src/layer-store.js +63 -5
  143. package/dist/reports/src/layer-types.d.ts +34 -1
  144. package/dist/reports/src/layers-route.d.ts +47 -4
  145. package/dist/reports/src/layers-route.js +88 -12
  146. package/dist/reports/src/media-types.d.ts +11 -0
  147. package/dist/reports/src/media-types.js +22 -0
  148. package/dist/reports/src/namespace-guard.d.ts +10 -1
  149. package/dist/reports/src/namespace-guard.js +10 -1
  150. package/dist/reports/src/navigation.d.ts +12 -0
  151. package/dist/reports/src/navigation.js +7 -0
  152. package/dist/reports/src/object-io.d.ts +11 -4
  153. package/dist/reports/src/object-io.js +4 -4
  154. package/dist/reports/src/object-store-conformance.d.ts +27 -0
  155. package/dist/reports/src/object-store-conformance.js +87 -0
  156. package/dist/reports/src/object-store.d.ts +33 -24
  157. package/dist/reports/src/object-store.js +17 -24
  158. package/dist/reports/src/parse-with.d.ts +16 -0
  159. package/dist/reports/src/parse-with.js +14 -0
  160. package/dist/reports/src/performance-part.d.ts +25 -1
  161. package/dist/reports/src/performance-part.js +15 -1
  162. package/dist/reports/src/performance.d.ts +22 -2
  163. package/dist/reports/src/performance.js +12 -2
  164. package/dist/reports/src/persist.d.ts +12 -3
  165. package/dist/reports/src/persist.js +12 -3
  166. package/dist/reports/src/phone.d.ts +18 -1
  167. package/dist/reports/src/phone.js +18 -1
  168. package/dist/reports/src/protocol.d.ts +30 -4
  169. package/dist/reports/src/protocol.js +15 -4
  170. package/dist/reports/src/publication.d.ts +21 -1
  171. package/dist/reports/src/publication.js +21 -1
  172. package/dist/reports/src/publish-checks.d.ts +35 -0
  173. package/dist/reports/src/publish-checks.js +122 -0
  174. package/dist/reports/src/publish.d.ts +44 -9
  175. package/dist/reports/src/publish.js +40 -7
  176. package/dist/reports/src/read.d.ts +46 -16
  177. package/dist/reports/src/read.js +38 -14
  178. package/dist/reports/src/recording-bundle.d.ts +13 -2
  179. package/dist/reports/src/recording-bundle.js +4 -2
  180. package/dist/reports/src/recording-keys.d.ts +15 -1
  181. package/dist/reports/src/recording-keys.js +15 -1
  182. package/dist/reports/src/remote-report.d.ts +28 -7
  183. package/dist/reports/src/remote-report.js +15 -7
  184. package/dist/reports/src/report-cli.d.ts +51 -0
  185. package/dist/reports/src/report-cli.js +485 -0
  186. package/dist/reports/src/report-index.d.ts +99 -0
  187. package/dist/reports/src/report-index.js +337 -0
  188. package/dist/reports/src/report-loader.d.ts +10 -0
  189. package/dist/reports/src/report-loader.js +6 -0
  190. package/dist/reports/src/report-parts.d.ts +29 -3
  191. package/dist/reports/src/report-parts.js +40 -3
  192. package/dist/reports/src/report-status.d.ts +48 -0
  193. package/dist/reports/src/report-status.js +156 -0
  194. package/dist/reports/src/report-types.d.ts +73 -0
  195. package/dist/reports/src/report-types.js +3 -0
  196. package/dist/reports/src/reporter.d.ts +67 -0
  197. package/dist/reports/src/reporter.js +128 -0
  198. package/dist/reports/src/reports-explorer-route.d.ts +541 -0
  199. package/dist/reports/src/reports-explorer-route.js +11 -0
  200. package/dist/reports/src/reports-list-route.d.ts +9 -0
  201. package/dist/reports/src/reports-list-route.js +9 -0
  202. package/dist/reports/src/reports-route.d.ts +561 -22
  203. package/dist/reports/src/reports-route.js +11 -3
  204. package/dist/reports/src/reports-store.d.ts +19 -2
  205. package/dist/reports/src/reports-store.js +10 -2
  206. package/dist/reports/src/resilient-cache.d.ts +14 -1
  207. package/dist/reports/src/resilient-cache.js +8 -1
  208. package/dist/reports/src/retention.d.ts +17 -1
  209. package/dist/reports/src/retention.js +5 -1
  210. package/dist/reports/src/run-bundle.d.ts +63 -0
  211. package/dist/reports/src/run-bundle.js +159 -0
  212. package/dist/reports/src/s3-store.d.ts +79 -0
  213. package/dist/reports/src/s3-store.js +295 -0
  214. package/dist/reports/src/scenario.d.ts +14 -4
  215. package/dist/reports/src/scenario.js +5 -4
  216. package/dist/reports/src/sigv4.d.ts +72 -0
  217. package/dist/reports/src/sigv4.js +96 -0
  218. package/dist/reports/src/snapshot-bundle.d.ts +24 -1
  219. package/dist/reports/src/snapshot-bundle.js +27 -2
  220. package/dist/reports/src/snapshot-surface.d.ts +20 -9
  221. package/dist/reports/src/snapshot-surface.js +32 -19
  222. package/dist/reports/src/source-content.d.ts +23 -0
  223. package/dist/reports/src/source-content.js +30 -1
  224. package/dist/reports/src/source-entries.d.ts +13 -0
  225. package/dist/reports/src/source-entries.js +6 -0
  226. package/dist/reports/src/source-part.d.ts +15 -0
  227. package/dist/reports/src/source-part.js +8 -0
  228. package/dist/reports/src/source-reader.d.ts +11 -0
  229. package/dist/reports/src/source-reader.js +5 -0
  230. package/dist/reports/src/spec-evidence.d.ts +12 -2
  231. package/dist/reports/src/spec-evidence.js +6 -2
  232. package/dist/reports/src/spec-inventory.d.ts +15 -1
  233. package/dist/reports/src/spec-inventory.js +22 -1
  234. package/dist/reports/src/spec-link.d.ts +28 -0
  235. package/dist/reports/src/spec-link.js +70 -0
  236. package/dist/reports/src/spec-set.d.ts +63 -0
  237. package/dist/reports/src/spec-set.js +177 -0
  238. package/dist/reports/src/status.d.ts +10 -0
  239. package/dist/reports/src/status.js +5 -0
  240. package/dist/reports/src/store-prefix.d.ts +28 -0
  241. package/dist/reports/src/store-prefix.js +22 -0
  242. package/dist/reports/src/store-url.d.ts +89 -0
  243. package/dist/reports/src/store-url.js +160 -0
  244. package/dist/reports/src/test-catalog-entity.d.ts +11 -0
  245. package/dist/reports/src/test-catalog-entity.js +6 -0
  246. package/dist/reports/src/types.d.ts +6 -1
  247. package/dist/reports/src/use-report-nav.d.ts +35 -0
  248. package/dist/reports/src/use-report-nav.js +12 -0
  249. package/dist/schema/src/api.d.ts +799 -0
  250. package/dist/schema/src/api.js +201 -0
  251. package/dist/schema/src/cli-results.d.ts +210 -0
  252. package/dist/schema/src/cli-results.js +124 -0
  253. package/dist/schema/src/common.d.ts +53 -0
  254. package/dist/schema/src/common.js +42 -0
  255. package/dist/schema/src/index.d.ts +14 -0
  256. package/dist/schema/src/index.js +14 -0
  257. package/dist/schema/src/layer.d.ts +2273 -0
  258. package/dist/schema/src/layer.js +462 -0
  259. package/dist/schema/src/manifest.d.ts +95 -0
  260. package/dist/schema/src/manifest.js +84 -0
  261. package/dist/schema/src/report-sources.d.ts +28 -0
  262. package/dist/schema/src/report-sources.js +25 -0
  263. package/dist/schema/src/runs-index.d.ts +16 -0
  264. package/dist/schema/src/runs-index.js +15 -0
  265. package/dist/schema/src/server-config.d.ts +93 -0
  266. package/dist/schema/src/server-config.js +73 -0
  267. package/dist/schema/src/spec.d.ts +69 -0
  268. package/dist/schema/src/spec.js +58 -0
  269. package/dist/server/src/app.d.ts +62 -0
  270. package/dist/server/src/app.js +419 -0
  271. package/dist/server/src/auth.d.ts +41 -0
  272. package/dist/server/src/auth.js +59 -0
  273. package/dist/server/src/config.d.ts +83 -0
  274. package/dist/server/src/config.js +187 -0
  275. package/dist/server/src/dev.d.ts +12 -0
  276. package/dist/server/src/dev.js +80 -0
  277. package/dist/server/src/events.d.ts +29 -0
  278. package/dist/server/src/events.js +101 -0
  279. package/dist/server/src/host.d.ts +30 -0
  280. package/dist/server/src/host.js +115 -0
  281. package/dist/server/src/index.d.ts +16 -0
  282. package/dist/server/src/index.js +16 -0
  283. package/dist/server/src/llms.d.ts +19 -0
  284. package/dist/server/src/llms.js +63 -0
  285. package/dist/server/src/main.d.ts +30 -0
  286. package/dist/server/src/main.js +112 -0
  287. package/dist/server/src/openapi.d.ts +59 -0
  288. package/dist/server/src/openapi.js +374 -0
  289. package/dist/server/src/problem.d.ts +8 -0
  290. package/dist/server/src/problem.js +39 -0
  291. package/dist/server/src/site.d.ts +13 -0
  292. package/dist/server/src/site.js +43 -0
  293. package/dist/server/src/store-api.d.ts +28 -0
  294. package/dist/server/src/store-api.js +159 -0
  295. package/dist/server/src/validate.d.ts +71 -0
  296. package/dist/server/src/validate.js +197 -0
  297. package/dist/vitest/src/index.d.ts +27 -5
  298. package/dist/vitest/src/index.js +18 -5
  299. package/dist/webdriver/src/driver.d.ts +63 -11
  300. package/dist/webdriver/src/driver.js +57 -6
  301. package/dist/webdriver/src/index.d.ts +8 -0
  302. package/dist/webdriver/src/index.js +1 -0
  303. package/dist/webdriver/src/protocol.d.ts +75 -6
  304. package/dist/webdriver/src/protocol.js +79 -6
  305. package/docs/agents.md +137 -0
  306. package/docs/deploying.md +345 -0
  307. package/docs/dogfooding.md +175 -0
  308. package/docs/extending.md +242 -0
  309. package/docs/integrating.md +485 -0
  310. package/docs/reference/bun.md +141 -0
  311. package/docs/reference/cli.md +146 -0
  312. package/docs/reference/core.md +2426 -0
  313. package/docs/reference/detox.md +150 -0
  314. package/docs/reference/http-api.md +303 -0
  315. package/docs/reference/playwright.md +303 -0
  316. package/docs/reference/reports.md +7098 -0
  317. package/docs/reference/schema.md +1651 -0
  318. package/docs/reference/server.md +685 -0
  319. package/docs/reference/vitest.md +45 -0
  320. package/docs/reference/webdriver.md +330 -0
  321. package/docs/report-backends.md +144 -0
  322. package/docs/report-contract.md +400 -0
  323. package/docs/reporting-issues.md +160 -0
  324. package/docs/server.md +285 -0
  325. package/docs/statecharts.md +641 -0
  326. package/llms-full.txt +3506 -0
  327. package/llms.txt +47 -0
  328. package/package.json +33 -5
  329. package/packages/core/README.md +2 -1
  330. package/packages/reports/README.md +69 -2
  331. package/packages/reports/STORAGE.md +5 -1
  332. package/packages/schema/README.md +14 -0
  333. package/packages/schema/schemas/check-detail.schema.json +1032 -0
  334. package/packages/schema/schemas/checks-result.schema.json +26 -0
  335. package/packages/schema/schemas/command-error.schema.json +35 -0
  336. package/packages/schema/schemas/doctor-result.schema.json +60 -0
  337. package/packages/schema/schemas/effective-delta.schema.json +490 -0
  338. package/packages/schema/schemas/effective-evidence.schema.json +471 -0
  339. package/packages/schema/schemas/evidence-page.schema.json +271 -0
  340. package/packages/schema/schemas/hello-event.schema.json +22 -0
  341. package/packages/schema/schemas/init-plan.schema.json +347 -0
  342. package/packages/schema/schemas/layer-rows.schema.json +199 -0
  343. package/packages/schema/schemas/layer.schema.json +2888 -0
  344. package/packages/schema/schemas/merge-result.schema.json +40 -0
  345. package/packages/schema/schemas/outline.schema.json +62 -0
  346. package/packages/schema/schemas/problem.schema.json +37 -0
  347. package/packages/schema/schemas/publish-checks.schema.json +1413 -0
  348. package/packages/schema/schemas/publish-result.schema.json +168 -0
  349. package/packages/schema/schemas/ready.schema.json +68 -0
  350. package/packages/schema/schemas/report-event.schema.json +100 -0
  351. package/packages/schema/schemas/report-status.schema.json +370 -0
  352. package/packages/schema/schemas/server-config.schema.json +194 -0
  353. package/packages/schema/schemas/server-info.schema.json +114 -0
  354. package/packages/schema/schemas/spec-set.schema.json +103 -0
  355. package/packages/schema/schemas/store-listing.schema.json +29 -0
  356. package/packages/schema/schemas/store-write-result.schema.json +28 -0
  357. package/packages/schema/schemas/stream-result.schema.json +59 -0
  358. package/packages/server/README.md +43 -0
  359. package/packages/server/openapi.json +6699 -0
  360. package/packages/visualizer/README.md +27 -5
  361. package/packages/visualizer/example/specs/coffee/ordering/cart.qnt +7 -0
  362. package/packages/visualizer/example/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  363. package/packages/visualizer/example/specs/coffee/ordering/drink-price.dmn +24 -0
  364. package/packages/visualizer/example/specs/coffee/ordering/loyalty.feature +7 -0
  365. package/packages/visualizer/example/specs/coffee/ordering/ordering.feature +36 -0
  366. package/packages/visualizer/example/specs/coffee/ordering/payment.als +4 -0
  367. package/packages/visualizer/fixtures/failures/specs/coffee/ordering/cart.qnt +7 -0
  368. package/packages/visualizer/fixtures/failures/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  369. package/packages/visualizer/fixtures/failures/specs/coffee/ordering/drink-price.dmn +24 -0
  370. package/packages/visualizer/fixtures/failures/specs/coffee/ordering/loyalty.feature +7 -0
  371. package/packages/visualizer/fixtures/failures/specs/coffee/ordering/ordering.feature +36 -0
  372. package/packages/visualizer/fixtures/failures/specs/coffee/ordering/payment.als +4 -0
  373. package/packages/visualizer/fixtures/full/specs/coffee/ordering/cart.qnt +7 -0
  374. package/packages/visualizer/fixtures/full/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  375. package/packages/visualizer/fixtures/full/specs/coffee/ordering/drink-price.dmn +24 -0
  376. package/packages/visualizer/fixtures/full/specs/coffee/ordering/loyalty.feature +7 -0
  377. package/packages/visualizer/fixtures/full/specs/coffee/ordering/ordering.feature +36 -0
  378. package/packages/visualizer/fixtures/full/specs/coffee/ordering/payment.als +4 -0
  379. package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/cart.qnt +7 -0
  380. package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  381. package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/drink-price.dmn +24 -0
  382. package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/loyalty.feature +7 -0
  383. package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/ordering.feature +36 -0
  384. package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/payment.als +4 -0
  385. package/packages/visualizer/fixtures/partial/specs/coffee/ordering/cart.qnt +7 -0
  386. package/packages/visualizer/fixtures/partial/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  387. package/packages/visualizer/fixtures/partial/specs/coffee/ordering/drink-price.dmn +24 -0
  388. package/packages/visualizer/fixtures/partial/specs/coffee/ordering/loyalty.feature +7 -0
  389. package/packages/visualizer/fixtures/partial/specs/coffee/ordering/ordering.feature +36 -0
  390. package/packages/visualizer/fixtures/partial/specs/coffee/ordering/payment.als +4 -0
  391. package/packages/visualizer/fixtures/removed/specs/coffee/ordering/cart.qnt +7 -0
  392. package/packages/visualizer/fixtures/removed/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  393. package/packages/visualizer/fixtures/removed/specs/coffee/ordering/drink-price.dmn +24 -0
  394. package/packages/visualizer/fixtures/removed/specs/coffee/ordering/loyalty.feature +7 -0
  395. package/packages/visualizer/fixtures/removed/specs/coffee/ordering/ordering.feature +36 -0
  396. package/packages/visualizer/fixtures/removed/specs/coffee/ordering/payment.als +4 -0
  397. package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/cart.qnt +7 -0
  398. package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/checkout.openslo.yaml +10 -0
  399. package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/drink-price.dmn +24 -0
  400. package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/loyalty.feature +7 -0
  401. package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/ordering.feature +36 -0
  402. package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/payment.als +4 -0
  403. package/packages/visualizer/scripts/make-fixtures.ts +2 -0
  404. package/packages/visualizer/scripts/publish-data.ts +1 -2
  405. package/packages/visualizer/src/app/AppShell.tsx +9 -2
  406. package/packages/visualizer/src/app/report-sources.tsx +6 -4
  407. package/packages/visualizer/src/app/router.tsx +3 -3
  408. package/packages/visualizer/src/components/Header.module.css +35 -0
  409. package/packages/visualizer/src/components/Header.tsx +41 -4
  410. package/packages/visualizer/src/data/adapters/adapter.ts +5 -17
  411. package/packages/visualizer/src/data/adapters/index.ts +10 -1
  412. package/packages/visualizer/src/evidence/api.ts +14 -2
  413. package/packages/visualizer/src/evidence/artifacts.module.css +213 -0
  414. package/packages/visualizer/src/evidence/artifacts.tsx +272 -0
  415. package/packages/visualizer/src/evidence/check-detail.tsx +38 -4
  416. package/packages/visualizer/src/evidence/evidence-context.tsx +74 -12
  417. package/packages/visualizer/src/evidence/evidence.module.css +20 -0
  418. package/packages/visualizer/src/evidence/marks.tsx +2 -0
  419. package/packages/visualizer/src/evidence/overview.tsx +3 -3
  420. package/packages/visualizer/src/evidence/sources-panel.tsx +88 -34
  421. package/packages/visualizer/src/evidence/spec-page.tsx +23 -16
  422. package/packages/visualizer/src/find/Finder.tsx +1 -7
  423. package/packages/visualizer/src/find/open.ts +4 -0
  424. package/packages/visualizer/src/live/live-stream.ts +204 -0
  425. package/packages/visualizer/src/runtime.ts +19 -0
  426. package/packages/visualizer/src/state/ui-store.ts +6 -2
  427. package/packages/visualizer/vite/atlas-server-proxy.ts +36 -0
  428. package/packages/visualizer/vite/example-reports.ts +475 -0
  429. package/packages/visualizer/vite.config.ts +18 -2
@@ -1,50 +1,87 @@
1
- /** Commit-scoped definitions and independently produced evidence. */
1
+ /**
2
+ * @module Explorer data types
3
+ *
4
+ * The plain shapes the reports explorer shares between the store readers, the API routes and the viewer: a spec
5
+ * entry, a commit's spec inventory, the four result statuses, measurements, checks and parts. They are types only
6
+ * and carry no behaviour. The vocabulary matches the layer document (`docs/report-contract.md`): `status` is the
7
+ * closed set of four, everything else about a check is open.
8
+ */
9
+ /** Commit-scoped definitions and independently produced evidence. One spec of the outline a report is laid over. */
2
10
  export type SpecEntry = {
11
+ /** `specs/<path inside the specs directory>`. The `specPath` a check uses to say which spec it belongs to. */
3
12
  readonly path: string;
13
+ /** Groups specs in the viewer (by default the project's folder name). */
4
14
  readonly domain: string;
15
+ /** The notation: `gherkin`, `quint`, `dmn`, `alloy`, `openslo`, a file extension, or `document`. An open vocabulary. */
5
16
  readonly kind: string;
6
17
  readonly title: string;
18
+ /** A fingerprint of the spec's text, so a reader can warn when a spec changed since a layer recorded it. Opaque. */
7
19
  readonly fingerprint?: string;
8
20
  };
21
+ /** The specs of one commit. */
9
22
  export type SpecInventory = {
23
+ /** The 40-hex-digit commit. */
10
24
  readonly sha: string;
11
25
  readonly entries: readonly SpecEntry[];
12
26
  };
27
+ /** The four result statuses. The only closed vocabulary in the format: `not-run` is never a pass and `running` is not done. */
13
28
  export type EvidenceStatus = 'passed' | 'failed' | 'running' | 'not-run';
29
+ /** A number a check recorded. Exceeding `limit` is shown and never fails the check by itself. */
14
30
  export type EvidenceMeasurement = {
15
31
  readonly name: string;
16
32
  readonly value: number;
33
+ /** The unit of `value` and `limit`, such as `ms`. */
17
34
  readonly unit: string;
35
+ /** The allowance for `value`, in the same unit, when there is one. */
18
36
  readonly limit?: number;
19
37
  };
20
- export type EvidenceCheck = {
38
+ /** What a check may carry beyond its outcome. All optional and open: see docs/extending.md. */
39
+ export type EvidenceExtras = Partial<Pick<import('../../schema/src/layer.js').Check, 'tags' | 'labels' | 'links' | 'steps' | 'attachments' | 'annotations' | 'attempts' | 'extensions'>>;
40
+ /** One check of a part, as recorded. */
41
+ export type EvidenceCheck = EvidenceExtras & {
42
+ /** Stable across runs; the newer result replaces the older one only if both used the same id. */
21
43
  readonly id: string;
22
44
  readonly title: string;
23
45
  readonly status: EvidenceStatus;
46
+ /** Why the check has this status, for a person. */
24
47
  readonly detail: string;
48
+ /** The spec the check belongs to, as `specs/<path>`. */
25
49
  readonly specPath?: string;
26
50
  readonly measurements: readonly EvidenceMeasurement[];
51
+ /** How long the check took, when the producer measured it. */
52
+ readonly durationMs?: number;
27
53
  };
28
54
  /** `kind` is an open producer key; new parts need no protocol change. */
29
- export type ReportPart = {
55
+ export type ReportPart = EvidenceExtras & {
56
+ /** `modified`: recorded from a checkout with uncommitted changes; `unknown`: origin not captured. Advisory; never changes a status. */
30
57
  readonly freshness?: 'unknown' | 'modified';
58
+ /** String choices that make a result its own slot (a device, a seed). */
31
59
  readonly parameters?: Readonly<Record<string, string>>;
60
+ /** The commit the part was recorded at. */
32
61
  readonly sha: string;
62
+ /** The part's id; when the part is published it is the `producer` of the layer made from it. */
33
63
  readonly id: string;
64
+ /** Open category (`behavior`, `performance`, ...); part of the slot. */
34
65
  readonly kind: string;
35
66
  readonly title: string;
67
+ /** When the checks ran, epoch milliseconds. */
36
68
  readonly recordedAtMs: number;
37
69
  readonly checks: readonly EvidenceCheck[];
38
70
  };
71
+ /** The part of a {@link ReportPart} that a spec run's evidence file carries: its `kind`, `title` and `checks`. */
39
72
  export type ReportPartOutput = Pick<ReportPart, 'kind' | 'title' | 'checks'>;
73
+ /** What the explorer shows for one commit: its specs (or null when none were recorded) and the parts recorded against it. */
40
74
  export type ExplorerData = {
41
75
  readonly inventory: SpecInventory | null;
42
76
  readonly parts: readonly ReportPart[];
77
+ /** A message to show instead of data, when something could not be read. */
43
78
  readonly notice?: string;
44
79
  };
80
+ /** The checkout a workspace reads from. */
45
81
  export type WorkspaceVersion = {
46
82
  readonly sha: string;
47
83
  readonly branch: string;
84
+ /** True when the checkout has uncommitted changes. */
48
85
  readonly dirty: boolean;
49
86
  };
50
87
  /** Only composition roots provide checkout content; it is never CI evidence. */
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module Explorer data types
3
+ *
4
+ * The plain shapes the reports explorer shares between the store readers, the API routes and the viewer: a spec
5
+ * entry, a commit's spec inventory, the four result statuses, measurements, checks and parts. They are types only
6
+ * and carry no behaviour. The vocabulary matches the layer document (`docs/report-contract.md`): `status` is the
7
+ * closed set of four, everything else about a check is open.
8
+ */
@@ -1,4 +1,12 @@
1
1
  import type { ObjectStore } from './object-store.js';
2
- /** A per-version marker lets an independent producer appear without a spec run. */
2
+ /**
3
+ * Writes the marker `versions/<sha>.json` (`{"sha": "<sha>"}`) so an independent producer's commit appears without
4
+ * a spec run. Writing it again is harmless. Throws `Invalid commit` when `sha` is not a 40-hex-digit commit.
5
+ */
3
6
  export declare function recordExplorerVersion(store: ObjectStore, sha: string): Promise<void>;
7
+ /**
8
+ * Lists the commits that have a marker, in key order. Keys under `versions/` that are not `<40 hex>.json` are
9
+ * ignored. A marker that is missing at read time or whose content does not name its own sha is not skipped:
10
+ * it throws `Invalid explorer version`, so corrupt data fails visibly.
11
+ */
4
12
  export declare function listExplorerVersions(store: ObjectStore): Promise<readonly string[]>;
@@ -1,11 +1,28 @@
1
+ /**
2
+ * @module Explorer version markers
3
+ *
4
+ * Marker files `versions/<sha>.json` that list which commits a store has anything recorded for, so the explorer can
5
+ * show a commit that has parts or specs but no spec run. A store layout older than layers; the markers are small,
6
+ * immutable and idempotent to write, and are read in place by newer readers.
7
+ *
8
+ * @see docs/report-contract.md (stores written before layers existed)
9
+ */
1
10
  import { readUtf8, writeUtf8 } from './object-io.js';
2
11
  import { isCommitSha } from './keys.js';
3
- /** A per-version marker lets an independent producer appear without a spec run. */
12
+ /**
13
+ * Writes the marker `versions/<sha>.json` (`{"sha": "<sha>"}`) so an independent producer's commit appears without
14
+ * a spec run. Writing it again is harmless. Throws `Invalid commit` when `sha` is not a 40-hex-digit commit.
15
+ */
4
16
  export async function recordExplorerVersion(store, sha) {
5
17
  if (!isCommitSha(sha))
6
18
  throw new Error('Invalid commit');
7
19
  await writeUtf8(store, `versions/${sha}.json`, JSON.stringify({ sha }), 'application/json');
8
20
  }
21
+ /**
22
+ * Lists the commits that have a marker, in key order. Keys under `versions/` that are not `<40 hex>.json` are
23
+ * ignored. A marker that is missing at read time or whose content does not name its own sha is not skipped:
24
+ * it throws `Invalid explorer version`, so corrupt data fails visibly.
25
+ */
9
26
  export async function listExplorerVersions(store) {
10
27
  const versions = [];
11
28
  for (const key of await store.listKeys('versions/')) {
@@ -1,6 +1,21 @@
1
1
  import type { ObjectStore } from './object-store.js';
2
+ /**
3
+ * Maps a report API path (with its query) to the file an export stores it under, for example `/evidence?cursor=x`
4
+ * to `evidence/pages/x.json` and `/` to `index.json`. Files a layer carries (`/blobs/`, `/files/`, `frame.css`,
5
+ * `report.json`) keep their path so their type stays known by name; everything else gets `.json` appended. Pure.
6
+ */
2
7
  export declare function evidenceFile(path: string): string;
3
- /** Export the combined report, preserving layer provenance and lazy recording addresses. */
8
+ /**
9
+ * Exports the combined report, preserving layer provenance and lazy recording addresses.
10
+ *
11
+ * `args.fetch` answers report API paths (`/outline`, `/evidence?cursor=`, ...), for example the reports app's own
12
+ * `request`. Every response is stored in `args.target` under {@link evidenceFile}, each path once. A 404 or 503 for
13
+ * a path is recorded in `missing` and skipped; any other failure throws, as does a layer catalog that repeats a
14
+ * page. Live runs are left out and each execution is exported once. Nothing in `target` is deleted.
15
+ *
16
+ * @returns `revisions` (distinct commits among the exported layers), `layers` (layers exported) and `missing`
17
+ * (paths that were not there).
18
+ */
4
19
  export declare function exportEvidence(args: {
5
20
  fetch: (path: string) => Promise<Response>;
6
21
  target: ObjectStore;
@@ -1,21 +1,55 @@
1
+ /**
2
+ * @module Static export of a report
3
+ *
4
+ * Copies what a running reports API serves (outline, spec texts, layer pages, rows, per-result evidence, recorded
5
+ * files) into an {@link ObjectStore}, one file per URL, so the viewer can be hosted statically. {@link evidenceFile}
6
+ * is the single mapping from an API path to the exported file name; the exporter writes with it and a static host
7
+ * must read with it. Only collected layers are exported (a static site has no running suite).
8
+ */
1
9
  import { eachLimited } from './completion-order.js';
10
+ import { bundleKeysOf } from './evidence-detail.js';
2
11
  import { recordingPaths } from './evidence-types.js';
3
12
  import { distinctHeaders } from './layer-merge.js';
4
13
  import { writeUtf8 } from './object-io.js';
5
14
  import { capturedFiles } from './frames.js';
15
+ /**
16
+ * Maps a report API path (with its query) to the file an export stores it under, for example `/evidence?cursor=x`
17
+ * to `evidence/pages/x.json` and `/` to `index.json`. Files a layer carries (`/blobs/`, `/files/`, `frame.css`,
18
+ * `report.json`) keep their path so their type stays known by name; everything else gets `.json` appended. Pure.
19
+ */
6
20
  export function evidenceFile(path) {
7
21
  const url = new URL(path || '/', 'http://atlas');
8
22
  if (url.pathname === '/')
9
23
  return 'index.json';
10
24
  if (url.pathname === '/evidence' && url.searchParams.has('cursor'))
11
25
  return `evidence/pages/${encodeURIComponent(url.searchParams.get('cursor'))}.json`;
26
+ // One result's evidence: a file per result, named by its check (and kind), beside its layer's own.
27
+ const detail = /^\/evidence\/detail\/([^/]+)\/([^/]+)$/.exec(url.pathname);
28
+ if (detail) {
29
+ const check = url.searchParams.get('check');
30
+ const kind = url.searchParams.get('kind');
31
+ return `evidence/detail/${detail[1]}/${detail[2]}${check === null ? '' : `/${encodeURIComponent(check)}${kind ? `~${encodeURIComponent(kind)}` : ''}`}.json`;
32
+ }
33
+ // A file a layer carries: kept as it is, with its type known by its name.
34
+ if (url.pathname.includes('/blobs/'))
35
+ return url.pathname.slice(1);
12
36
  if (url.pathname.endsWith('/spec'))
13
37
  return `${url.pathname.slice(1, -5)}/specs/${encodeURIComponent(url.searchParams.get('path') ?? '')}.txt`;
14
38
  if (url.pathname.includes('/files/') || url.pathname.endsWith('/frame.css') || url.pathname.endsWith('/report.json'))
15
39
  return url.pathname.slice(1);
16
40
  return `${url.pathname.slice(1)}.json`;
17
41
  }
18
- /** Export the combined report, preserving layer provenance and lazy recording addresses. */
42
+ /**
43
+ * Exports the combined report, preserving layer provenance and lazy recording addresses.
44
+ *
45
+ * `args.fetch` answers report API paths (`/outline`, `/evidence?cursor=`, ...), for example the reports app's own
46
+ * `request`. Every response is stored in `args.target` under {@link evidenceFile}, each path once. A 404 or 503 for
47
+ * a path is recorded in `missing` and skipped; any other failure throws, as does a layer catalog that repeats a
48
+ * page. Live runs are left out and each execution is exported once. Nothing in `target` is deleted.
49
+ *
50
+ * @returns `revisions` (distinct commits among the exported layers), `layers` (layers exported) and `missing`
51
+ * (paths that were not there).
52
+ */
19
53
  export async function exportEvidence(args) {
20
54
  const missing = [];
21
55
  const copied = new Map();
@@ -67,6 +101,23 @@ export async function exportEvidence(args) {
67
101
  if (layer.sha)
68
102
  revisions.add(layer.sha);
69
103
  const rowsText = await copy(`/evidence/rows/${encodeURIComponent(layer.backend)}/${encodeURIComponent(layer.id)}`);
104
+ // Evidence a result carries: what it says, and every file it points to.
105
+ if (rowsText) {
106
+ const withEvidence = JSON.parse(rowsText).rows.filter(row => row.evidence);
107
+ const copyDetail = async (path) => {
108
+ const text = await copy(path);
109
+ if (!text)
110
+ return;
111
+ const read = JSON.parse(text);
112
+ const keys = new Set([...bundleKeysOf('check' in read ? read.check : {}), ...bundleKeysOf(read.run)]);
113
+ await eachLimited([...keys], 4, key => copy(`/layers/${encodeURIComponent(layer.id)}/blobs/${key.split('/').map(encodeURIComponent).join('/')}`).then(() => { }));
114
+ };
115
+ const base = `/evidence/detail/${encodeURIComponent(layer.backend)}/${encodeURIComponent(layer.id)}`;
116
+ if (layer.evidence)
117
+ await copyDetail(base);
118
+ for (const row of withEvidence)
119
+ await copyDetail(`${base}?check=${encodeURIComponent(row.id)}&kind=${encodeURIComponent(row.kind)}`);
120
+ }
70
121
  const recording = layer.recording;
71
122
  if (!rowsText || !recording)
72
123
  return;
@@ -1,9 +1,13 @@
1
1
  /**
2
- * Cacheable reads of a reports API. Commit pages, sources, stylesheets and
2
+ * @module Cacheable reads of a commit-keyed reports API
3
+ *
4
+ * The client side of the older, commit-addressed reports API (`/<sha>/explorer`, `/<sha>/spec`,
5
+ * `/<sha>/sources`, `/<sha>/tests/<source>/<testId>`, ...). Commit pages, sources, stylesheets and
3
6
  * test timelines go through TanStack Query. Frame files also land in
4
7
  * `ReportCache` (IndexedDB on the wall, a map in tests) so a scrub reads
5
8
  * bytes the browser already kept, without putting multi-megabyte HTML into
6
- * the query document.
9
+ * the query document. A 503 from the API means reports are not available and throws {@link ReportsUnavailable};
10
+ * a 404 for a spec, test or frame is answered as `null` (or an empty stylesheet), not an error.
7
11
  */
8
12
  import type { ExplorerData } from './explorer-types.js';
9
13
  import type { CommitPage, SourceRecord } from './protocol.js';
@@ -11,17 +15,24 @@ import type { HtmlReportBlob } from './recording-bundle.js';
11
15
  import type { RunReport } from './report-types.js';
12
16
  import type { HttpClient } from './http.js';
13
17
  import { QueryClient } from '@tanstack/solid-query';
18
+ /** Thrown when the reports API answers 503: no reports store is configured or reachable. Its message is `reports_unavailable`. */
14
19
  export declare class ReportsUnavailable extends Error {
15
20
  constructor();
16
21
  }
17
22
  /** String store the query persister and frame files share. */
18
23
  export type ReportCache = {
24
+ /** The saved value, or null when there is none. */
19
25
  get(key: string): Promise<string | null>;
26
+ /** Saves a value, replacing any under the key. */
20
27
  set(key: string, value: string): Promise<void>;
28
+ /** Forgets a key; a missing key is not an error. */
21
29
  remove(key: string): Promise<void>;
22
30
  };
31
+ /** A {@link ReportCache} held in a `Map`, lost on reload. For tests and hosts without persistent storage. */
23
32
  export declare function memoryReportCache(): ReportCache;
33
+ /** Creates the TanStack `QueryClient` the fetcher expects: results stay fresh 5 minutes, are kept 1 day, and are neither retried nor refetched on window focus. */
24
34
  export declare function reportQueryClient(): QueryClient;
35
+ /** The TanStack query keys of each read, so a host can invalidate or persist them. Every key starts with `reports`. */
25
36
  export declare const reportQueryKey: {
26
37
  commits: readonly ["reports", "commits"];
27
38
  explorer: (sha: string) => readonly ["reports", "explorer", string];
@@ -31,20 +42,33 @@ export declare const reportQueryKey: {
31
42
  test: (sha: string, source: string, testId: string) => readonly ["reports", "test", string, string, string];
32
43
  blob: (sha: string, source: string, testId: string, file: string) => readonly ["reports", "blob", string, string, string, string];
33
44
  };
45
+ /** The reads the explorer makes. Rejections are `ReportsUnavailable` (503) or an `Error` naming the HTTP status. */
34
46
  export type ReportFetcher = {
47
+ /** The specs and parts recorded for a commit. Never served from a stale query (always refetched). */
35
48
  explorer(sha: string): Promise<ExplorerData>;
49
+ /** The text of one spec of a commit, or null when it is not there. */
36
50
  spec(sha: string, path: string): Promise<string | null>;
51
+ /** One page of commits; pass the previous page's `cursor`, or null for the first page. */
37
52
  commits(cursor: string | null): Promise<CommitPage>;
53
+ /** The spec-run sources of a commit. */
38
54
  sources(sha: string): Promise<readonly SourceRecord[]>;
55
+ /** The stylesheet snapshots of a commit render with; empty when there is none. */
39
56
  frameCss(sha: string): Promise<string>;
57
+ /** One recorded test's report, or null when it is not there. */
40
58
  test(sha: string, source: string, testId: string): Promise<RunReport | null>;
59
+ /** One captured file of a test, or null when it is missing (a missing file is retried on the next call). Resolved from the `ReportCache` before the network. */
41
60
  blob(sha: string, source: string, testId: string, file: string): Promise<HtmlReportBlob | null>;
42
61
  };
62
+ /** What {@link createHttpReportFetcher} needs. */
43
63
  export type ReportFetcherArgs = {
64
+ /** The HTTP client used for every request. */
44
65
  readonly http: HttpClient;
66
+ /** The URL prefix of the reports API, prepended to each path with no added slash (for example `/api/reports`). */
45
67
  readonly apiBase: string;
68
+ /** The query cache; see {@link reportQueryClient}. */
46
69
  readonly client: QueryClient;
70
+ /** Where captured frame files are kept between visits. */
47
71
  readonly cache: ReportCache;
48
72
  };
49
- /** Query-cached reads. Frame files resolve from `cache` before the network. */
73
+ /** Creates a {@link ReportFetcher} over HTTP with query-cached reads. Frame files resolve from `cache` before the network. */
50
74
  export declare function createHttpReportFetcher(args: ReportFetcherArgs): ReportFetcher;
@@ -1,19 +1,25 @@
1
1
  /**
2
- * Cacheable reads of a reports API. Commit pages, sources, stylesheets and
2
+ * @module Cacheable reads of a commit-keyed reports API
3
+ *
4
+ * The client side of the older, commit-addressed reports API (`/<sha>/explorer`, `/<sha>/spec`,
5
+ * `/<sha>/sources`, `/<sha>/tests/<source>/<testId>`, ...). Commit pages, sources, stylesheets and
3
6
  * test timelines go through TanStack Query. Frame files also land in
4
7
  * `ReportCache` (IndexedDB on the wall, a map in tests) so a scrub reads
5
8
  * bytes the browser already kept, without putting multi-megabyte HTML into
6
- * the query document.
9
+ * the query document. A 503 from the API means reports are not available and throws {@link ReportsUnavailable};
10
+ * a 404 for a spec, test or frame is answered as `null` (or an empty stylesheet), not an error.
7
11
  */
8
12
  import { QueryClient } from '@tanstack/solid-query';
9
13
  const MINUTE = 60_000;
10
14
  const DAY = 24 * 60 * MINUTE;
15
+ /** Thrown when the reports API answers 503: no reports store is configured or reachable. Its message is `reports_unavailable`. */
11
16
  export class ReportsUnavailable extends Error {
12
17
  constructor() {
13
18
  super('reports_unavailable');
14
19
  this.name = 'ReportsUnavailable';
15
20
  }
16
21
  }
22
+ /** A {@link ReportCache} held in a `Map`, lost on reload. For tests and hosts without persistent storage. */
17
23
  export function memoryReportCache() {
18
24
  const map = new Map();
19
25
  return {
@@ -28,6 +34,7 @@ export function memoryReportCache() {
28
34
  },
29
35
  };
30
36
  }
37
+ /** Creates the TanStack `QueryClient` the fetcher expects: results stay fresh 5 minutes, are kept 1 day, and are neither retried nor refetched on window focus. */
31
38
  export function reportQueryClient() {
32
39
  return new QueryClient({
33
40
  defaultOptions: {
@@ -40,6 +47,7 @@ export function reportQueryClient() {
40
47
  },
41
48
  });
42
49
  }
50
+ /** The TanStack query keys of each read, so a host can invalidate or persist them. Every key starts with `reports`. */
43
51
  export const reportQueryKey = {
44
52
  commits: ['reports', 'commits'],
45
53
  explorer: (sha) => ['reports', 'explorer', sha],
@@ -142,7 +150,7 @@ function blobPath(sha, source, testId, file) {
142
150
  .join('/');
143
151
  return `/${sha}/tests/${encodeURIComponent(source)}/${encodeURIComponent(testId)}/files/${encoded}`;
144
152
  }
145
- /** Query-cached reads. Frame files resolve from `cache` before the network. */
153
+ /** Creates a {@link ReportFetcher} over HTTP with query-cached reads. Frame files resolve from `cache` before the network. */
146
154
  export function createHttpReportFetcher(args) {
147
155
  const { http, apiBase, client } = args;
148
156
  return {
@@ -1 +1,7 @@
1
+ /**
2
+ * @module Date formatting
3
+ *
4
+ * Formats epoch-millisecond timestamps for display in the viewer's locale.
5
+ */
6
+ /** Formats epoch milliseconds as a local date and time (`toLocaleString`); an empty string for 0 or missing, and the number as text if it cannot be formatted. */
1
7
  export declare function fmtDate(ms: number): string;
@@ -1,3 +1,9 @@
1
+ /**
2
+ * @module Date formatting
3
+ *
4
+ * Formats epoch-millisecond timestamps for display in the viewer's locale.
5
+ */
6
+ /** Formats epoch milliseconds as a local date and time (`toLocaleString`); an empty string for 0 or missing, and the number as text if it cannot be formatted. */
1
7
  export function fmtDate(ms) {
2
8
  if (!ms)
3
9
  return '';
@@ -1,7 +1,16 @@
1
+ /**
2
+ * @module Display formatting for recorded tests
3
+ *
4
+ * Small pure formatters the viewer uses to show durations, file names, action lines and captured blobs. Nothing
5
+ * here reads a store or the network; missing or unreadable input becomes a placeholder, never an exception.
6
+ */
1
7
  import type { HtmlReportTest } from './recording-bundle.js';
2
8
  import type { ReportSnapshotBlob } from './report-types.js';
9
+ /** Formats milliseconds compactly (`850ms`, `1.5s`, `2m 5s`); `—` for null, undefined or a non-finite number. */
3
10
  export declare function fmtMs(ms: number | null | undefined): string;
11
+ /** The last `/`-separated segment of a path; empty for no path. */
4
12
  export declare function fileName(path: string | undefined): string;
13
+ /** The group label for a test's source file: its base name, or `Other` when it has none. */
5
14
  export declare function fileLabel(sourceFile: string | undefined): string;
6
15
  /** Compact `arg, arg` for an action line. Empty when the step recorded none. */
7
16
  export declare function formatArgs(args: readonly unknown[] | undefined): string;
@@ -11,6 +20,13 @@ export declare function actionLabel(step: {
11
20
  readonly args?: readonly unknown[] | undefined;
12
21
  readonly title: string;
13
22
  }): string;
23
+ /**
24
+ * The text to show for a captured blob: binary blobs become a `(binary name, ~N bytes)` placeholder, JSON is
25
+ * pretty-printed (left as is if it does not parse), anything else is shown as stored, and `(missing)` when the
26
+ * test does not hold the blob's file.
27
+ */
14
28
  export declare function formatBlobBody(test: HtmlReportTest, blob: ReportSnapshotBlob): string;
29
+ /** The heading line of a blob: `name · nodeId · media`, without the node when it has none. */
15
30
  export declare function blobHeading(blob: ReportSnapshotBlob): string;
31
+ /** A `data:` URL for a blob stored as base64 bytes, or null when the test holds no such bytes (text blobs have none). */
16
32
  export declare function downloadUrl(test: HtmlReportTest, blob: ReportSnapshotBlob): string | null;
@@ -1,4 +1,5 @@
1
1
  import { blobDataUrl, blobText } from './frames.js';
2
+ /** Formats milliseconds compactly (`850ms`, `1.5s`, `2m 5s`); `—` for null, undefined or a non-finite number. */
2
3
  export function fmtMs(ms) {
3
4
  if (ms === null || ms === undefined || !Number.isFinite(ms))
4
5
  return '—';
@@ -8,9 +9,11 @@ export function fmtMs(ms) {
8
9
  return `${(ms / 1000).toFixed(1)}s`;
9
10
  return `${Math.floor(ms / 60000)}m ${Math.round((ms % 60000) / 1000)}s`;
10
11
  }
12
+ /** The last `/`-separated segment of a path; empty for no path. */
11
13
  export function fileName(path) {
12
14
  return path ? (path.split('/').pop() ?? '') : '';
13
15
  }
16
+ /** The group label for a test's source file: its base name, or `Other` when it has none. */
14
17
  export function fileLabel(sourceFile) {
15
18
  return sourceFile ? fileName(sourceFile) : 'Other';
16
19
  }
@@ -44,6 +47,11 @@ export function actionLabel(step) {
44
47
  return step.title;
45
48
  return `${step.action}(${formatArgs(step.args)})`;
46
49
  }
50
+ /**
51
+ * The text to show for a captured blob: binary blobs become a `(binary name, ~N bytes)` placeholder, JSON is
52
+ * pretty-printed (left as is if it does not parse), anything else is shown as stored, and `(missing)` when the
53
+ * test does not hold the blob's file.
54
+ */
47
55
  export function formatBlobBody(test, blob) {
48
56
  if (blob.media === 'bytes') {
49
57
  const bin = test.blobs[blob.file];
@@ -63,9 +71,11 @@ export function formatBlobBody(test, blob) {
63
71
  }
64
72
  return text;
65
73
  }
74
+ /** The heading line of a blob: `name · nodeId · media`, without the node when it has none. */
66
75
  export function blobHeading(blob) {
67
76
  return `${blob.name}${blob.nodeId ? ` · ${blob.nodeId}` : ''} · ${blob.media}`;
68
77
  }
78
+ /** A `data:` URL for a blob stored as base64 bytes, or null when the test holds no such bytes (text blobs have none). */
69
79
  export function downloadUrl(test, blob) {
70
80
  return blobDataUrl(test, blob);
71
81
  }
@@ -1,12 +1,24 @@
1
+ /**
2
+ * @module Frames of a recorded test
3
+ *
4
+ * Pure helpers over a recorded test's step tree: flattening it into time-ordered frames (captured snapshots),
5
+ * choosing the frame and actor a route selects, stepping to neighbouring frames or failures, and listing the files
6
+ * a report names. Results of `testFrames` and the per-actor orderings are cached per test, keyed by the identity of
7
+ * `test.report.steps`, so treat a loaded report as immutable. Nothing here reads a store.
8
+ */
1
9
  import type { HtmlReportTest } from './recording-bundle.js';
2
10
  import type { ReportFrame, ReportSnapshotBlob, ReportStep, RunReport } from './report-types.js';
3
11
  import type { Route } from './hash.js';
12
+ /** A frame placed in its step, in the flattened timeline. */
4
13
  export type FlatFrame = {
5
14
  step: ReportStep;
6
15
  frame: ReportFrame;
16
+ /** How deeply the step is nested (0 for a top-level step). */
7
17
  depth: number;
18
+ /** Position in the flattened list this frame came from; `testFrames` renumbers it by capture time. Route `frame=N` is `index + 1`. */
8
19
  index: number;
9
20
  };
21
+ /** A UI snapshot slot for one client (actor) of a frame. */
10
22
  export type OrderedUiBlob = {
11
23
  readonly nodeId: string;
12
24
  /** This frame's snapshot, or the client's latest earlier one when stale. */
@@ -14,31 +26,52 @@ export type OrderedUiBlob = {
14
26
  /** True when `blob` is carried forward from an earlier frame. */
15
27
  readonly stale: boolean;
16
28
  };
29
+ /** A step placed in the flattened (depth-first) step list. */
17
30
  export type FlatStep = {
18
31
  step: ReportStep;
19
32
  depth: number;
33
+ /** The enclosing step, or null for a top-level step. */
20
34
  parent: FlatStep | null;
21
35
  index: number;
22
36
  };
37
+ /** Flattens the frames of a step tree depth first (a step's own frames, then its children's), in step order, not capture-time order. Appends to `out`. */
23
38
  export declare function flattenFrames(steps: readonly ReportStep[], out?: FlatFrame[], depth?: number): FlatFrame[];
39
+ /** Flattens a step tree depth first into rows that know their depth and parent. Appends to `out`. */
24
40
  export declare function flattenSteps(steps: readonly ReportStep[], out?: FlatStep[], depth?: number, parent?: FlatStep | null): FlatStep[];
41
+ /** The first frame of `step`, or failing that of its first descendant that has one; null when none of them has a frame. */
25
42
  export declare function firstFrameFor(step: ReportStep, frames: readonly FlatFrame[]): FlatFrame | null;
43
+ /** The last frame (in list order, which should be capture-time order) captured at or before the step ended; null when none was. */
26
44
  export declare function lastFrameBefore(step: ReportStep, frames: readonly FlatFrame[]): FlatFrame | null;
45
+ /** All frames of a test in capture-time order (ties keep step order), each numbered by its position. Cached per report. */
27
46
  export declare function testFrames(test: HtmlReportTest): FlatFrame[];
28
- /** Return UI snapshots in one stable actor order, including empty slots. */
47
+ /**
48
+ * Returns a frame's UI snapshots (html or png) in one stable actor order, including empty slots, so each client
49
+ * stays in the same column from frame to frame. The order is the report's `meta.actorIds`, then any other client in
50
+ * the order first seen. A client with no snapshot at this frame carries its latest earlier one (`stale: true`), or
51
+ * `null` blob if it has none yet. Snapshots with no `nodeId` follow, named `snapshot-N`.
52
+ */
29
53
  export declare function orderedUiBlobs(frame: FlatFrame | null, test: HtmlReportTest): OrderedUiBlob[];
54
+ /** The frame a route selects: the 1-based `frame` param when in range, otherwise the first frame of a failed step, otherwise the last frame; null with no frames. */
30
55
  export declare function selectedFrame(frames: readonly FlatFrame[], route: Route): FlatFrame | null;
31
- /** Every file a report names: step snapshots, and files attached to the test as a whole. */
56
+ /** Every distinct file a report names, relative to the test's folder: step snapshots, and files attached to the test as a whole (artifacts with their poster and captions). Used to know what to copy or prefetch. */
32
57
  export declare function capturedFiles(report: Pick<RunReport, 'steps' | 'artifacts'>): string[];
58
+ /** Whether a snapshot is a rendered user interface (`html` or `png`), as opposed to data such as JSON or text. */
33
59
  export declare function isUi(b: ReportSnapshotBlob): boolean;
60
+ /** The UI snapshots (html or png) of a frame; empty for no frame. */
34
61
  export declare function uiBlobs(frame: FlatFrame | null): ReportSnapshotBlob[];
62
+ /** All snapshots of a frame of any media; empty for no frame. */
35
63
  export declare function stageBlobs(frame: FlatFrame | null): ReportSnapshotBlob[];
64
+ /** Whether a frame has at least one UI snapshot. */
36
65
  export declare function frameHasUi(frame: FlatFrame | null): boolean;
37
- /** Frame files around `index` (the visible one, plus neighbors) to fetch ahead. */
66
+ /** The distinct html, png, json and text files of the frames within `radius` of `index` (the visible one plus neighbors, clamped to the list), to fetch ahead. */
38
67
  export declare function frameFilesNear(frames: readonly FlatFrame[], index: number, radius: number): readonly string[];
68
+ /** The clients (actors) to show for a frame: those with a UI snapshot, else those with any snapshot, else the report's declared `meta.actorIds`. */
39
69
  export declare function actorIds(frame: FlatFrame | null, test: HtmlReportTest): string[];
70
+ /** The client a route selects: the `node` param when it is one of the frame's actors, else the frame's step actor, else the first actor; null with none. */
40
71
  export declare function selectedNode(frame: FlatFrame | null, route: Route, test: HtmlReportTest): string | null;
72
+ /** The text of a blob the test holds as text, or null when it is missing or held as bytes. */
41
73
  export declare function blobText(test: HtmlReportTest, blob: ReportSnapshotBlob): string | null;
74
+ /** A `data:` URL for a blob the test holds as base64 bytes, or null when it is missing or held as text. */
42
75
  export declare function blobDataUrl(test: HtmlReportTest, blob: ReportSnapshotBlob): string | null;
43
76
  /** Whether any frame of `step` (not its children) shows a press target. */
44
77
  export declare function stepHasPress(step: ReportStep): boolean;