@crvouga/atlas 0.4.0 → 0.6.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 (444) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +191 -611
  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 +35 -1
  9. package/dist/core/src/config.d.ts +77 -4
  10. package/dist/core/src/config.js +110 -17
  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 +75 -16
  30. package/dist/core/src/run/execute.js +71 -18
  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 +85 -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 +56 -0
  120. package/dist/reports/src/http-store.js +148 -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 +369 -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/live-reporter.d.ts +34 -0
  147. package/dist/reports/src/live-reporter.js +122 -0
  148. package/dist/reports/src/media-types.d.ts +11 -0
  149. package/dist/reports/src/media-types.js +22 -0
  150. package/dist/reports/src/namespace-guard.d.ts +10 -1
  151. package/dist/reports/src/namespace-guard.js +10 -1
  152. package/dist/reports/src/navigation.d.ts +12 -0
  153. package/dist/reports/src/navigation.js +7 -0
  154. package/dist/reports/src/object-io.d.ts +11 -4
  155. package/dist/reports/src/object-io.js +4 -4
  156. package/dist/reports/src/object-store-conformance.d.ts +27 -0
  157. package/dist/reports/src/object-store-conformance.js +87 -0
  158. package/dist/reports/src/object-store.d.ts +33 -24
  159. package/dist/reports/src/object-store.js +17 -24
  160. package/dist/reports/src/parse-with.d.ts +16 -0
  161. package/dist/reports/src/parse-with.js +14 -0
  162. package/dist/reports/src/performance-part.d.ts +25 -1
  163. package/dist/reports/src/performance-part.js +15 -1
  164. package/dist/reports/src/performance.d.ts +22 -2
  165. package/dist/reports/src/performance.js +12 -2
  166. package/dist/reports/src/persist.d.ts +12 -3
  167. package/dist/reports/src/persist.js +12 -3
  168. package/dist/reports/src/phone.d.ts +18 -1
  169. package/dist/reports/src/phone.js +18 -1
  170. package/dist/reports/src/protocol.d.ts +26 -4
  171. package/dist/reports/src/protocol.js +15 -4
  172. package/dist/reports/src/publication.d.ts +21 -1
  173. package/dist/reports/src/publication.js +21 -1
  174. package/dist/reports/src/publish-checks.d.ts +35 -0
  175. package/dist/reports/src/publish-checks.js +122 -0
  176. package/dist/reports/src/publish.d.ts +42 -9
  177. package/dist/reports/src/publish.js +36 -7
  178. package/dist/reports/src/read.d.ts +46 -16
  179. package/dist/reports/src/read.js +38 -14
  180. package/dist/reports/src/recording-bundle.d.ts +13 -2
  181. package/dist/reports/src/recording-bundle.js +4 -2
  182. package/dist/reports/src/recording-keys.d.ts +15 -1
  183. package/dist/reports/src/recording-keys.js +15 -1
  184. package/dist/reports/src/remote-report.d.ts +28 -7
  185. package/dist/reports/src/remote-report.js +15 -7
  186. package/dist/reports/src/report-cli.d.ts +51 -0
  187. package/dist/reports/src/report-cli.js +486 -0
  188. package/dist/reports/src/report-index.d.ts +99 -0
  189. package/dist/reports/src/report-index.js +337 -0
  190. package/dist/reports/src/report-loader.d.ts +10 -0
  191. package/dist/reports/src/report-loader.js +6 -0
  192. package/dist/reports/src/report-parts.d.ts +29 -3
  193. package/dist/reports/src/report-parts.js +37 -3
  194. package/dist/reports/src/report-status.d.ts +48 -0
  195. package/dist/reports/src/report-status.js +156 -0
  196. package/dist/reports/src/report-types.d.ts +73 -0
  197. package/dist/reports/src/report-types.js +3 -0
  198. package/dist/reports/src/reporter.d.ts +67 -0
  199. package/dist/reports/src/reporter.js +128 -0
  200. package/dist/reports/src/reports-explorer-route.d.ts +541 -0
  201. package/dist/reports/src/reports-explorer-route.js +11 -0
  202. package/dist/reports/src/reports-list-route.d.ts +9 -0
  203. package/dist/reports/src/reports-list-route.js +9 -0
  204. package/dist/reports/src/reports-route.d.ts +561 -22
  205. package/dist/reports/src/reports-route.js +11 -3
  206. package/dist/reports/src/reports-store.d.ts +19 -2
  207. package/dist/reports/src/reports-store.js +10 -2
  208. package/dist/reports/src/resilient-cache.d.ts +14 -1
  209. package/dist/reports/src/resilient-cache.js +8 -1
  210. package/dist/reports/src/retention.d.ts +17 -1
  211. package/dist/reports/src/retention.js +5 -1
  212. package/dist/reports/src/run-bundle.d.ts +63 -0
  213. package/dist/reports/src/run-bundle.js +159 -0
  214. package/dist/reports/src/s3-store.d.ts +79 -0
  215. package/dist/reports/src/s3-store.js +295 -0
  216. package/dist/reports/src/scenario.d.ts +14 -4
  217. package/dist/reports/src/scenario.js +5 -4
  218. package/dist/reports/src/sigv4.d.ts +72 -0
  219. package/dist/reports/src/sigv4.js +96 -0
  220. package/dist/reports/src/snapshot-bundle.d.ts +24 -1
  221. package/dist/reports/src/snapshot-bundle.js +27 -2
  222. package/dist/reports/src/snapshot-surface.d.ts +20 -9
  223. package/dist/reports/src/snapshot-surface.js +32 -19
  224. package/dist/reports/src/source-content.d.ts +23 -0
  225. package/dist/reports/src/source-content.js +30 -1
  226. package/dist/reports/src/source-entries.d.ts +13 -0
  227. package/dist/reports/src/source-entries.js +6 -0
  228. package/dist/reports/src/source-part.d.ts +15 -0
  229. package/dist/reports/src/source-part.js +8 -0
  230. package/dist/reports/src/source-reader.d.ts +11 -0
  231. package/dist/reports/src/source-reader.js +5 -0
  232. package/dist/reports/src/spec-evidence.d.ts +12 -2
  233. package/dist/reports/src/spec-evidence.js +6 -2
  234. package/dist/reports/src/spec-inventory.d.ts +15 -1
  235. package/dist/reports/src/spec-inventory.js +22 -1
  236. package/dist/reports/src/spec-link.d.ts +28 -0
  237. package/dist/reports/src/spec-link.js +70 -0
  238. package/dist/reports/src/spec-set.d.ts +63 -0
  239. package/dist/reports/src/spec-set.js +177 -0
  240. package/dist/reports/src/status.d.ts +10 -0
  241. package/dist/reports/src/status.js +5 -0
  242. package/dist/reports/src/store-prefix.d.ts +28 -0
  243. package/dist/reports/src/store-prefix.js +22 -0
  244. package/dist/reports/src/store-url.d.ts +89 -0
  245. package/dist/reports/src/store-url.js +160 -0
  246. package/dist/reports/src/test-catalog-entity.d.ts +11 -0
  247. package/dist/reports/src/test-catalog-entity.js +6 -0
  248. package/dist/reports/src/types.d.ts +6 -1
  249. package/dist/reports/src/use-report-nav.d.ts +35 -0
  250. package/dist/reports/src/use-report-nav.js +12 -0
  251. package/dist/runners/src/codecept.d.ts +14 -0
  252. package/dist/runners/src/codecept.js +16 -0
  253. package/dist/runners/src/jest.d.ts +50 -0
  254. package/dist/runners/src/jest.js +52 -0
  255. package/dist/runners/src/mocha.d.ts +40 -0
  256. package/dist/runners/src/mocha.js +39 -0
  257. package/dist/runners/src/node-test.d.ts +28 -0
  258. package/dist/runners/src/node-test.js +44 -0
  259. package/dist/runners/src/publish.d.ts +30 -0
  260. package/dist/runners/src/publish.js +68 -0
  261. package/dist/schema/src/api.d.ts +800 -0
  262. package/dist/schema/src/api.js +201 -0
  263. package/dist/schema/src/cli-results.d.ts +210 -0
  264. package/dist/schema/src/cli-results.js +124 -0
  265. package/dist/schema/src/common.d.ts +53 -0
  266. package/dist/schema/src/common.js +42 -0
  267. package/dist/schema/src/index.d.ts +16 -0
  268. package/dist/schema/src/index.js +16 -0
  269. package/dist/schema/src/layer.d.ts +2273 -0
  270. package/dist/schema/src/layer.js +462 -0
  271. package/dist/schema/src/live-run.d.ts +123 -0
  272. package/dist/schema/src/live-run.js +30 -0
  273. package/dist/schema/src/manifest.d.ts +97 -2
  274. package/dist/schema/src/manifest.js +84 -0
  275. package/dist/schema/src/project.d.ts +20 -0
  276. package/dist/schema/src/project.js +10 -0
  277. package/dist/schema/src/report-sources.d.ts +29 -0
  278. package/dist/schema/src/report-sources.js +27 -1
  279. package/dist/schema/src/runs-index.d.ts +17 -1
  280. package/dist/schema/src/runs-index.js +15 -0
  281. package/dist/schema/src/server-config.d.ts +177 -0
  282. package/dist/schema/src/server-config.js +85 -0
  283. package/dist/schema/src/spec.d.ts +69 -0
  284. package/dist/schema/src/spec.js +58 -0
  285. package/dist/server/src/app.d.ts +72 -0
  286. package/dist/server/src/app.js +557 -0
  287. package/dist/server/src/auth.d.ts +41 -0
  288. package/dist/server/src/auth.js +59 -0
  289. package/dist/server/src/config.d.ts +83 -0
  290. package/dist/server/src/config.js +204 -0
  291. package/dist/server/src/dev.d.ts +12 -0
  292. package/dist/server/src/dev.js +89 -0
  293. package/dist/server/src/events.d.ts +29 -0
  294. package/dist/server/src/events.js +101 -0
  295. package/dist/server/src/host.d.ts +30 -0
  296. package/dist/server/src/host.js +115 -0
  297. package/dist/server/src/index.d.ts +18 -0
  298. package/dist/server/src/index.js +18 -0
  299. package/dist/server/src/live-runs.d.ts +52 -0
  300. package/dist/server/src/live-runs.js +229 -0
  301. package/dist/server/src/llms.d.ts +19 -0
  302. package/dist/server/src/llms.js +63 -0
  303. package/dist/server/src/main.d.ts +30 -0
  304. package/dist/server/src/main.js +114 -0
  305. package/dist/server/src/openapi.d.ts +56 -0
  306. package/dist/server/src/openapi.js +438 -0
  307. package/dist/server/src/problem.d.ts +8 -0
  308. package/dist/server/src/problem.js +39 -0
  309. package/dist/server/src/projects.d.ts +3 -0
  310. package/dist/server/src/projects.js +154 -0
  311. package/dist/server/src/settings-page.d.ts +9 -0
  312. package/dist/server/src/settings-page.js +93 -0
  313. package/dist/server/src/settings.d.ts +23 -0
  314. package/dist/server/src/settings.js +72 -0
  315. package/dist/server/src/site.d.ts +15 -0
  316. package/dist/server/src/site.js +78 -0
  317. package/dist/server/src/store-api.d.ts +28 -0
  318. package/dist/server/src/store-api.js +180 -0
  319. package/dist/server/src/validate.d.ts +71 -0
  320. package/dist/server/src/validate.js +197 -0
  321. package/dist/vitest/src/index.d.ts +27 -5
  322. package/dist/vitest/src/index.js +18 -5
  323. package/dist/webdriver/src/driver.d.ts +63 -11
  324. package/dist/webdriver/src/driver.js +57 -6
  325. package/dist/webdriver/src/index.d.ts +8 -0
  326. package/dist/webdriver/src/index.js +1 -0
  327. package/dist/webdriver/src/protocol.d.ts +75 -6
  328. package/dist/webdriver/src/protocol.js +79 -6
  329. package/docs/agents.md +137 -0
  330. package/docs/deploying.md +345 -0
  331. package/docs/dogfooding.md +175 -0
  332. package/docs/extending.md +242 -0
  333. package/docs/integrating.md +485 -0
  334. package/docs/reference/bun.md +141 -0
  335. package/docs/reference/cli.md +148 -0
  336. package/docs/reference/core.md +2432 -0
  337. package/docs/reference/detox.md +150 -0
  338. package/docs/reference/http-api.md +799 -0
  339. package/docs/reference/playwright.md +303 -0
  340. package/docs/reference/reports.md +7152 -0
  341. package/docs/reference/runners.md +169 -0
  342. package/docs/reference/schema.md +1762 -0
  343. package/docs/reference/server.md +825 -0
  344. package/docs/reference/vitest.md +45 -0
  345. package/docs/reference/webdriver.md +330 -0
  346. package/docs/report-backends.md +144 -0
  347. package/docs/report-contract.md +400 -0
  348. package/docs/reporting-issues.md +160 -0
  349. package/docs/runners.md +69 -0
  350. package/docs/server.md +321 -0
  351. package/docs/statecharts.md +643 -0
  352. package/llms-full.txt +4114 -0
  353. package/llms.txt +49 -0
  354. package/package.json +61 -11
  355. package/packages/core/README.md +2 -1
  356. package/packages/reports/README.md +65 -0
  357. package/packages/reports/STORAGE.md +4 -0
  358. package/packages/runners/README.md +6 -0
  359. package/packages/runners/compat/codecept.cjs +2 -0
  360. package/packages/runners/compat/jest.cjs +2 -0
  361. package/packages/runners/compat/mocha.cjs +2 -0
  362. package/packages/schema/README.md +14 -0
  363. package/packages/schema/schemas/atlas-change.schema.json +4 -0
  364. package/packages/schema/schemas/check-detail.schema.json +1032 -0
  365. package/packages/schema/schemas/checks-result.schema.json +26 -0
  366. package/packages/schema/schemas/command-error.schema.json +35 -0
  367. package/packages/schema/schemas/doctor-result.schema.json +60 -0
  368. package/packages/schema/schemas/effective-delta.schema.json +490 -0
  369. package/packages/schema/schemas/effective-evidence.schema.json +471 -0
  370. package/packages/schema/schemas/evidence-page.schema.json +271 -0
  371. package/packages/schema/schemas/hello-event.schema.json +26 -0
  372. package/packages/schema/schemas/init-plan.schema.json +347 -0
  373. package/packages/schema/schemas/layer-rows.schema.json +199 -0
  374. package/packages/schema/schemas/layer.schema.json +2888 -0
  375. package/packages/schema/schemas/live-run-start.schema.json +42 -0
  376. package/packages/schema/schemas/live-run-update.schema.json +93 -0
  377. package/packages/schema/schemas/live-run.schema.json +225 -0
  378. package/packages/schema/schemas/merge-result.schema.json +40 -0
  379. package/packages/schema/schemas/outline.schema.json +62 -0
  380. package/packages/schema/schemas/problem.schema.json +37 -0
  381. package/packages/schema/schemas/project-slug.schema.json +8 -0
  382. package/packages/schema/schemas/project.schema.json +22 -0
  383. package/packages/schema/schemas/projects.schema.json +33 -0
  384. package/packages/schema/schemas/publish-checks.schema.json +1413 -0
  385. package/packages/schema/schemas/publish-result.schema.json +168 -0
  386. package/packages/schema/schemas/ready.schema.json +68 -0
  387. package/packages/schema/schemas/report-event.schema.json +100 -0
  388. package/packages/schema/schemas/report-status.schema.json +370 -0
  389. package/packages/schema/schemas/server-config.schema.json +208 -0
  390. package/packages/schema/schemas/server-editable-settings.schema.json +132 -0
  391. package/packages/schema/schemas/server-info.schema.json +114 -0
  392. package/packages/schema/schemas/server-settings-snapshot.schema.json +285 -0
  393. package/packages/schema/schemas/spec-set.schema.json +103 -0
  394. package/packages/schema/schemas/store-listing.schema.json +29 -0
  395. package/packages/schema/schemas/store-write-result.schema.json +28 -0
  396. package/packages/schema/schemas/stream-result.schema.json +59 -0
  397. package/packages/server/README.md +43 -0
  398. package/packages/server/openapi.json +11021 -0
  399. package/packages/visualizer/README.md +32 -11
  400. package/packages/visualizer/bin/atlas-client.mjs +176 -0
  401. package/packages/visualizer/bin/atlas-visualizer.mjs +2 -175
  402. package/packages/visualizer/src/app/AppShell.tsx +32 -16
  403. package/packages/visualizer/src/app/report-sources.tsx +7 -4
  404. package/packages/visualizer/src/app/router.tsx +3 -3
  405. package/packages/visualizer/src/components/ActivityIndicator.module.css +4 -0
  406. package/packages/visualizer/src/components/ActivityIndicator.tsx +6 -0
  407. package/packages/visualizer/src/components/Header.module.css +101 -192
  408. package/packages/visualizer/src/components/Header.tsx +88 -13
  409. package/packages/visualizer/src/components/ProjectPicker.tsx +64 -0
  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/data/adapters/report-backend.test.ts +3 -2
  413. package/packages/visualizer/src/data/adapters/report-backend.ts +1 -1
  414. package/packages/visualizer/src/data/queries.ts +14 -7
  415. package/packages/visualizer/src/evidence/api.ts +16 -3
  416. package/packages/visualizer/src/evidence/artifacts.module.css +213 -0
  417. package/packages/visualizer/src/evidence/artifacts.tsx +272 -0
  418. package/packages/visualizer/src/evidence/check-detail.tsx +21 -4
  419. package/packages/visualizer/src/evidence/document-page.tsx +6 -2
  420. package/packages/visualizer/src/evidence/evidence-context.tsx +79 -12
  421. package/packages/visualizer/src/evidence/evidence.module.css +11 -1
  422. package/packages/visualizer/src/evidence/feature-page.tsx +7 -3
  423. package/packages/visualizer/src/evidence/model-page.tsx +6 -2
  424. package/packages/visualizer/src/evidence/project-home.tsx +45 -0
  425. package/packages/visualizer/src/evidence/recording-page.tsx +4 -1
  426. package/packages/visualizer/src/evidence/spec-index.tsx +2 -1
  427. package/packages/visualizer/src/evidence/spec-page.tsx +23 -16
  428. package/packages/visualizer/src/evidence/test-filter.tsx +21 -0
  429. package/packages/visualizer/src/find/Finder.tsx +1 -7
  430. package/packages/visualizer/src/find/open.ts +4 -0
  431. package/packages/visualizer/src/live/live-query.ts +21 -0
  432. package/packages/visualizer/src/live/live-runs.tsx +69 -0
  433. package/packages/visualizer/src/live/live-stream.ts +225 -0
  434. package/packages/visualizer/src/live/report-progress.ts +62 -0
  435. package/packages/visualizer/src/live/test-progress.tsx +34 -0
  436. package/packages/visualizer/src/runtime.ts +35 -0
  437. package/packages/visualizer/src/state/ui-store.ts +3 -2
  438. package/packages/visualizer/src/views/ChartPage.tsx +2 -0
  439. package/packages/visualizer/src/views/ChartTests.tsx +43 -0
  440. package/packages/visualizer/src/views/SidePanel.tsx +2 -0
  441. package/packages/visualizer/vite/atlas-files.test.ts +4 -4
  442. package/packages/visualizer/vite/atlas-files.ts +1 -5
  443. package/packages/visualizer/vite/atlas-server-proxy.ts +37 -0
  444. package/packages/visualizer/vite.config.ts +11 -3
@@ -0,0 +1,345 @@
1
+ # Running Atlas for a project: one server
2
+
3
+ This is the production setup. A project runs **one Atlas server**. Developers' machines and every CI job send
4
+ their results to it, as they finish or when they are done, and it shows everyone, developers and the business
5
+ alike, the whole project at once, live. It keeps results on its own disk by default, or in an object-store bucket
6
+ if you prefer; either way nothing is partitioned by run, branch or person: results are layered. The server's API,
7
+ configuration and protocol are in **[the Atlas server](server.md)**; this page is the path to production.
8
+
9
+ ```
10
+ a developer's worktree ─┐ ┌─▶ developers (browser, live)
11
+ a CI job, any branch ───┼─ atlas report publish|stream ─▶ SERVER ◀┤ atlas serve: keeps layers in ./atlas-data
12
+ a device lab, nightly ──┘ (immutable layers, over HTTP) or S3 ├─▶ business or in a bucket (--write)
13
+ └─▶ CI gate atlas report status
14
+ ```
15
+
16
+ Why this holds together:
17
+
18
+ - **Publishing never conflicts.** A layer is one immutable file named by its content. Two machines that
19
+ publish at once write different files; a retry writes the same one. There is no lock, no index to
20
+ corrupt, nothing to merge.
21
+ - **The server is replaceable.** What it knows is its write backend (a folder, or a bucket). Replace it, restore it
22
+ from a backup, or run a copy on a laptop: they show the same report, because a report is a function of the
23
+ layers ([the contract](report-contract.md)).
24
+ - **One view.** The newest completed result of every check, in every environment, from anyone. A
25
+ developer's local run on a feature branch, CI on `main` and a device lab's nightly sit side by side.
26
+ Narrow it only when you choose to ([filters](#5-choosing-what-takes-part)).
27
+
28
+ - [1. Where results are kept](#1-where-results-are-kept)
29
+ - [2. Check it](#2-check-it)
30
+ - [3. Send results from CI and from laptops](#3-send-results-from-ci-and-from-laptops)
31
+ - [4. The server](#4-the-server)
32
+ - [5. Choosing what takes part](#5-choosing-what-takes-part)
33
+ - [6. Operating it](#6-operating-it)
34
+ - [7. Performance](#7-performance)
35
+ - [8. Troubleshooting](#8-troubleshooting)
36
+
37
+ ## 1. Where results are kept
38
+
39
+ **By default, on the server's own disk** (`./atlas-data`, or the volume you mount at `ATLAS_DATA`). Nothing else
40
+ needs to exist: skip to [section 3](#3-send-results-from-ci-and-from-laptops). Back that folder up like any data
41
+ directory; starting a new server on a restored copy shows the same report.
42
+
43
+ **To keep results in a bucket instead** (so a replaced server loses nothing, or CI already has bucket access),
44
+ name it and make it the place uploads go: `ATLAS_STORE=project=s3://my-bucket/atlas/my-project ATLAS_WRITE=project`.
45
+ The rest of this section is that setup. A store is named by a URL. Keys never go in it.
46
+
47
+ | Store | URL |
48
+ | --- | --- |
49
+ | AWS S3 | `s3://my-bucket/atlas/my-project` (add `?region=eu-west-1` if `AWS_REGION` is not set) |
50
+ | A folder | `/srv/atlas`, `./atlas-reports` (a CI workspace, an NFS mount, a laptop) |
51
+ | Cloudflare R2 | `r2://bucket/atlas/my-project?account=<account id>` (or `R2_ACCOUNT_ID`), with the R2 token's keys in `ATLAS_S3_ACCESS_KEY_ID` / `ATLAS_S3_SECRET_ACCESS_KEY` |
52
+ | Google Cloud Storage | `gs://bucket/atlas/my-project`, with an HMAC key pair in `ATLAS_S3_*` |
53
+ | MinIO, Backblaze B2, Wasabi, SeaweedFS, any S3-compatible | `s3://bucket/atlas/my-project?endpoint=https://host&region=auto` |
54
+
55
+ Atlas talks to S3 itself, signing requests with Signature Version 4 and sending them with `fetch`: no
56
+ SDK, no extra install, the same on Bun and Node. It is tested against AWS's published signing vectors
57
+ and, for real, against a live S3 server (SeaweedFS) in CI. Stores other than AWS and SeaweedFS speak the
58
+ same protocol; the `r2://` and `gs://` shorthands only fill in the endpoint. None of them is part of Atlas's own tests,
59
+ so run `atlas report doctor` against yours before relying on it.
60
+
61
+ **On AWS:**
62
+
63
+ 1. Create a bucket. Keep "block all public access" on. Default encryption (SSE-S3) needs nothing more; with
64
+ SSE-KMS the roles below also need `kms:Decrypt` and `kms:GenerateDataKey` on the key.
65
+ 2. Use one folder per project (`atlas/my-project/`). Several projects can share a bucket.
66
+ 3. Create two roles. `atlas report policy` prints each, scoped to the bucket and folder:
67
+
68
+ ```sh
69
+ atlas report policy --store s3://my-bucket/atlas/my-project --role publisher # CI and developers
70
+ atlas report policy --store s3://my-bucket/atlas/my-project --role reader # a server that only reads it, and the gate
71
+ # the server that uploads into it needs --role both (also grants server/live/* for live leases)
72
+ ```
73
+
74
+ A publisher may write and read `layers/*` and list the folder. A reader may read `layers/*` and list.
75
+ Nobody needs to delete or overwrite: **do not grant it**. (`s3:ListBucket` is for publishers too: without
76
+ it S3 answers "403 forbidden" instead of "404 not found" when asked whether a layer exists yet.)
77
+ 4. Do not put a lifecycle rule that expires `layers/`. Old layers are cheap and are history. If storage
78
+ grows, expire `layers/runs/` (screenshots and clips) first.
79
+
80
+ Versioning and replication are optional: nothing is ever overwritten with different bytes.
81
+
82
+ ## 2. Check it
83
+
84
+ ```sh
85
+ export ATLAS_STORE=s3://my-bucket/atlas/my-project
86
+ atlas report doctor # a role that can do everything
87
+ atlas report doctor --role publisher # what CI and developers can do
88
+ atlas report doctor --role reader # what a reader can do
89
+ ```
90
+
91
+ ```
92
+ my-project
93
+ ✓ store s3://my-bucket/atlas/my-project/ (us-east-1)
94
+ ✓ list 38 ms, credentials from AWS CLI (profile default)
95
+ ✓ contents 1240 layers (newest 2026-10-09T11:59:00.000Z), 3 spec sets, 12 runs
96
+ ✓ write wrote, listed, read back and deleted a scratch object: the store meets the ObjectStore contract
97
+ All good.
98
+ ```
99
+
100
+ Each failure says what to fix: the permission that is missing, the region that is wrong, the clock that is
101
+ off. The credentials come from the same places an AWS SDK looks, in this order: `ATLAS_S3_ACCESS_KEY_ID` /
102
+ `ATLAS_S3_SECRET_ACCESS_KEY` (so one store can use keys that are not the machine's AWS keys), then
103
+ `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`, EKS web identity (IRSA), ECS task roles,
104
+ `~/.aws/credentials`, the AWS CLI (which covers SSO, assumed roles and `credential_process`), and EC2
105
+ instance metadata. Credentials that expire are refreshed before they do.
106
+
107
+ ## 3. Send results from CI and from laptops
108
+
109
+ Every environment runs the same command. Set `ATLAS_STORE` once and it needs no flags for the store.
110
+
111
+ ### To the server
112
+
113
+ ```sh
114
+ export ATLAS_STORE=https://atlas.example.com # once, in .envrc, CI variables or your shell profile
115
+ export ATLAS_TOKEN=… # a publish token of the server (never in the URL)
116
+ bun test --reporter=junit --reporter-outfile=out.xml
117
+ bunx atlas report publish --producer unit --junit out.xml --specs ./specs --environment desktop-web
118
+ ```
119
+
120
+ The result is in everyone's view within a few milliseconds, with no bucket credentials anywhere, and no
121
+ artifacts to merge. To show a long suite *while it runs*, stream it: `my-suite --json | atlas report stream
122
+ --producer e2e --environment ios` ([sending results](server.md#sending-results)). The gate asks the server for the
123
+ verdict, so only the verdict travels: `atlas report status --branch main --ignore-modified`.
124
+ [`examples/deploy/github-actions.yml`](https://github.com/crvouga/atlas/blob/main/examples/deploy/github-actions.yml)
125
+ is the whole workflow, publishers and gate. The rest of this section is publishing straight to a bucket, for
126
+ CI that has bucket access and no route to the server.
127
+
128
+ ### Straight to the bucket
129
+
130
+ ### CI
131
+
132
+ Give CI a role, not a key. On GitHub Actions that is OIDC, so no AWS secret is stored anywhere. Every
133
+ node publishes its own layers straight to the bucket: no artifacts to download and merge. The server finds them
134
+ at its next refresh.
135
+
136
+ ```yaml
137
+ permissions: { id-token: write, contents: read }
138
+ env: { ATLAS_STORE: "s3://my-bucket/atlas/my-project" }
139
+ steps:
140
+ - run: bun test --reporter=junit --reporter-outfile=out.xml
141
+ continue-on-error: true # a failing suite must still publish: a failure is evidence
142
+ - uses: aws-actions/configure-aws-credentials@v4
143
+ with: { role-to-assume: "arn:aws:iam::123456789012:role/atlas-publisher", aws-region: us-east-1 }
144
+ - run: bunx atlas report publish --producer unit --junit out.xml --specs ./specs --environment desktop-web
145
+ if: always()
146
+ ```
147
+
148
+ `--sha`, `--branch` and the run URL come from the CI's variables. `--specs ./specs` also publishes the
149
+ specs themselves, so the server can show them without a checkout (below).
150
+
151
+ ### A developer's laptop
152
+
153
+ ```sh
154
+ aws sso login # or any way you sign in to AWS
155
+ export ATLAS_STORE=s3://my-bucket/atlas/my-project # once, in .envrc or your shell profile
156
+ bun test --reporter=junit --reporter-outfile=out.xml
157
+ bunx atlas report publish --producer unit --junit out.xml --specs ./specs --environment desktop-web
158
+ ```
159
+
160
+ Atlas sees from git whether the worktree has uncommitted edits to tracked files. If it does, the layer is
161
+ marked **modified**: it appears in the shared view with the warning "Potentially outdated: recorded from a
162
+ modified checkout", never as the commit's own result. Outside a git checkout the origin is **unknown**.
163
+ A CI checkout is the commit it names. Untracked files (build output, `out.xml`) do not count.
164
+
165
+ Through the server a result is in the shared view at once; straight to a bucket, within the server's refresh interval
166
+ (10 seconds by default).
167
+
168
+ ### What lands in the bucket
169
+
170
+ | Key | What | Written by |
171
+ | --- | --- | --- |
172
+ | `layers/manifests/<id>.json`, `layers/index/…` | One layer of checks, and its catalog entry | `publish` |
173
+ | `layers/specs/blobs/<sha256>.txt`, `layers/specs/sets/<id>.json`, `layers/specs/index/…` | The specs of one commit, by content | `publish --specs` |
174
+ | `layers/runs/<run>/…`, `layers/runs/index/…` | A statechart run with its screenshots and clips | `publish --manifest … --upload-run` |
175
+
176
+ Everything is immutable and addressed by its content, so each publish is safe to repeat and safe to run
177
+ in parallel. A set of specs is named by the files and the commit, so publishing the same commit from ten
178
+ nodes writes it once.
179
+
180
+ For statecharts, publish each run as a layer and upload it for the client:
181
+
182
+ ```sh
183
+ bunx atlas run --config atlas.config.ts --shard 1/2
184
+ bunx atlas report publish --producer statecharts --environment desktop-web \
185
+ --manifest atlas-runs/<run>/manifest.json --specs ./specs --upload-run
186
+ ```
187
+
188
+ A run is uploaded only when its privacy scan passed: the same rule the static client applies.
189
+
190
+ ## 4. The server
191
+
192
+ ```sh
193
+ atlas serve # ATLAS_STORE says where; listens on :8080
194
+ ```
195
+
196
+ It serves the client, the report and the project's specs and runs from all configured backends. It also
197
+ accepts uploads and announces new results on its event stream. Uploads go to `--data` by default;
198
+ use a named `--store project=s3://… --write project` to put uploads in a shared bucket, with publisher permissions.
199
+
200
+ | Flag | Environment | Meaning |
201
+ | --- | --- | --- |
202
+ | `--store <url>` (repeatable) | `ATLAS_STORE` | Where layers are. Several stores are one report: repeat the flag, or separate them in the variable with commas or new lines. |
203
+ | `--data <dir>` | `ATLAS_DATA` | Local upload backend. Default `./atlas-data`. |
204
+ | `--write <id>` | `ATLAS_WRITE` | Backend that accepts uploads. Default `data`. |
205
+ | `--port <n>` | `ATLAS_PORT` or `PORT` | Default 8080. `0` picks a free one. |
206
+ | `--host <h>` | `ATLAS_HOST` or `HOST` | Default `127.0.0.1`. Listening beyond this machine requires tokens or `--insecure`. |
207
+ | `--site <dir>` | `ATLAS_SITE` | The built client. Default: `./atlas-site`, else built once into `~/.cache/atlas/site`. |
208
+ | `--outline-branch <b>` | `ATLAS_OUTLINE_BRANCH` | Which branch's specs the report is laid over. Default `main`, then `master`, then the newest. |
209
+ | `--refresh <seconds>` | `ATLAS_REFRESH_SECONDS` | How often the bucket is looked at for new layers. Default 10. |
210
+ | `--branch <name>` (repeatable) | `ATLAS_ONLY_BRANCH` | Only layers recorded on these branches take part. |
211
+ | `--ignore-modified` | `ATLAS_IGNORE_MODIFIED=1` | Leave out layers from modified checkouts and unknown origins. |
212
+ | | `ATLAS_TOKEN`, `ATLAS_PUBLISH_TOKEN`, `ATLAS_READ_TOKEN` | Admin, publisher and reader tokens, each at least 12 characters. Send `Authorization: Bearer <token>`, or HTTP Basic with the token as the password. Probes require no token. |
213
+
214
+ ### Run it
215
+
216
+ **Docker.** [`examples/deploy/Dockerfile`](https://github.com/crvouga/atlas/blob/main/examples/deploy/Dockerfile)
217
+ installs Atlas, builds the client once (it is the same for every project: the server tells the page where its
218
+ data is) and starts the server, keeping results on the volume at `/data`:
219
+
220
+ ```sh
221
+ docker build -t atlas examples/deploy
222
+ docker run -p 8080:8080 -v atlas-data:/data -e ATLAS_TOKEN=$(openssl rand -hex 24) atlas
223
+ ```
224
+
225
+ For a bucket as the system of record add `-e ATLAS_STORE=project=s3://my-bucket/atlas/my-project -e ATLAS_WRITE=project -e AWS_REGION=us-east-1`.
226
+ On ECS, EKS or EC2, attach the combined **both** policy (including `server/live/*` for producer leases) to the task, service account or
227
+ instance and set no keys.
228
+
229
+ **Try it on one machine.** [`examples/deploy/compose.yaml`](https://github.com/crvouga/atlas/blob/main/examples/deploy/compose.yaml)
230
+ starts the server on a volume; `compose.s3.yaml` starts it with an S3 server and a bucket as its storage.
231
+ Publish to `http://localhost:8080` from your project and open it.
232
+
233
+ **Kubernetes.** [`examples/deploy/kubernetes.yaml`](https://github.com/crvouga/atlas/blob/main/examples/deploy/kubernetes.yaml):
234
+ one copy (the server is a singleton for the project), results in the bucket, readiness on `/readyz`, an IRSA
235
+ service account.
236
+
237
+ **Without a container.** `bun add -d @crvouga/atlas`, then `bunx atlas client build --no-data --out
238
+ atlas-site` and `bunx atlas serve`. It runs on Bun and on Node 22.18 or later. Everything it can be told is in
239
+ [the Atlas server](server.md#configuration).
240
+
241
+ ### Who may look
242
+
243
+ Set `ATLAS_READ_TOKEN` for a dashboard that only accepts readers. `ATLAS_PUBLISH_TOKEN` also allows
244
+ uploads, and `ATLAS_TOKEN` grants administration. Without tokens the server listens on loopback by default. Put it behind what your
245
+ company already uses: an ALB with OIDC, Cloudflare Access, `oauth2-proxy`, Tailscale. TLS ends at that
246
+ layer too. Pass `--insecure` only when that proxy handles sign-in.
247
+
248
+ ### What it serves
249
+
250
+ | Path | |
251
+ | --- | --- |
252
+ | `/` | The client. Its page carries the server's address book, so one build serves every project. |
253
+ | `/api/reports/evidence/effective` | The whole report in one request: only the layers that win a check, each with only the rows that win. ETag, gzip. |
254
+ | `/api/reports/evidence`, `/evidence/rows/<backend>/<id>`, `/outline`, `/outline/spec?path=` | History, one layer's checks, the specs. |
255
+ | `/api/reports/evidence/detail/<backend>/<id>?check=<id>&kind=<kind>` | Everything one result carries: its timeline, annotations, retries, attachments and extensions, and the run's own. Without `check`, only the run's. |
256
+ | `/api/reports/layers/<id>/blobs/<key>` | One file a layer carries (screenshot, video, trace…), served as untrusted bytes with range support, cached for good. |
257
+ | `/api/data/specs/…`, `/api/data/runs/…`, `/api/data/sources.json` | The specs and runs, laid out the way the client reads a static host. |
258
+ | `/api/checks` | Upload a layer of checks with `POST`. |
259
+ | `/api/events` | Live report updates over server-sent events. |
260
+ | `/healthz` | The process is up. |
261
+ | `/readyz` | `200` once the bucket was read and at least one store answers; `503` otherwise. Route traffic on this. |
262
+
263
+ The specs come from the newest **spec set** published from `main` (`publish --specs`), so the server needs no
264
+ checkout and no git access. A set from someone's modified worktree is used only if no committed one exists.
265
+
266
+ ## 5. Choosing what takes part
267
+
268
+ By default every layer takes part: a report is the newest completed result of each check in each
269
+ environment, from wherever it was recorded. That is the unified view, and it is honest: a developer's run
270
+ on `feat/pay` shows up, labelled, until something newer replaces it.
271
+
272
+ Narrow it by choice, per consumer, never by moving data:
273
+
274
+ | You want | Use |
275
+ | --- | --- |
276
+ | A release gate that no laptop can turn red | `atlas report status --branch main --ignore-modified` |
277
+ | A pull request's gate that inherits what it did not re-run from `main` | `--branch "$PR_BRANCH" --branch main --ignore-modified` |
278
+ | A business dashboard of what is committed | `atlas serve --ignore-modified` |
279
+ | Everything, as the team lives it | nothing (the default) |
280
+ | One person's view of what leaving a source out changes | **Sources** in the client: leave out a branch, environment, version or layer |
281
+
282
+ ## 6. Operating it
283
+
284
+ - **Upgrades.** The layer format is a stable, versioned contract. A server reads every layer a publisher of
285
+ an older or the same schema version wrote, and names (never guesses at) a layer of a newer one. Upgrade
286
+ readers (the server, the gate) before publishers when a release bumps `schemaVersion`; within a version
287
+ they never need to move together.
288
+ - **Logs.** One JSON line per request to stdout. `/healthz` and `/readyz` are not logged. At start it
289
+ prints what it reads and any store it cannot reach.
290
+ - **A store goes down.** The server keeps serving what it has, names the store in the client's notices and
291
+ in `/readyz`, and recovers by itself. The gate fails closed: unknown is not a pass.
292
+ - **A layer cannot be read** (corrupt, or written by a newer Atlas): a notice names it. It is tried again
293
+ every five minutes.
294
+ - **Scaling.** One Atlas node supports multiple project namespaces with independently loaded report indexes. It takes in an upload in milliseconds and a
295
+ report of 100,000 checks costs a client kilobytes per change ([performance](server.md#performance)). Memory
296
+ grows with the number of distinct checks, plus about a hundred bytes for each layer ever seen (to know it has
297
+ read it). More than one server on a backend works and shows the same report, but each hears of uploads to
298
+ another only at its next refresh.
299
+ - **Cost.** Between full listings a refresh asks for one page of the catalog, newest first, and stops at the
300
+ first page it already knows: one `LIST` request every refresh interval, however long the history. A full
301
+ listing (one request per thousand layers) runs at the start and every 30 refreshes (five minutes by
302
+ default), which is also how a layer recorded with an old timestamp is found. One small `GET` per new
303
+ layer, once.
304
+ - **Retention.** Atlas deletes nothing. `atlas report doctor` shows what the bucket holds.
305
+ - **Disaster recovery.** The write backend (the data folder, or the bucket) is the only state. Back it up, replicate or version it as you
306
+ do any data; a server is rebuilt from nothing in the time it takes to read the layers (below). It listens at once
307
+ and answers `/readyz` 503 until it has, so a liveness probe never kills one that is still reading.
308
+ - **A second bucket.** Another team's layers, a device lab, an archive: pass several `--store`s. They are one
309
+ report, attributed to the store they came from.
310
+
311
+ ## 7. Performance
312
+
313
+ Measured, not promised (a laptop, a local S3 server, so these are the client's own costs; real S3 adds its
314
+ latency per request, which the server hides by reading 64 at a time):
315
+
316
+ | What | Cost |
317
+ | --- | --- |
318
+ | Publish a layer of plain checks | One `HEAD` and two small `PUT`s. Two thousand layers published in under two seconds from one process, in parallel. |
319
+ | Server start | About 0.2 ms of CPU per layer, plus S3 latency ÷ 64 per layer: 2,000 layers in well under a second on a fast store, a few seconds on S3. Each layer is read once, ever. |
320
+ | Refresh with nothing new | One `LIST` request for the newest page of the catalog, whatever the history. |
321
+ | The report, to a client | One request. 12,000 checks from 2,000 layers is 108 KB gzipped, built once per change. |
322
+ | The client asking again | `304 Not Modified` in under a millisecond. While the live stream is open it asks only when told, and then for only what changed. |
323
+ | The client in a browser | One request for the report, plus the spec index, outline and run index and the specs it opens. None per layer, whatever the history (measured in Chromium against a server reading S3). |
324
+
325
+ How: each layer is folded into the winning result of every check once and dropped unless it still holds a
326
+ winner, so work and memory follow the number of checks. Because the winner rule is a total order, folding in
327
+ any order is exact; a test proves the incremental report equals recomputing from every layer. The client
328
+ reads that compact report in one request and only falls back to reading every layer when you ask it to
329
+ leave a source out (which needs the history).
330
+
331
+ ## 8. Troubleshooting
332
+
333
+ | You see | Cause and fix |
334
+ | --- | --- |
335
+ | `No AWS credentials found for the object store` | None of the places was set. The message lists them. `aws sso login`, or export `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`. |
336
+ | `access denied … s3:PutObject` | The role is missing a permission. `atlas report policy --store <url>` prints the policy. |
337
+ | `403` on a layer that should not exist yet | The account cannot list the bucket (`s3:ListBucket`), so S3 answers 403 for a missing object. Grant it on the folder. |
338
+ | `the signature was rejected` | Wrong secret, or wrong region/endpoint for these keys, or the clock is off by more than 15 minutes. |
339
+ | `the bucket does not exist` | Typo, another account, or the store needs `?endpoint=…` (R2, MinIO). |
340
+ | `cannot reach <host>` | Network, DNS or endpoint. Requests are retried with backoff first. |
341
+ | The server says `listening … no backend can be read yet` | The bucket is unreachable from the server. It retries; `/readyz` stays 503 until it can read. |
342
+ | A new layer does not show | Uploaded through the server it is there at once: check the token (`401`/`403` say so). Written straight to a bucket, wait one refresh interval (10 s). Check `atlas report status --store <url>` sees it. |
343
+ | Everything is red because of one laptop | By design the newest result wins. Gate on `--ignore-modified` and a branch ([above](#5-choosing-what-takes-part)). |
344
+ | Specs are empty in the client | Nothing published with `--specs` yet, or only from a branch other than `main`: set `--outline-branch`. |
345
+ | `Run … is not shared: its privacy scan did not pass` | `--upload-run` refuses runs whose scan found real data. Fix what it found and run again. |
@@ -0,0 +1,175 @@
1
+ # Dogfooding Atlas from another project
2
+
3
+ Atlas is developed by using it in real projects. Those projects install one released package from
4
+ npm, `@crvouga/atlas`, and report what they find as GitHub issues. They never change Atlas. Every
5
+ fix and feature is made in this repository and reaches a project as a new version.
6
+
7
+ This replaces the Git submodule workflow. Several projects pushing to one `main` through their
8
+ submodules lost work and mixed unrelated changes together. If your project still has
9
+ `vendor/atlas`, follow [Migrating from the submodule](#migrating-from-the-submodule).
10
+
11
+ This guide is written for people and coding agents working in a project that uses Atlas. To set
12
+ Atlas up in a project, follow [integrating Atlas](integrating.md): it takes a project from nothing to
13
+ a layered, gated report of its specs. This page is about the relationship with Atlas itself: install,
14
+ upgrade, and what to do when something is wrong.
15
+
16
+ ## The rules
17
+
18
+ 1. Install Atlas from npm. No submodule, no vendored copy, no `git` or `file:` dependency.
19
+ 2. Never change Atlas from your project: do not edit `node_modules`, do not keep a patch
20
+ (`bun patch`, `pnpm patch`, `patch-package`), do not clone this repository to push a fix.
21
+ 3. When Atlas is wrong or is missing something, [file an issue](reporting-issues.md). A workaround
22
+ in your own code is fine while you wait; say so in the issue.
23
+ 4. Upgrade Atlas in a commit of its own.
24
+
25
+ ## Install
26
+
27
+ Atlas runs on Bun, and on Node 22.18 or later. It is one package:
28
+
29
+ ```sh
30
+ bun add -d @crvouga/atlas
31
+ ```
32
+
33
+ The commands in this guide use Bun. Any package manager installs it the same way
34
+ (`pnpm add -D`, `npm install -D`); use the one your project already has.
35
+
36
+ Everything is in it, each part behind its own import path. A bundler keeps only what you import,
37
+ and nothing runs just because the package is installed.
38
+
39
+ | Import | What it is |
40
+ | --- | --- |
41
+ | `@crvouga/atlas` | Specs, lint, planning, the runner, `httpDriver`, `functionDriver`, reports, `defineConfig`. |
42
+ | `@crvouga/atlas/spec` | The browser-safe subset for loading and composing charts. |
43
+ | `@crvouga/atlas/signals` | Driver-neutral signals (`role`, `text`, `label`, `screen`). |
44
+ | `@crvouga/atlas/playwright` | The Playwright driver. Also install `playwright`. |
45
+ | `@crvouga/atlas/bun` | The Bun WebView driver. |
46
+ | `@crvouga/atlas/webdriver` | The WebDriver and Appium driver. |
47
+ | `@crvouga/atlas/detox` | The Detox driver. Also install `detox`. |
48
+ | `@crvouga/atlas/vitest` | Each planned path as a test in Vitest, `bun test` or any Jest-style runner. |
49
+ | `@crvouga/atlas/schema` | Zod schemas for layers, check files, report status, manifests, timelines and the runs index. |
50
+ | `@crvouga/atlas/schemas/<name>.schema.json` | The same contract as JSON Schema files. |
51
+ | `@crvouga/atlas/reports/<module>` | Publishing, storing, combining, gating and serving test evidence for specs of any kind. |
52
+
53
+ It also installs two commands: `atlas` (report, lint, plan, run, merge, export) and
54
+ `atlas client` (browse specs, runs and reports).
55
+
56
+ `playwright` and `detox` are optional peers: install the one your driver uses, as above. The
57
+ documentation ships in the package, matching the version you installed: the README of each part at
58
+ `node_modules/@crvouga/atlas/packages/<part>/README.md`, and these guides at
59
+ `node_modules/@crvouga/atlas/docs/` (`integrating.md`, `deploying.md`, `extending.md`, `report-contract.md`,
60
+ `report-backends.md`, `statecharts.md`, `dogfooding.md`, `reporting-issues.md`).
61
+
62
+ Your `atlas.config.ts`, specs, implementation, fixtures and generated `atlas-runs/` stay in your
63
+ project. Import only the paths in the table; files under the package's `dist` or `packages` are not
64
+ part of its interface.
65
+
66
+ ## Upgrade
67
+
68
+ Every releasable change that lands on Atlas's `main` is published within minutes; nobody cuts
69
+ releases by hand ([releasing.md](https://github.com/crvouga/atlas/blob/main/docs/releasing.md)). There is one package and one version, so an upgrade
70
+ is one line:
71
+
72
+ ```sh
73
+ bun update @crvouga/atlas --latest
74
+ ```
75
+
76
+ Run your Atlas checks, then commit the manifests and lockfile on their own so an upgrade is easy to
77
+ find and to revert.
78
+
79
+ To see what changed:
80
+
81
+ ```sh
82
+ npm view @crvouga/atlas version # the newest release
83
+ cat node_modules/@crvouga/atlas/CHANGELOG.md # every release up to the version you have
84
+ ```
85
+
86
+ Each release is also a [GitHub Release](https://github.com/crvouga/atlas/releases) with the same
87
+ notes. Versions follow semver; a breaking change is a major version, and its notes say what to
88
+ change.
89
+
90
+ ## When something is wrong or missing
91
+
92
+ File an issue: [reporting-issues.md](reporting-issues.md) has the kinds, the title format, what to
93
+ leave out, and the `gh` command. One issue per bug or missing feature.
94
+
95
+ When the fix is merged, the release that carries it comments on the issue with the version to
96
+ upgrade to. Upgrade, remove your workaround, and you are done.
97
+
98
+ Do not wait silently and do not quietly work around Atlas in your project. The issue is how the
99
+ problem gets fixed for every project that uses it.
100
+
101
+ ## Migrating from the submodule
102
+
103
+ Do this once per project. Check first that the package is on npm:
104
+ `npm view @crvouga/atlas version` prints a version.
105
+
106
+ 1. **Save anything that only exists in the submodule.** Nothing may be pushed from it any more.
107
+
108
+ ```sh
109
+ git -C vendor/atlas status --short
110
+ git -C vendor/atlas log --oneline origin/main..HEAD
111
+ ```
112
+
113
+ If either prints something, save it as a patch and attach it to an issue that describes what it
114
+ is for, so it is redone in Atlas instead of being lost:
115
+
116
+ ```sh
117
+ git -C vendor/atlas fetch origin main
118
+ git -C vendor/atlas diff origin/main > atlas-local-changes.patch
119
+ ```
120
+
121
+ 2. **Remove the submodule.**
122
+
123
+ ```sh
124
+ git submodule deinit -f vendor/atlas
125
+ git rm -f vendor/atlas
126
+ rm -rf .git/modules/vendor/atlas
127
+ ```
128
+
129
+ `git rm` also removes its entry from `.gitmodules`; delete the file if it is now empty.
130
+
131
+ 3. **Remove the workspace link.** Delete the `vendor/atlas/packages/*` entry from your workspace
132
+ list (`pnpm-workspace.yaml`, or `workspaces` in `package.json`).
133
+
134
+ 4. **Depend on the one released package.** In every `package.json`, remove each
135
+ `"@crvouga/atlas-…": "workspace:*"` entry, and in each of those package directories add the
136
+ package with your project's package manager:
137
+
138
+ ```sh
139
+ bun add -d @crvouga/atlas@latest # or: pnpm add -D @crvouga/atlas@latest
140
+ ```
141
+
142
+ 5. **Rename the imports.** The separate packages are now paths of `@crvouga/atlas`:
143
+
144
+ | Before | After |
145
+ | --- | --- |
146
+ | `@crvouga/atlas-playwright` | `@crvouga/atlas/playwright` |
147
+ | `@crvouga/atlas-bun` | `@crvouga/atlas/bun` |
148
+ | `@crvouga/atlas-webdriver` | `@crvouga/atlas/webdriver` |
149
+ | `@crvouga/atlas-detox` | `@crvouga/atlas/detox` |
150
+ | `@crvouga/atlas-vitest` | `@crvouga/atlas/vitest` |
151
+ | `@crvouga/atlas-schema` | `@crvouga/atlas/schema` |
152
+ | `@crvouga/atlas-schema/schemas/<file>` | `@crvouga/atlas/schemas/<file>` |
153
+ | `@crvouga/atlas-reports/<module>` | `@crvouga/atlas/reports/<module>` |
154
+ | `@crvouga/atlas client` (the `atlas client` command) | installed with `@crvouga/atlas` |
155
+
156
+ `@crvouga/atlas`, `@crvouga/atlas/spec` and `@crvouga/atlas/signals` are unchanged. One pass
157
+ over a project's sources does the rest:
158
+
159
+ ```sh
160
+ git grep -lE "@crvouga/atlas-(playwright|bun|webdriver|detox|vitest|schema|reports)" -- '*.ts' '*.tsx' '*.mts' '*.mjs' \
161
+ | xargs perl -pi -e 's{\@crvouga/atlas-schema/schemas/}{\@crvouga/atlas/schemas/}g; s{\@crvouga/atlas-(playwright|bun|webdriver|detox|vitest|schema|reports)\b}{\@crvouga/atlas/$1}g'
162
+ ```
163
+
164
+ 6. **Install and check.**
165
+
166
+ ```sh
167
+ bun install # or: pnpm install
168
+ ```
169
+
170
+ Run your type-check and your Atlas lint, run and visualizer commands. Anything that worked
171
+ through the submodule and does not work from npm is a bug: [file it](reporting-issues.md).
172
+
173
+ 7. **Commit** the removed submodule, the workspace file, the manifests, the renamed imports and the
174
+ lockfile together. Remove any instructions in your project's own agent guidance that describe
175
+ editing Atlas through `vendor/atlas`, and point them at this guide.