@crvouga/atlas 0.4.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 (379) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +178 -617
  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 +35 -5
  94. package/dist/reports/src/evidence-live.js +18 -2
  95. package/dist/reports/src/evidence-types.d.ts +68 -1
  96. package/dist/reports/src/evidence-types.js +5 -1
  97. package/dist/reports/src/evidence-view.d.ts +43 -4
  98. package/dist/reports/src/evidence-view.js +13 -2
  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 +35 -5
  134. package/dist/reports/src/layer-axes.js +25 -5
  135. package/dist/reports/src/layer-catalog.d.ts +28 -1
  136. package/dist/reports/src/layer-catalog.js +18 -1
  137. package/dist/reports/src/layer-merge.d.ts +98 -9
  138. package/dist/reports/src/layer-merge.js +147 -31
  139. package/dist/reports/src/layer-source.d.ts +18 -0
  140. package/dist/reports/src/layer-source.js +11 -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 +32 -1
  144. package/dist/reports/src/layers-route.d.ts +47 -4
  145. package/dist/reports/src/layers-route.js +86 -7
  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 +26 -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 +42 -9
  175. package/dist/reports/src/publish.js +36 -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 +37 -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 +32 -4
  329. package/packages/core/README.md +2 -1
  330. package/packages/reports/README.md +65 -0
  331. package/packages/reports/STORAGE.md +4 -0
  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 +21 -0
  361. package/packages/visualizer/src/app/AppShell.tsx +9 -2
  362. package/packages/visualizer/src/app/report-sources.tsx +6 -4
  363. package/packages/visualizer/src/app/router.tsx +3 -3
  364. package/packages/visualizer/src/components/Header.module.css +35 -0
  365. package/packages/visualizer/src/components/Header.tsx +40 -3
  366. package/packages/visualizer/src/data/adapters/adapter.ts +5 -17
  367. package/packages/visualizer/src/data/adapters/index.ts +10 -1
  368. package/packages/visualizer/src/evidence/api.ts +14 -2
  369. package/packages/visualizer/src/evidence/artifacts.module.css +213 -0
  370. package/packages/visualizer/src/evidence/artifacts.tsx +272 -0
  371. package/packages/visualizer/src/evidence/check-detail.tsx +3 -1
  372. package/packages/visualizer/src/evidence/evidence-context.tsx +74 -12
  373. package/packages/visualizer/src/evidence/spec-page.tsx +23 -16
  374. package/packages/visualizer/src/find/Finder.tsx +1 -7
  375. package/packages/visualizer/src/find/open.ts +4 -0
  376. package/packages/visualizer/src/live/live-stream.ts +204 -0
  377. package/packages/visualizer/src/runtime.ts +19 -0
  378. package/packages/visualizer/vite/atlas-server-proxy.ts +36 -0
  379. package/packages/visualizer/vite.config.ts +11 -3
@@ -0,0 +1,45 @@
1
+ # Reference: vitest
2
+
3
+ Run a statechart plan as Vitest tests. Import path `@crvouga/atlas/vitest`.
4
+
5
+ > Generated from the doc comments of `packages/vitest/src` by `bun run docs`. Do not edit: change the comment next to the code.
6
+
7
+ ### Test-runner adapter
8
+
9
+ Source: `packages/vitest/src/index.ts`. Import: `@crvouga/atlas/vitest`
10
+
11
+ Runs an Atlas config as a test suite in Vitest, `bun test` or any Jest-style runner. The runner's own
12
+ `describe`, `it`, `beforeAll` and `expect` are passed in, so this module imports no test framework
13
+ and never touches global test state. It owns the mapping from planned paths to tests; the run itself
14
+ is `runConfig` from the core.
15
+
16
+ #### `describeAtlas`
17
+
18
+ ```ts
19
+ export function describeAtlas<C>(config: AtlasConfig<C>, suite: Suite, options: RunCommandOptions & { baseDirectory?: string; timeoutMs?: number } = {})
20
+ ```
21
+
22
+ Registers a test suite for an Atlas config: one test that the charts are executable (no structural
23
+ lint finding), then one test per planned path, so any Vitest/Jest-style runner reports each journey
24
+ and generated path on its own. The whole plan runs once in `beforeAll` (paths share one manifest);
25
+ each test then reads its path's outcome. A failed path fails its test with the last attempt's error;
26
+ `passed` and `flaky` paths pass; a path that was `not-reached` (blocked by an event with no
27
+ implementation) or was not part of the run passes quietly.
28
+
29
+ `prepare` runs synchronously when `describeAtlas` is called, so specs that cannot be loaded throw at
30
+ collection time. The run writes its output like `atlas run` does.
31
+
32
+ - `config`: the Atlas config to run.
33
+
34
+ - `suite`: the runner's `describe`, `it`, `beforeAll` and `expect`.
35
+
36
+ - `options`: the `atlas run` options (`mode`, `paths`, `retry`, `output`, `log`, ...);
37
+ `baseDirectory` resolves relative config paths (the current directory when omitted) and `timeoutMs`
38
+ bounds the `beforeAll` (30 minutes by default). Progress lines are discarded unless `log` is given.
39
+
40
+ **Example**
41
+
42
+ ```ts
43
+ import { beforeAll, describe, expect, it } from 'bun:test';
44
+ describeAtlas(config, { describe, it, beforeAll, expect });
45
+ ```
@@ -0,0 +1,330 @@
1
+ # Reference: webdriver
2
+
3
+ The W3C WebDriver / Appium driver for statechart runs. Import path `@crvouga/atlas/webdriver`.
4
+
5
+ > Generated from the doc comments of `packages/webdriver/src` by `bun run docs`. Do not edit: change the comment next to the code.
6
+
7
+ ### WebDriver driver
8
+
9
+ Source: `packages/webdriver/src/driver.ts`
10
+
11
+ The Atlas driver for anything that speaks W3C WebDriver: browsers through their driver binary
12
+ (safaridriver, chromedriver, geckodriver, msedgedriver) and native iOS and Android apps through
13
+ Appium. It owns starting (or connecting to) the WebDriver server, opening sessions, resolving
14
+ signals and raw locators to elements, and logging taps and typing to the step timeline; the
15
+ protocol calls themselves live in `./protocol`. It requires a reachable WebDriver server (`url`) or a
16
+ server binary on the `PATH` (`server`), and FFmpeg on the `PATH` for clips encoded from
17
+ screenshots. A session or server that cannot start rejects the attempt that needed it.
18
+
19
+ #### `Target`
20
+
21
+ ```ts
22
+ export type Target = Signal | Locator;
23
+ ```
24
+
25
+ What a step points at: a signal (resolved per platform) or a raw WebDriver locator.
26
+
27
+ #### `Mode`
28
+
29
+ ```ts
30
+ export type Mode = 'web' | 'native';
31
+ ```
32
+
33
+ How signals are resolved: `web` evaluates a DOM probe in the page, `native` queries the accessibility tree (an Appium session).
34
+
35
+ #### `WebDriverContext`
36
+
37
+ ```ts
38
+ export type WebDriverContext = SignalContext & {
39
+ /** The open WebDriver session, for protocol calls the context does not wrap (`session.execute`, `session.command`). */
40
+ session: WebDriverSession;
41
+ /** Whether signals resolve in the DOM (`web`) or the accessibility tree (`native`). */
42
+ mode: Mode;
43
+ /** What `goto` resolves paths against; undefined when the options set no `baseUrl`. */
44
+ baseUrl: string | undefined;
45
+ /** Navigate, relative to `baseUrl` (a deep link in a native session). Without a `baseUrl` the URL is sent as given. */
46
+ goto(url: string): Promise<void>;
47
+ /** The id of the first visible element a target resolves to, or null. Does not wait. */
48
+ find(target: Target): Promise<string | null>;
49
+ /** Whether the target resolves to a visible element right now. Does not wait; resolution errors count as not visible. */
50
+ isVisible(target: Target): Promise<boolean>;
51
+ /** Actions a person does; each is added to the step timeline (with the element's centre as the tap position) and then performed. */
52
+ user: {
53
+ /** Clicks the target's element, polling up to `actionTimeoutMs` for it to appear; throws `<target> is not on screen` otherwise. `label` is the caption. */
54
+ tap(target: Target, label: string): Promise<void>;
55
+ /** Clicks the target's element to focus it, then sends `text` as keys (it does not clear existing text); waits and throws like `tap`. */
56
+ type(target: Target, text: string, label: string): Promise<void>;
57
+ };
58
+ };
59
+ ```
60
+
61
+ What every event and recogniser receives from `webdriverDriver`: the open session plus a
62
+ `SignalContext` whose targets may also be raw locators. It is created per attempt (or once per run
63
+ with `session: 'per-run'`) and carries the actions that are logged to the step timeline.
64
+
65
+ #### `WebDriverServer`
66
+
67
+ ```ts
68
+ export type WebDriverServer = {
69
+ /** The server binary: `safaridriver`, `chromedriver`, `geckodriver`, `appium`. */
70
+ command: string;
71
+ /** `{port}` is replaced with the port. Defaults: `--port {port}` (`--port={port}` for chromedriver and msedgedriver). */
72
+ args?: string[];
73
+ /** The port to listen on; a free port on 127.0.0.1 is picked when omitted. */
74
+ port?: number;
75
+ /** How long to wait for the server to answer `GET /status` as ready, in milliseconds (default 30 000). */
76
+ readyTimeoutMs?: number;
77
+ };
78
+ ```
79
+
80
+ A WebDriver server binary the driver starts for the run and kills when the driver is disposed.
81
+
82
+ #### `WebDriverDriverOptions`
83
+
84
+ ```ts
85
+ export type WebDriverDriverOptions = {
86
+ /** A running WebDriver server (for example `http://127.0.0.1:4723` for Appium); or set `server` to start one for the run. */
87
+ url?: string;
88
+ /** A server to start for the run; used when `url` is not set. The driver throws on first use if neither is set. */
89
+ server?: WebDriverServer;
90
+ /** W3C capabilities (`alwaysMatch`), e.g. `{ browserName: 'safari' }` or Appium's `platformName`, `appium:app`. */
91
+ capabilities: Record<string, unknown>;
92
+ /** `web` resolves signals in the DOM; `native` resolves them in the accessibility tree. Inferred from the capabilities. */
93
+ mode?: Mode;
94
+ /** Where `goto` paths resolve; the implementation's setup decides where to open. */
95
+ baseUrl?: string | (() => string | Promise<string>);
96
+ /** `per-attempt` (default) starts a fresh session (browser or app) for every path attempt; `per-run` reuses one. */
97
+ session?: 'per-attempt' | 'per-run';
98
+ /** Clips: `frames` (default) encodes screenshots with FFmpeg; `appium` uses Appium's screen recorder; `none`. */
99
+ recording?: 'frames' | 'appium' | 'none';
100
+ /** How long a tap waits for its target, in milliseconds (default 15 000). */
101
+ actionTimeoutMs?: number;
102
+ /** The driver's name in reports; `webdriver:<platformName>` for native sessions, else `webdriver:<browserName>`, when omitted. */
103
+ name?: string;
104
+ /** Pauses around actions in showcase mode, in milliseconds; 400 before and 900 after when omitted. */
105
+ pacing?: { before: number; after: number };
106
+ /**
107
+ * Sessions open at once (one per worker): raise it for a grid or several devices. 1 when
108
+ * omitted, and always 1 with a per-run session.
109
+ */
110
+ concurrency?: number;
111
+ };
112
+ ```
113
+
114
+ Options of `webdriverDriver`. `capabilities` and one of `url` or `server` are required.
115
+
116
+ #### `nativeLocator`
117
+
118
+ ```ts
119
+ export function nativeLocator(signal: Signal): Locator | null
120
+ ```
121
+
122
+ Translates a signal into an Appium locator: a test ID becomes an `accessibility id`; text, labels
123
+ and roles become an XPath over the label, name, value, text and content-desc attributes (a
124
+ substring match unless `exact`), with a role narrowed to the matching XCUITest and UiAutomator2
125
+ element types.
126
+
127
+ **Returns** the locator, or null when the signal matches by regular expression, which XPath 1.0
128
+ cannot express (the driver then matches it against the page source instead).
129
+
130
+ **Throws** Error for a `css` signal, which only works in web sessions.
131
+
132
+ #### `webdriverDriver`
133
+
134
+ ```ts
135
+ export function webdriverDriver(options: WebDriverDriverOptions): Driver<WebDriverContext>
136
+ ```
137
+
138
+ Creates a driver for anything that speaks W3C WebDriver: Safari (safaridriver ships with macOS),
139
+ Chrome, Firefox and Edge, or a native iOS or Android app through Appium. Signals resolve in the
140
+ DOM for web sessions and in the accessibility tree for native ones (test IDs are accessibility
141
+ identifiers), so one implementation style covers both. Screenshots and the page source are
142
+ standard; clips are encoded from screenshots (FFmpeg on the `PATH`), or come from Appium's screen
143
+ recorder.
144
+
145
+ The WebDriver server is started lazily on the first attempt (`options.server`) or used as is
146
+ (`options.url`); `dispose()` deletes the shared session and kills a server this driver started.
147
+ With `session: 'per-attempt'` each attempt opens and deletes its own session. A server that exits
148
+ or is not ready in time, and a session the server refuses, reject the attempt that needed them.
149
+
150
+ - `options`: the server, capabilities and behaviour; see `WebDriverDriverOptions`.
151
+
152
+ **Returns** a driver whose context is a `WebDriverContext`.
153
+
154
+ **Throws** Error on the first attempt when neither `options.url` nor `options.server` is set.
155
+
156
+ **Example**
157
+
158
+ ```ts
159
+ const driver = webdriverDriver({
160
+ server: { command: 'chromedriver' },
161
+ capabilities: { browserName: 'chrome', 'goog:chromeOptions': { args: ['--headless=new'] } },
162
+ baseUrl: 'http://localhost:3000'
163
+ });
164
+ ```
165
+
166
+ #### `screen`
167
+
168
+ ```ts
169
+ export const screen = …
170
+ ```
171
+
172
+ Builds a state implementation recognised from signals or raw locators: every `all` target visible,
173
+ one of `any` (when given) and none of `none`. `checks` pair a statement from the state's
174
+ `meta.checks` with the target that proves it. A target whose lookup throws counts as not visible.
175
+
176
+ **Example**
177
+
178
+ ```ts
179
+ states: { 'Visit booked': screen({ all: [text('Booked for')], none: [accessibilityId('book-button')] }) }
180
+ ```
181
+
182
+ ### WebDriver driver entry point
183
+
184
+ Source: `packages/webdriver/src/index.ts`. Import: `@crvouga/atlas/webdriver`
185
+
186
+ Public surface of `@crvouga/atlas/webdriver`: the driver (`webdriverDriver`), the protocol client
187
+ (`WebDriverSession`), the shared UI signals, and builders for raw locators that only Appium
188
+ understands. Requires a WebDriver server at run time; importing it has no side effects.
189
+
190
+ #### `accessibilityId`
191
+
192
+ ```ts
193
+ export const accessibilityId = …
194
+ ```
195
+
196
+ Appium: an accessibility identifier (iOS) or content description (Android); React Native's `testID`.
197
+
198
+ #### `xpath`
199
+
200
+ ```ts
201
+ export const xpath = …
202
+ ```
203
+
204
+ An XPath 1.0 expression over the page or Appium source tree.
205
+
206
+ #### `iosPredicate`
207
+
208
+ ```ts
209
+ export const iosPredicate = …
210
+ ```
211
+
212
+ Appium iOS: an NSPredicate over the element tree, e.g. `label == "Book" AND type == "XCUIElementTypeButton"`.
213
+
214
+ #### `androidUiAutomator`
215
+
216
+ ```ts
217
+ export const androidUiAutomator = …
218
+ ```
219
+
220
+ Appium Android: a UiSelector expression, e.g. `new UiSelector().text("Book")`.
221
+
222
+ ### WebDriver protocol client
223
+
224
+ Source: `packages/webdriver/src/protocol.ts`
225
+
226
+ A dependency-free client for the W3C WebDriver protocol (https://www.w3.org/TR/webdriver2/), the
227
+ standard every browser driver speaks (safaridriver, chromedriver, geckodriver, msedgedriver) and
228
+ Appium extends for native iOS and Android apps. It only speaks HTTP+JSON through the global
229
+ `fetch`: it neither starts servers nor knows about Atlas signals (that is `./driver`). Every call
230
+ has a timeout and rejects with a `WebDriverError` when the server reports an error.
231
+
232
+ #### `ELEMENT_KEY`
233
+
234
+ ```ts
235
+ export const ELEMENT_KEY = …
236
+ ```
237
+
238
+ The W3C web element identifier key: the property under which a server sends an element id in an element reference.
239
+
240
+ #### `Locator`
241
+
242
+ ```ts
243
+ export type Locator = { using: string; value: string; name?: string };
244
+ ```
245
+
246
+ A location strategy and value. W3C strategies: `css selector`, `xpath`, `link text`,
247
+ `partial link text`, `tag name`. Appium adds `accessibility id`, `id`, `class name`,
248
+ `-ios predicate string`, `-ios class chain` and `-android uiautomator`.
249
+
250
+ #### `WebDriverError`
251
+
252
+ ```ts
253
+ export class WebDriverError extends Error
254
+ ```
255
+
256
+ The error a WebDriver server reports for a command, or `invalid response` when its answer is not
257
+ JSON. The message reads `<code>: <message>`. Network failures and timeouts are not wrapped: they
258
+ reject with the error `fetch` raised.
259
+
260
+ - `readonly code: string;` — The W3C error code, such as `no such element`, `stale element reference` or `invalid session id`; `unknown error` when the server gave none.
261
+ - `readonly status: number;` — The HTTP status of the response.
262
+
263
+ #### `Rect`
264
+
265
+ ```ts
266
+ export type Rect = { x: number; y: number; width: number; height: number };
267
+ ```
268
+
269
+ An element's position and size as the server reports it (`x` and `y` are the top-left corner).
270
+
271
+ #### `WebDriverSession`
272
+
273
+ ```ts
274
+ export class WebDriverSession
275
+ ```
276
+
277
+ One WebDriver session: a browser window or an Appium app on a device. Each method is one W3C
278
+ command (or a small combination) sent to `<serverUrl>/session/<id>/...`. Create it with
279
+ `WebDriverSession.create`; end it with `delete()`. Every method rejects with a `WebDriverError`
280
+ when the server refuses the command (for example `no such element` or `stale element reference`).
281
+ Elements are passed as the element id strings `findElements` returns.
282
+
283
+ **Example**
284
+
285
+ ```ts
286
+ const session = await WebDriverSession.create('http://127.0.0.1:4444', { browserName: 'chrome' });
287
+ await session.navigate('http://localhost:3000');
288
+ const [button] = await session.findElements({ using: 'css selector', value: '#book' });
289
+ if (button) await session.click(button);
290
+ await session.delete();
291
+ ```
292
+
293
+ - `readonly serverUrl: string;` — The server's base URL, without a trailing slash.
294
+ - `readonly id: string;` — The session id the server assigned.
295
+ - `readonly capabilities: Record<string, unknown>;` — The capabilities the server matched for this session (empty if it returned none).
296
+ - `timeoutMs: number;` — How long each command may take before it is aborted, in milliseconds (60 000 by default). Writable.
297
+ - `static async create(serverUrl: string, capabilities: Record<string, unknown>, timeoutMs = 120_000)` — Starts a session (New Session) with `capabilities` as `alwaysMatch`. - `serverUrl`: base URL of the WebDriver server, such as `http://127.0.0.1:4444`. - `timeoutMs`: how long New Session may take (default 120 000), since starting a browser or app is slow; later commands use the session's own `timeoutMs`. **Throws** WebDriverError when the server cannot match the capabilities or start the session.
298
+ - `command(method: 'GET' | 'POST' | 'DELETE', path: string, body?: unknown)` — Sends any command to this session, for what this client does not wrap (extensions such as `/appium/start_recording_screen`). - `path`: the command path after `/session/<id>`, starting with `/`. - `body`: the JSON body; a POST without one sends `{}` as the standard requires, GET and DELETE send none. **Returns** the response's `value`.
299
+ - `async navigate(url: string)` — Navigates to a URL (Navigate To) and resolves when the server answers (the page load strategy decides how long that takes). In a native session this is how a deep link is opened.
300
+ - `async currentUrl()` — The current URL (Get Current URL).
301
+ - `async refresh()` — Reloads the page (Refresh).
302
+ - `async back()` — Goes back in the history (Back).
303
+ - `async findElements(locator: Locator)` — The ids of every element matching the locator, (Find Elements); empty when none match.
304
+ - `async isDisplayed(element: string)` — Whether the element is shown (the `displayed` endpoint, which browser drivers and Appium implement).
305
+ - `async rect(element: string)` — The element's position and size (Get Element Rect).
306
+ - `async click(element: string)` — Clicks or taps the element (Element Click).
307
+ - `async clear(element: string)` — Clears an editable element (Element Clear).
308
+ - `async sendKeys(element: string, text: string)` — Types `text` into the element (Element Send Keys).
309
+ - `async elementText(element: string)` — The element's rendered text (Get Element Text).
310
+ - `async execute(script: string, args: unknown[] = [])` — Runs a JavaScript function body in the page (Execute Script, web contexts only) and returns its result. `args` are available as `arguments`; an element reference in an argument or result uses the W3C element key (see `elementId` to read one).
311
+ - `elementId(value: unknown)` — The element id inside an element reference returned by `execute`, or null when `value` is not one.
312
+ - `async source()` — The page source (Get Page Source): the HTML of a web page, or the XML element tree of a native app under Appium.
313
+ - `async screenshot()` — A screenshot of the viewport or screen (Take Screenshot), decoded from base64 to PNG bytes.
314
+ - `async tapAt(x: number, y: number)` — A tap at viewport coordinates through W3C Actions (a touch pointer).
315
+ - `async delete()` — Ends the session (Delete Session), closing its browser window or app session.
316
+
317
+ #### `waitForServer`
318
+
319
+ ```ts
320
+ export async function waitForServer(serverUrl: string, timeoutMs = 30_000)
321
+ ```
322
+
323
+ Waits until a WebDriver server answers `GET /status` as ready, polling every 250 ms (a server
324
+ that reports no `ready` field counts as ready).
325
+
326
+ - `serverUrl`: base URL of the server.
327
+
328
+ - `timeoutMs`: how long to keep polling (default 30 000).
329
+
330
+ **Throws** Error naming the last failure when the deadline passes.
@@ -0,0 +1,144 @@
1
+ # Report backends and live snapshots
2
+
3
+ > [!NOTE]
4
+ > Atlas has two kinds of backend, and this page is about the first.
5
+ >
6
+ > - **Run sources** (this page): where the viewer finds *statechart runs* (`manifest.json` per run)
7
+ > and live snapshots of a run in progress: a directory, HTTP files, or an HTTP API.
8
+ > - **Layer stores**: where *layers of evidence for any kind of spec* are kept, an `ObjectStore`
9
+ > such as a directory or a bucket. Any number of them are one report. See
10
+ > [the report contract](report-contract.md#backends) and [integrating Atlas](integrating.md).
11
+ >
12
+ > Publish a run as a layer (`atlas report publish --manifest`) to have it combine with other suites,
13
+ > environments and branches.
14
+
15
+ Atlas maps the product's areas, screens, events and journeys from a spec, then overlays evidence
16
+ of what the product did. Specs and reports are independent. Local development, CI, device labs
17
+ and hosted runners can supply reports to the same product atlas simultaneously. The viewer works
18
+ before the first report exists.
19
+
20
+ ## Connect sources
21
+
22
+ The default source is the directory passed to `--runs`. Add sources with a JSON file:
23
+
24
+ ```json
25
+ {
26
+ "schemaVersion": 1,
27
+ "sources": [
28
+ { "id": "mobile", "label": "Mobile runs", "type": "directory", "runs": "./mobile-runs" },
29
+ { "id": "ci", "label": "CI reports", "type": "http", "baseUrl": "https://reports.example.com/atlas-data/" },
30
+ { "id": "runner", "label": "Hosted runner", "type": "api", "baseUrl": "https://runner.example.com/atlas/", "eventsUrl": "events", "pollMs": 10000 }
31
+ ]
32
+ }
33
+ ```
34
+
35
+ ```sh
36
+ atlas-visualizer dev --specs ./specs --runs ./atlas-runs --sources ./atlas.sources.json
37
+ atlas-visualizer build --specs ./specs --runs ./atlas-runs --sources ./atlas.sources.json --out ./atlas-site
38
+ atlas-visualizer publish-data --specs ./specs --runs ./atlas-runs --sources ./atlas.sources.json --out ./atlas-data
39
+ ```
40
+
41
+ Directory paths resolve against the configuration file. Source ids are unique, stable names
42
+ containing letters, numbers, underscores or hyphens. `workspace` is reserved for `--runs`.
43
+ `ATLAS_SOURCES_FILE` is the environment equivalent. Restart dev after changing the file.
44
+ Credentials must not appear in this file or URLs: descriptors are sent to the browser and
45
+ included in static output.
46
+
47
+ Remote services must allow requests
48
+ from the viewer's origin. For private services, use an authenticated same-origin gateway. Atlas
49
+ does not download private GitHub artifacts or sign object-storage requests itself: expose their
50
+ published data over HTTP or implement a gateway using the contract below.
51
+
52
+ ## Transport contracts
53
+
54
+ | Backend | Index | Snapshot | Media and other reports | Updates |
55
+ | --- | --- | --- | --- | --- |
56
+ | Directory | Generated from run directories | `<run>/manifest.json` | Files beside the manifest | File watcher and polling fallback |
57
+ | HTTP files | `runs/index.json` | `runs/<id>/manifest.json` | `runs/<id>/<path>` | Polling; optional server events |
58
+ | HTTP API | `runs` | `runs/<id>/manifest` | `runs/<id>/files/<path>` | Polling; optional server events |
59
+
60
+ Locations are relative to `baseUrl`. The index follows the Atlas runs-index contract:
61
+
62
+ ```json
63
+ {
64
+ "runs": [{
65
+ "id": "build-123",
66
+ "startedAt": "2026-10-09T11:59:00Z",
67
+ "progress": "running",
68
+ "hasManifest": true,
69
+ "execution": {
70
+ "totalPaths": 8,
71
+ "completedPaths": 2,
72
+ "activePaths": ["journey-3"],
73
+ "updatedAt": "2026-10-09T12:00:00Z"
74
+ }
75
+ }]
76
+ }
77
+ ```
78
+
79
+ Each manifest is a full snapshot of everything received so far, rather than a patch or unfinished
80
+ JSON document. Records can be absent; malformed records are reported individually. Set
81
+ `run.finishedAt` to `null` while running, then a timestamp when complete. Its absence preserves
82
+ the meaning of older completed reports. Optional `run.progress` has the same shape as `execution`
83
+ above. Paths can declare `progress: queued | running | complete`.
84
+
85
+ Unvisited `not-reached` records appear pending during an active run. Passed and failed records
86
+ appear immediately. A PNG can arrive before its optional WebP thumbnail. Promised media can
87
+ declare `screenshotState: processing` or `clip.state: processing` until ready.
88
+
89
+ The runner publishes an initial snapshot, each reached screen and completed step, each completed
90
+ path and run completion. File replacements are atomic. Active outcomes stay out of
91
+ `outcomes.json`, so merging and rerunning reuse only completed paths. Results retain deterministic
92
+ plan order across workers.
93
+
94
+ ## Server events
95
+
96
+ An optional `eventsUrl`, relative to `baseUrl`, serves `text/event-stream`. Send ordinary messages
97
+ or named `atlas:change` events:
98
+
99
+ ```text
100
+ event: atlas:change
101
+ id: 124
102
+ data: {"scope":"runs","runIds":["build-123"]}
103
+
104
+ ```
105
+
106
+ These invalidate the source's index and named snapshots. Empty `runIds` refreshes cached snapshots
107
+ for this source. Reconnection does the same to recover missed updates. Malformed notices are
108
+ ignored. Polling remains available if a stream disconnects or EventSource is unavailable.
109
+
110
+ Configured source indexes poll every ten seconds by default (`pollMs` overrides this); selected
111
+ running snapshots poll every two seconds. `VITE_ATLAS_POLL_MS` controls spec polling. Pause live
112
+ updates to keep a snapshot steady; manual Refresh still works. Resuming refreshes immediately.
113
+
114
+ ## Identity, failures and publishing
115
+
116
+ Viewer identities combine source ids and native run ids. Cache keys include the backend location
117
+ and transport. Matching run names cannot mix results or media. Shared links retain the qualified
118
+ identity; old links containing only a run id still resolve to workspace reports.
119
+
120
+ One unavailable source leaves other sources and the spec usable. Failed refreshes retain the
121
+ last valid index and snapshot, with the failure recorded in data issues. A missing first snapshot
122
+ is a waiting state for a running report. Latest follows the newest report, including active runs;
123
+ choosing a particular report keeps it selected as newer reports arrive.
124
+
125
+ Publishing includes privacy-checked running snapshots and finished runs. Extra directory sources
126
+ are copied under `data/backends/<id>/`; `sources.json` uses relative URLs. Remote descriptors stay
127
+ remote. Missing or failed privacy checks exclude the run, and temporary files and work directories
128
+ are excluded. `--keep` applies per directory source. Publish updated data to the same host while
129
+ a run is active for static viewers to receive its snapshots through polling.
130
+
131
+ `VITE_ATLAS_BASE_URL` sets the primary spec/data location; `VITE_ATLAS_SOURCES_URL` can point to a
132
+ descriptor file hosted elsewhere. Published descriptors translate directory sources into HTTP
133
+ URLs and never expose the directory paths.
134
+
135
+ ## Another transport
136
+
137
+ `src/data/adapters/report-backend.ts` defines `ReportBackend`: stable identity and cache key,
138
+ report listing, snapshot loading, media resolution and optional change subscription. The query
139
+ layer consumes this separately from the spec adapter. An embedded viewer can supply a backend
140
+ through `ReportSourcesContext`; a new built-in transport can add a factory alongside
141
+ `createReportBackend`. Screens, maps and journeys require no transport-specific code.
142
+
143
+ The generated JSON Schemas include `report-sources`, `atlas-change`, `run-info` and `run-summary`
144
+ alongside the existing manifest and record schemas.