@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,462 @@
1
+ /**
2
+ * @module Layer document and report status schemas
3
+ *
4
+ * The stable evidence format. A layer is the one unit of evidence every producer writes and every reader combines;
5
+ * this module also holds the input a producer hands to the publisher (`PublishChecksSchema`), the spec set a report is
6
+ * laid over (`SpecSetSchema`) and the JSON `atlas report status` prints (`ReportStatusSchema`). Reports are never
7
+ * stored
8
+ * as a whole; they are computed by layering.
9
+ *
10
+ * A layer is one focused recording: the checks one producer ran, on one environment, from one
11
+ * version and branch. It is immutable and addressed by its content.
12
+ *
13
+ * Compatibility, which is the point of this file:
14
+ * - Within a schema major version a change only adds optional fields. Readers ignore fields they
15
+ * do not know (every object here is loose), so an old reader reads a newer minor layer.
16
+ * - The closed enumerations (`status`, `freshness`) change only with a new major version.
17
+ * - `schemaVersion` is the major version. A reader that is older than a layer says so; it never
18
+ * guesses.
19
+ *
20
+ * Extensibility, which is what makes one format fit any test framework (docs/extending.md):
21
+ * - Evidence is open. Beyond its outcome a check may carry attachments of any media type, timeline
22
+ * steps, annotations, retry attempts, tags, labels, links and namespaced `extensions`. Every one of
23
+ * them is optional, so a layer without them is as valid as it ever was.
24
+ * - Vocabularies are open strings (`role`, `kind`, `type`, `level`, a step's `status`). The values
25
+ * documented here are conventions, not a list: a reader shows what it does not know in a generic way.
26
+ * - `extensions` is where a producer or a tool puts structured data of its own, under a key it owns
27
+ * (`com.example.coverage`). Readers keep it and never fail on it.
28
+ * - Evidence never decides a result. A reader that cannot read a piece of evidence drops that piece and
29
+ * keeps the check, its status and its place in the report.
30
+ *
31
+ * @see docs/report-contract.md
32
+ * @see docs/extending.md
33
+ */
34
+ import { z } from 'zod/v4';
35
+ /**
36
+ * The major version of the layer format, written as `schemaVersion` in every layer. `parseLayerDocument` reads a
37
+ * layer without the field as this version and refuses any other.
38
+ */
39
+ export const LAYER_SCHEMA_VERSION = 1;
40
+ /** Outcomes of a check. Anything not `passed` is not evidence of success. */
41
+ export const CHECK_STATUSES = ['passed', 'failed', 'running', 'not-run'];
42
+ /**
43
+ * Zod enum over `CHECK_STATUSES`, the closed vocabulary of a check's and an attempt's `status`. It changes only with
44
+ * a new `schemaVersion`.
45
+ */
46
+ export const CheckStatusSchema = z.enum(CHECK_STATUSES);
47
+ /**
48
+ * Why a layer's origin is advisory: `modified` (recorded from a checkout with uncommitted changes) or `unknown`
49
+ * (origin not captured). Absent on a layer from a clean commit. It never changes a status. A closed vocabulary: it
50
+ * changes only with a new `schemaVersion`.
51
+ */
52
+ export const FRESHNESS = ['unknown', 'modified'];
53
+ /**
54
+ * A number a check measured, such as a latency or a size, with its unit and an optional allowance. A measurement over
55
+ * its `limit` is reported and never changes the check's status.
56
+ */
57
+ export const MeasurementSchema = z.looseObject({
58
+ name: z.string().min(1),
59
+ value: z.number().describe('A finite number'),
60
+ unit: z.string(),
61
+ limit: z.number().optional().describe('The allowance. A measurement over it is reported, and never fails the check by itself')
62
+ });
63
+ /**
64
+ * Structured data of a producer's or tool's own, by namespace: `{ "com.example.coverage": { … } }`.
65
+ * Use a name you own (a reverse domain, or your tool's name). Readers preserve it and never fail on it.
66
+ */
67
+ export const ExtensionsSchema = z.record(z.string().min(1), z.unknown());
68
+ /** A link attached to a layer, part, check or annotation: a URL, an optional name and why it is linked. */
69
+ export const LinkSchema = z.looseObject({
70
+ url: z.string().min(1),
71
+ name: z.string().optional(),
72
+ rel: z.string().optional().describe('Why it is linked, in an open vocabulary: issue, run, trace, docs, source…')
73
+ });
74
+ /** Where in a check something happened: at a step, and/or this long after the check started. */
75
+ export const MomentSchema = z.looseObject({
76
+ step: z.string().optional().describe('The `id` of a step'),
77
+ offsetMs: z.number().nonnegative().optional()
78
+ });
79
+ /**
80
+ * A file or a value that goes with a result: a screenshot, a video, a trace, a log, a DOM or accessibility
81
+ * snapshot, a HAR, a coverage report, a diff, anything. `contentType` says how to read it; `role` says what
82
+ * it is for, in an open vocabulary (`screenshot`, `video`, `trace`, `log`, `snapshot`, `har`, `coverage`,
83
+ * `diff`, `report`…). The bytes are in the layer (`bundleKey`), somewhere else (`uri`), or small enough to
84
+ * sit inline (`text`).
85
+ */
86
+ export const AttachmentSchema = z.looseObject({
87
+ id: z.string().optional().describe('Lets another attachment, step or annotation refer to this one'),
88
+ name: z.string().min(1),
89
+ role: z.string().optional(),
90
+ contentType: z.string().optional().describe('An IANA media type. Absent means application/octet-stream'),
91
+ bundleKey: z.string().optional().describe('The key of its bytes in the layer'),
92
+ uri: z.string().optional().describe('Where else to read it: an https URL, or a path a host understands'),
93
+ text: z.string().optional().describe('A small UTF-8 value, inline'),
94
+ bytes: z.number().int().nonnegative().optional(),
95
+ sha256: z.string().optional(),
96
+ width: z.number().nonnegative().optional(),
97
+ height: z.number().nonnegative().optional(),
98
+ durationMs: z.number().nonnegative().optional().describe('For video and audio'),
99
+ description: z.string().optional(),
100
+ at: MomentSchema.optional(),
101
+ poster: z.string().optional().describe('The `id` of an attachment that stands for this one before it is opened'),
102
+ captions: z.array(z.string()).optional().describe('The `id`s of attachments (WebVTT, SRT) that caption this one'),
103
+ extensions: ExtensionsSchema.optional()
104
+ });
105
+ /** A note about a result: a warning, a deprecation, a coverage figure, an accessibility finding, anything. */
106
+ export const AnnotationSchema = z.looseObject({
107
+ type: z.string().min(1).describe('An open vocabulary: note, warning, deprecation, issue, accessibility, coverage…'),
108
+ message: z.string(),
109
+ level: z.string().optional().describe('Conventionally info, warning or error. Anything else is shown as a note'),
110
+ at: MomentSchema.optional(),
111
+ source: z.looseObject({ file: z.string().optional(), line: z.number().int().optional(), column: z.number().int().optional() }).optional(),
112
+ links: z.array(LinkSchema).optional(),
113
+ extensions: ExtensionsSchema.optional()
114
+ });
115
+ /**
116
+ * One entry on a check's timeline. Steps are a flat list: nest them with `parentId`, order them by
117
+ * `offsetMs`. Whatever a framework calls its steps (actions, hooks, requests, spans), they fit.
118
+ */
119
+ export const StepSchema = z.looseObject({
120
+ id: z.string().optional(),
121
+ parentId: z.string().optional(),
122
+ name: z.string(),
123
+ kind: z.string().optional().describe('An open vocabulary: action, assertion, hook, request, span, given, when, then…'),
124
+ status: z.string().optional().describe('Conventionally passed, failed, skipped. Anything else is shown as it is'),
125
+ offsetMs: z.number().nonnegative().optional().describe('When it started, after the check did'),
126
+ durationMs: z.number().nonnegative().optional(),
127
+ detail: z.string().optional(),
128
+ attachments: z.array(AttachmentSchema).optional(),
129
+ annotations: z.array(AnnotationSchema).optional(),
130
+ extensions: ExtensionsSchema.optional()
131
+ });
132
+ /** One try of a check that was retried. The check's own status is the last one. */
133
+ export const AttemptSchema = z.looseObject({
134
+ index: z.number().int().nonnegative(),
135
+ status: CheckStatusSchema,
136
+ durationMs: z.number().nonnegative().optional(),
137
+ startedAtMs: z.number().nonnegative().optional(),
138
+ detail: z.string().optional(),
139
+ steps: z.array(StepSchema).optional(),
140
+ attachments: z.array(AttachmentSchema).optional(),
141
+ annotations: z.array(AnnotationSchema).optional(),
142
+ extensions: ExtensionsSchema.optional()
143
+ });
144
+ /** What may be attached at any level: a layer, a part, a check. Every field is optional and open. */
145
+ const evidenceShape = {
146
+ tags: z.array(z.string()).optional().describe('Free labels to filter and group by: smoke, slow, flaky…'),
147
+ labels: z.record(z.string(), z.string()).optional().describe('Facts about the result, not part of its identity: owner, severity, browser, os, build. Unlike `parameters` they never split a result into another slot'),
148
+ links: z.array(LinkSchema).optional(),
149
+ attachments: z.array(AttachmentSchema).optional(),
150
+ annotations: z.array(AnnotationSchema).optional(),
151
+ extensions: ExtensionsSchema.optional()
152
+ };
153
+ /**
154
+ * One check: the unit that has a status, such as a Gherkin scenario, a test case or a lint rule. Its `id` is stable
155
+ * across layers; with the layer's producer, the part's kind, the spec, the environment and the parameters it names
156
+ * the slot a result fills, and the newest completed result of a slot wins. It carries the outcome (`status`,
157
+ * `detail`, `measurements`) and, optionally, evidence (tags, labels, links, attachments, annotations, steps,
158
+ * attempts, extensions) that never decides the result.
159
+ */
160
+ export const CheckSchema = z.looseObject({
161
+ id: z.string().min(1).describe("The check's stable identity within its producer. The same check must keep the same id in every layer, or layers cannot replace one another"),
162
+ title: z.string(),
163
+ status: CheckStatusSchema,
164
+ detail: z.string().default('').describe('Why it failed, or what was measured'),
165
+ specPath: z.string().optional().describe('The spec this check belongs to, relative to the repository, such as specs/join.feature'),
166
+ measurements: z.array(MeasurementSchema).default([]),
167
+ durationMs: z.number().nonnegative().optional().describe('How long the check took, when the producer measured it'),
168
+ ...evidenceShape,
169
+ steps: z.array(StepSchema).optional().describe("The check's timeline"),
170
+ attempts: z.array(AttemptSchema).optional().describe('Every try, when the check was retried')
171
+ });
172
+ /**
173
+ * A spec a layer was recorded against: its path, domain, kind and title, and an advisory fingerprint of its text so a
174
+ * reader can warn when the spec changed since.
175
+ */
176
+ export const SpecEntrySchema = z.looseObject({
177
+ path: z.string().min(1),
178
+ domain: z.string(),
179
+ kind: z.string(),
180
+ title: z.string(),
181
+ fingerprint: z.string().optional().describe('Identity of the spec text the layer was recorded against, to warn when the spec changed since')
182
+ });
183
+ /**
184
+ * A group of checks inside a layer, with an open `kind` (`behavior`, `performance`, `accessibility`…) that is part of
185
+ * the slot a check fills. `publishChecks` writes a layer with one part. Parts may carry evidence of their own.
186
+ */
187
+ export const ReportPartSchema = z.looseObject({
188
+ freshness: z.enum(FRESHNESS).optional(),
189
+ parameters: z.record(z.string(), z.string()).optional(),
190
+ sha: z.string().default('').describe('Repeats the layer sha; readers use the layer'),
191
+ id: z.string().min(1),
192
+ kind: z.string().min(1).describe('An open category: behavior, performance, accessibility… A new kind needs no change to a reader'),
193
+ title: z.string(),
194
+ recordedAtMs: z.number().nonnegative(),
195
+ checks: z.array(CheckSchema),
196
+ ...evidenceShape
197
+ });
198
+ const RecordedTestSchema = z.looseObject({
199
+ testId: z.string().min(1),
200
+ title: z.string(),
201
+ status: z.enum(['passed', 'failed', 'skipped']),
202
+ system: z.string().default(''),
203
+ runtime: z.string().default(''),
204
+ seed: z.string().default(''),
205
+ durationMs: z.number().nonnegative().default(0)
206
+ });
207
+ /** A suite that recorded timelines and captured files, beside its checks. Absent for a layer of plain checks. */
208
+ export const LayerSourceSchema = z.looseObject({
209
+ source: z.string().min(1),
210
+ packageDir: z.string(),
211
+ bucket: z.string(),
212
+ status: z.enum(['passed', 'failed', 'skipped']),
213
+ updatedAtMs: z.number().nonnegative(),
214
+ environment: z.string().optional(),
215
+ parameters: z.record(z.string(), z.string()).optional(),
216
+ evidence: z.array(z.looseObject({ kind: z.string(), title: z.string(), checks: z.array(CheckSchema) })).optional(),
217
+ tests: z.array(RecordedTestSchema)
218
+ });
219
+ /**
220
+ * Where the recorded tests of a suite live in the store: in the layer's own bundle (`layer`), or at the older address
221
+ * of a commit and a source name (`commit`).
222
+ */
223
+ export const RecordingAddressSchema = z.union([
224
+ z.looseObject({ type: z.literal('layer') }),
225
+ z.looseObject({ type: z.literal('commit'), sha: z.string().min(1), source: z.string().min(1) })
226
+ ]);
227
+ /**
228
+ * The captured files of a layer by file key (`attachments/<sha256>` for attachments): each file's media type and the
229
+ * byte ranges (`blob` store key, `offset` and `size` in the decompressed blob) whose concatenation is the file.
230
+ * Written last when a layer is published.
231
+ */
232
+ export const BundleIndexSchema = z.record(z.string(), z.looseObject({
233
+ contentType: z.string(),
234
+ parts: z.array(z.looseObject({ blob: z.string(), offset: z.number().int().nonnegative(), size: z.number().int().nonnegative() }))
235
+ }));
236
+ /** Pattern of a layer id, a spec-set id or a content digest: 64 lowercase hexadecimal digits (a SHA-256). */
237
+ export const LAYER_ID = /^[0-9a-f]{64}$/;
238
+ /**
239
+ * `layers/manifests/<id>.json`. The id is the SHA-256 of the document without it, so two producers
240
+ * that record the same thing write the same layer, and a retried publish changes nothing.
241
+ */
242
+ export const LayerDocumentSchema = z.looseObject({
243
+ schemaVersion: z.literal(LAYER_SCHEMA_VERSION).describe('The major version of this contract'),
244
+ id: z.string().regex(LAYER_ID).describe('64 lowercase hex digits. Opaque to readers'),
245
+ producer: z.string().min(1).describe('A stable name for the suite or tool. With the check id, environment and parameters it picks the slot a layer fills'),
246
+ recordedAtMs: z.number().nonnegative().describe('When the checks ran, in epoch milliseconds. The newest completed result wins its slot'),
247
+ sha: z.string().nullable().describe('The commit the checks ran against. Provenance only; it never partitions a report'),
248
+ branch: z.string().nullable().describe('Provenance only'),
249
+ runUrl: z.string().nullable().describe('Where to read the CI run that produced it'),
250
+ environment: z.string().nullable().optional().describe('The client that was checked: desktop-web, mobile-web, ios, android, or any other lowercase name'),
251
+ parameters: z.record(z.string(), z.string()).default({}).describe('Other choices that make a result its own slot, such as a device size'),
252
+ freshness: z.enum(FRESHNESS).optional().describe('`modified`: recorded from a checkout with uncommitted changes. `unknown`: origin not captured'),
253
+ specs: z.array(SpecEntrySchema).default([]),
254
+ parts: z.array(ReportPartSchema),
255
+ source: LayerSourceSchema.nullable().default(null),
256
+ recording: RecordingAddressSchema.nullable().default(null),
257
+ bundle: BundleIndexSchema.default({}),
258
+ ...evidenceShape
259
+ });
260
+ /**
261
+ * Evidence is decoration, never the result. A reader that meets a piece of evidence it cannot read (a
262
+ * malformed attachment, a field of the wrong type) drops that piece and keeps the check, its status and
263
+ * its place in the report. The strict schemas above are what producers validate against; this is how
264
+ * readers stay forgiving.
265
+ */
266
+ function lenientList(value, schema, prepare = (item) => item) {
267
+ if (!Array.isArray(value))
268
+ return undefined;
269
+ return value.flatMap((item) => {
270
+ const parsed = schema.safeParse(prepare(item));
271
+ return parsed.success ? [parsed.data] : [];
272
+ });
273
+ }
274
+ const object = (value) => (typeof value === 'object' && value !== null && !Array.isArray(value) ? value : null);
275
+ function lenientEvidence(holder, nested = []) {
276
+ const out = { ...holder };
277
+ const set = (key, value) => { if (value === undefined)
278
+ delete out[key];
279
+ else
280
+ out[key] = value; };
281
+ if ('tags' in out)
282
+ set('tags', lenientList(out.tags, z.string()));
283
+ if ('links' in out)
284
+ set('links', lenientList(out.links, LinkSchema));
285
+ if ('attachments' in out)
286
+ set('attachments', lenientList(out.attachments, AttachmentSchema));
287
+ if ('annotations' in out)
288
+ set('annotations', lenientList(out.annotations, AnnotationSchema));
289
+ if ('labels' in out)
290
+ set('labels', z.record(z.string(), z.string()).safeParse(out.labels).data);
291
+ if ('extensions' in out)
292
+ set('extensions', ExtensionsSchema.safeParse(out.extensions).data);
293
+ if (nested.includes('steps') && 'steps' in out)
294
+ set('steps', lenientList(out.steps, StepSchema, (item) => { const step = object(item); return step ? lenientEvidence(step) : item; }));
295
+ if (nested.includes('attempts') && 'attempts' in out)
296
+ set('attempts', lenientList(out.attempts, AttemptSchema, (item) => { const attempt = object(item); return attempt ? lenientEvidence(attempt, ['steps']) : item; }));
297
+ return out;
298
+ }
299
+ function lenientLayer(raw) {
300
+ const layer = lenientEvidence(raw);
301
+ if (Array.isArray(layer.parts)) {
302
+ layer.parts = layer.parts.map((part) => {
303
+ const found = object(part);
304
+ if (!found)
305
+ return part;
306
+ const next = lenientEvidence(found);
307
+ if (Array.isArray(next.checks))
308
+ next.checks = next.checks.map((check) => { const c = object(check); return c ? lenientEvidence(c, ['steps', 'attempts']) : check; });
309
+ return next;
310
+ });
311
+ }
312
+ return layer;
313
+ }
314
+ /**
315
+ * Reads a layer manifest of any age and returns it, or the reason it cannot be read; it never throws. Layers written
316
+ * before `schemaVersion` existed are version 1. A layer of a newer major version is refused by name ("Upgrade
317
+ * @crvouga/atlas to read it") rather than half understood. Evidence the reader cannot read (a malformed attachment,
318
+ * step, annotation, link, tag, label or extension) is dropped and the check keeps its status and place; anything
319
+ * else that fails the schema refuses the whole layer, naming the first problem by its path. Callers treat a refused
320
+ * layer as unknown, never as passed.
321
+ *
322
+ * @see docs/report-contract.md
323
+ *
324
+ * @example
325
+ * ```ts
326
+ * import { parseLayerDocument } from '@crvouga/atlas/schema';
327
+ *
328
+ * const parsed = parseLayerDocument(JSON.parse(text));
329
+ * if (!parsed.ok) throw new Error(parsed.reason);
330
+ * for (const part of parsed.layer.parts) console.log(part.kind, part.checks.length);
331
+ * ```
332
+ */
333
+ export function parseLayerDocument(raw) {
334
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
335
+ return { ok: false, reason: 'A layer is a JSON object' };
336
+ const version = raw.schemaVersion;
337
+ if (version !== undefined && version !== LAYER_SCHEMA_VERSION) {
338
+ return {
339
+ ok: false,
340
+ reason: typeof version === 'number' && version > LAYER_SCHEMA_VERSION
341
+ ? `Written with layer schema version ${version}; this Atlas reads version ${LAYER_SCHEMA_VERSION}. Upgrade @crvouga/atlas to read it`
342
+ : `Unsupported layer schemaVersion ${JSON.stringify(version)}`
343
+ };
344
+ }
345
+ const parsed = LayerDocumentSchema.safeParse(lenientLayer({ ...raw, ...(version === undefined ? { schemaVersion: LAYER_SCHEMA_VERSION } : {}) }));
346
+ if (parsed.success)
347
+ return { ok: true, layer: parsed.data };
348
+ const issue = parsed.error.issues[0];
349
+ return { ok: false, reason: `Not a valid layer: ${issue ? `${issue.path.join('.') || '(root)'}: ${issue.message}` : 'unknown problem'}` };
350
+ }
351
+ /**
352
+ * An attachment as a producer hands it over, before the publisher stores its bytes. Give the bytes as
353
+ * `path` (a file, read by the CLI), `base64`, `data` (from code), or `text`; the publisher stores them in
354
+ * the layer, fills in `bundleKey`, `bytes` and `sha256`, and removes these four.
355
+ */
356
+ export const AttachmentInputSchema = AttachmentSchema.extend({
357
+ path: z.string().optional().describe('A file to read, relative to the file this is in. Used by `atlas report publish`'),
358
+ base64: z.string().optional(),
359
+ data: z.custom((value) => value instanceof Uint8Array).optional().describe('From code: the bytes')
360
+ });
361
+ const StepInputSchema = StepSchema.extend({ attachments: z.array(AttachmentInputSchema).optional() });
362
+ const AttemptInputSchema = AttemptSchema.extend({ steps: z.array(StepInputSchema).optional(), attachments: z.array(AttachmentInputSchema).optional() });
363
+ const CheckInputSchema = CheckSchema.extend({
364
+ attachments: z.array(AttachmentInputSchema).optional(),
365
+ steps: z.array(StepInputSchema).optional(),
366
+ attempts: z.array(AttemptInputSchema).optional()
367
+ });
368
+ /**
369
+ * The checks of a layer as a producer hands them to the publisher (`publishChecks`, `atlas report publish --checks`),
370
+ * before the publisher fills in the rest: `id`, `schemaVersion`, the part around the checks and the bundle of
371
+ * attachment bytes. It is the whole integration surface of a producer that has no timelines to record. `kind` names
372
+ * the part and defaults to `checks`. Attachments may carry their bytes (`AttachmentInputSchema`). Emitted as
373
+ * `publish-checks.schema.json`.
374
+ */
375
+ export const PublishChecksSchema = z.looseObject({
376
+ producer: z.string().min(1),
377
+ checks: z.array(CheckInputSchema),
378
+ kind: z.string().min(1).default('checks'),
379
+ title: z.string().optional(),
380
+ recordedAtMs: z.number().nonnegative(),
381
+ sha: z.string().nullable().default(null),
382
+ branch: z.string().nullable().default(null),
383
+ runUrl: z.string().nullable().default(null),
384
+ environment: z.string().nullable().optional(),
385
+ parameters: z.record(z.string(), z.string()).default({}),
386
+ freshness: z.enum(FRESHNESS).optional(),
387
+ specs: z.array(SpecEntrySchema).default([]),
388
+ tags: evidenceShape.tags,
389
+ labels: evidenceShape.labels,
390
+ links: evidenceShape.links,
391
+ attachments: z.array(AttachmentInputSchema).optional().describe('Attached to the whole layer: a CI log, a coverage report, a trace archive'),
392
+ annotations: evidenceShape.annotations,
393
+ extensions: evidenceShape.extensions
394
+ });
395
+ const CountsSchema = z.object({
396
+ passed: z.number().int().nonnegative(),
397
+ failed: z.number().int().nonnegative(),
398
+ running: z.number().int().nonnegative(),
399
+ 'not-run': z.number().int().nonnegative(),
400
+ total: z.number().int().nonnegative()
401
+ });
402
+ /** The `schemaVersion` of the `ReportStatus` JSON, currently 1. */
403
+ export const REPORT_STATUS_SCHEMA_VERSION = 1;
404
+ /**
405
+ * What `atlas report status --format json` prints: the combined report in numbers, and whether it
406
+ * passes. `ok` is the gate: nothing failed, nothing is still running, nothing could not be read,
407
+ * and every required environment has results.
408
+ */
409
+ export const ReportStatusSchema = z.looseObject({
410
+ schemaVersion: z.literal(REPORT_STATUS_SCHEMA_VERSION),
411
+ ok: z.boolean(),
412
+ reasons: z.array(z.string()).describe('Why `ok` is false, in words. Empty when it is true'),
413
+ checks: CountsSchema,
414
+ byEnvironment: z.record(z.string(), CountsSchema),
415
+ layers: z.number().int().nonnegative().describe('Distinct layers read, across all backends'),
416
+ backends: z.array(z.object({ id: z.string(), label: z.string(), available: z.boolean() })),
417
+ notices: z.array(z.string()).describe('What could not be read. Any notice fails the gate: unknown is not passed'),
418
+ specsWithoutEvidence: z.array(z.string()).describe('Specs of the outline with no result at all. The outline is `--specs <dir>`, or else the specs the layers recorded'),
419
+ specs: z.array(z.looseObject({
420
+ path: z.string().nullable().describe('Null for checks that name no spec in the outline'),
421
+ title: z.string(),
422
+ kind: z.string(),
423
+ checks: CountsSchema,
424
+ byEnvironment: z.record(z.string(), CountsSchema)
425
+ })).describe('The outcome of each spec, so a dashboard needs nothing else'),
426
+ failing: z.array(z.looseObject({
427
+ spec: z.string().nullable(),
428
+ check: z.string(),
429
+ title: z.string(),
430
+ status: z.enum(['failed', 'running']),
431
+ environment: z.string().nullable(),
432
+ producer: z.string(),
433
+ branch: z.string().nullable(),
434
+ sha: z.string().nullable(),
435
+ layer: z.string(),
436
+ backend: z.string(),
437
+ runUrl: z.string().nullable(),
438
+ detail: z.string()
439
+ })).describe('Each slot whose newest completed result failed, or that is still running')
440
+ });
441
+ /**
442
+ * The specs of one version of a project, as published: what the report is laid over. Layers of
443
+ * evidence say what ran; a spec set says what the specs were. Like layers, spec sets are immutable and
444
+ * never replace each other: the node shows the newest one of the branch you choose.
445
+ */
446
+ export const SpecSetSchema = z.looseObject({
447
+ schemaVersion: z.literal(1),
448
+ id: z.string().regex(LAYER_ID).describe('SHA-256 of the branch, commit, freshness and the digest of every file: the same specs from the same commit are the same set'),
449
+ branch: z.string().nullable(),
450
+ sha: z.string().nullable(),
451
+ recordedAtMs: z.number().nonnegative().describe('For a clean checkout, the commit time; for a modified one, when it was published'),
452
+ freshness: z.enum(FRESHNESS).optional(),
453
+ files: z.array(z.looseObject({
454
+ path: z.string().min(1).describe('`specs/<path inside the specs directory>`, the name a check uses in `specPath`'),
455
+ digest: z.string().regex(LAYER_ID).describe('SHA-256 of the file. Its text is at layers/specs/blobs/<digest>.txt'),
456
+ fingerprint: z.string().describe('The advisory fingerprint layers record, to warn when a spec changed since they ran'),
457
+ kind: z.string(),
458
+ title: z.string(),
459
+ domain: z.string(),
460
+ bytes: z.number().int().nonnegative()
461
+ }))
462
+ });
@@ -0,0 +1,123 @@
1
+ /** @module Live run protocol
2
+ * A live run is a producer lease, separate from immutable report layers. Server receipt times determine liveness.
3
+ * Expiration means interrupted, never passed; completed check results retain the stable layer contract.
4
+ */
5
+ import { z } from 'zod/v4';
6
+ /** Small progress messages: no attachment bytes, bounded step history and text. */
7
+ export declare const LiveCheckSchema: z.ZodObject<{
8
+ id: z.ZodString;
9
+ title: z.ZodString;
10
+ status: z.ZodEnum<{
11
+ passed: "passed";
12
+ failed: "failed";
13
+ running: "running";
14
+ "not-run": "not-run";
15
+ }>;
16
+ detail: z.ZodDefault<z.ZodString>;
17
+ specPath: z.ZodOptional<z.ZodString>;
18
+ durationMs: z.ZodOptional<z.ZodNumber>;
19
+ steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
20
+ name: z.ZodString;
21
+ status: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>>>;
23
+ }, z.core.$strip>;
24
+ /** The producer starts one UUID-named run. Identity stays fixed for its lifetime. */
25
+ export declare const LiveRunStartSchema: z.ZodObject<{
26
+ id: z.ZodString;
27
+ producer: z.ZodString;
28
+ title: z.ZodOptional<z.ZodString>;
29
+ environment: z.ZodOptional<z.ZodString>;
30
+ branch: z.ZodOptional<z.ZodString>;
31
+ sha: z.ZodOptional<z.ZodString>;
32
+ plannedChecks: z.ZodOptional<z.ZodNumber>;
33
+ }, z.core.$strip>;
34
+ /** Ordered deltas. A retried sequence must have identical content; terminal runs never accept more progress. */
35
+ export declare const LiveRunUpdateSchema: z.ZodObject<{
36
+ sequence: z.ZodNumber;
37
+ checks: z.ZodDefault<z.ZodArray<z.ZodObject<{
38
+ id: z.ZodString;
39
+ title: z.ZodString;
40
+ status: z.ZodEnum<{
41
+ passed: "passed";
42
+ failed: "failed";
43
+ running: "running";
44
+ "not-run": "not-run";
45
+ }>;
46
+ detail: z.ZodDefault<z.ZodString>;
47
+ specPath: z.ZodOptional<z.ZodString>;
48
+ durationMs: z.ZodOptional<z.ZodNumber>;
49
+ steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
50
+ name: z.ZodString;
51
+ status: z.ZodOptional<z.ZodString>;
52
+ }, z.core.$strip>>>;
53
+ }, z.core.$strip>>>;
54
+ finish: z.ZodOptional<z.ZodEnum<{
55
+ completed: "completed";
56
+ interrupted: "interrupted";
57
+ }>>;
58
+ reason: z.ZodOptional<z.ZodString>;
59
+ }, z.core.$strip>;
60
+ /** The bounded live feed response; completed and interrupted runs remain visible as recent history. */
61
+ export declare const LiveRunSchema: z.ZodObject<{
62
+ id: z.ZodString;
63
+ producer: z.ZodString;
64
+ title: z.ZodOptional<z.ZodString>;
65
+ environment: z.ZodOptional<z.ZodString>;
66
+ branch: z.ZodOptional<z.ZodString>;
67
+ sha: z.ZodOptional<z.ZodString>;
68
+ plannedChecks: z.ZodOptional<z.ZodNumber>;
69
+ status: z.ZodEnum<{
70
+ running: "running";
71
+ completed: "completed";
72
+ interrupted: "interrupted";
73
+ }>;
74
+ startedAtMs: z.ZodNumber;
75
+ lastHeartbeatAtMs: z.ZodNumber;
76
+ lastProgressAtMs: z.ZodNumber;
77
+ finishedAtMs: z.ZodOptional<z.ZodNumber>;
78
+ reason: z.ZodOptional<z.ZodString>;
79
+ sequence: z.ZodNumber;
80
+ completed: z.ZodNumber;
81
+ passed: z.ZodNumber;
82
+ failed: z.ZodNumber;
83
+ notRun: z.ZodNumber;
84
+ running: z.ZodNumber;
85
+ current: z.ZodArray<z.ZodObject<{
86
+ id: z.ZodString;
87
+ title: z.ZodString;
88
+ status: z.ZodEnum<{
89
+ passed: "passed";
90
+ failed: "failed";
91
+ running: "running";
92
+ "not-run": "not-run";
93
+ }>;
94
+ detail: z.ZodDefault<z.ZodString>;
95
+ specPath: z.ZodOptional<z.ZodString>;
96
+ durationMs: z.ZodOptional<z.ZodNumber>;
97
+ steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
98
+ name: z.ZodString;
99
+ status: z.ZodOptional<z.ZodString>;
100
+ }, z.core.$strip>>>;
101
+ }, z.core.$strip>>;
102
+ recent: z.ZodArray<z.ZodObject<{
103
+ id: z.ZodString;
104
+ title: z.ZodString;
105
+ status: z.ZodEnum<{
106
+ passed: "passed";
107
+ failed: "failed";
108
+ running: "running";
109
+ "not-run": "not-run";
110
+ }>;
111
+ detail: z.ZodDefault<z.ZodString>;
112
+ specPath: z.ZodOptional<z.ZodString>;
113
+ durationMs: z.ZodOptional<z.ZodNumber>;
114
+ steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
115
+ name: z.ZodString;
116
+ status: z.ZodOptional<z.ZodString>;
117
+ }, z.core.$strip>>>;
118
+ }, z.core.$strip>>;
119
+ }, z.core.$strip>;
120
+ /** The shape a producer uses for a progress check. */
121
+ export type LiveCheck = z.input<typeof LiveCheckSchema>;
122
+ /** A server's live run snapshot. */
123
+ export type LiveRun = z.output<typeof LiveRunSchema>;
@@ -0,0 +1,30 @@
1
+ /** @module Live run protocol
2
+ * A live run is a producer lease, separate from immutable report layers. Server receipt times determine liveness.
3
+ * Expiration means interrupted, never passed; completed check results retain the stable layer contract.
4
+ */
5
+ import { z } from 'zod/v4';
6
+ /** Small progress messages: no attachment bytes, bounded step history and text. */
7
+ export const LiveCheckSchema = z.object({
8
+ id: z.string().min(1).max(16384), title: z.string().min(1).max(2048),
9
+ status: z.enum(['running', 'passed', 'failed', 'not-run']), detail: z.string().max(8000).default(''),
10
+ specPath: z.string().max(2048).optional(), durationMs: z.number().finite().nonnegative().optional(),
11
+ steps: z.array(z.object({ name: z.string().max(2048), status: z.string().max(100).optional() })).max(20).optional()
12
+ });
13
+ /** The producer starts one UUID-named run. Identity stays fixed for its lifetime. */
14
+ export const LiveRunStartSchema = z.object({
15
+ id: z.string().uuid(), producer: z.string().min(1).max(200), title: z.string().max(2048).optional(),
16
+ environment: z.string().max(200).optional(), branch: z.string().max(500).optional(), sha: z.string().max(200).optional(),
17
+ plannedChecks: z.number().int().nonnegative().max(1_000_000).optional()
18
+ });
19
+ /** Ordered deltas. A retried sequence must have identical content; terminal runs never accept more progress. */
20
+ export const LiveRunUpdateSchema = z.object({
21
+ sequence: z.number().int().positive(), checks: z.array(LiveCheckSchema).max(1000).refine(checks => new Set(checks.map(check => check.id)).size === checks.length, 'Check ids must be unique in a batch').default([]),
22
+ finish: z.enum(['completed', 'interrupted']).optional(), reason: z.string().max(2000).optional()
23
+ });
24
+ /** The bounded live feed response; completed and interrupted runs remain visible as recent history. */
25
+ export const LiveRunSchema = LiveRunStartSchema.extend({
26
+ status: z.enum(['running', 'completed', 'interrupted']), startedAtMs: z.number(), lastHeartbeatAtMs: z.number(), lastProgressAtMs: z.number(),
27
+ finishedAtMs: z.number().optional(), reason: z.string().optional(), sequence: z.number(),
28
+ completed: z.number(), passed: z.number(), failed: z.number(), notRun: z.number(), running: z.number(),
29
+ current: z.array(LiveCheckSchema), recent: z.array(LiveCheckSchema)
30
+ });