@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
@@ -1,8 +1,35 @@
1
+ /**
2
+ * @module Privacy scanning
3
+ *
4
+ * Keeps real personal data out of the media and manifests a run produces and shares: patterns for
5
+ * data that must never appear, an allow-list for synthetic emails, and an allow-list of hosts a run may
6
+ * target. Findings describe what matched without repeating it. These are pure functions of their input;
7
+ * the runner applies them to the text a driver reports after each step and to the finished manifest.
8
+ *
9
+ * @see docs/statecharts.md
10
+ */
1
11
  import type { PrivacyRules } from './run/types.js';
2
12
  /** Defaults that fit any product: no real-looking emails, SSNs or card numbers in media or manifests. */
3
13
  export declare const DEFAULT_PRIVACY: Required<PrivacyRules>;
14
+ /**
15
+ * Combines a project's `PrivacyRules` with `DEFAULT_PRIVACY`: its `deny` and `allowEmails` are added
16
+ * to the defaults, while its `allowHosts`, when given, replaces the default hosts (so list loopback
17
+ * again if you still need it).
18
+ */
4
19
  export declare function mergePrivacy(rules?: PrivacyRules): Required<PrivacyRules>;
5
- /** What in `text` looks like real personal data, described without repeating it. */
20
+ /**
21
+ * Scans `text` for real-looking personal data and returns one description per finding, each
22
+ * prefixed by `where` and never containing the matched text (an email is shortened to its first
23
+ * letter and domain). Flags emails not matching `rules.allowEmails` and anything matching a
24
+ * `rules.deny` pattern. Returns an empty array when the text is clean.
25
+ *
26
+ * @param rules the merged rules (`mergePrivacy`).
27
+ */
6
28
  export declare function privacyFindings(text: string, where: string, rules: Required<PrivacyRules>): string[];
7
- /** Refuse to run against anything but the allowed hosts (loopback by default). */
29
+ /**
30
+ * Throws unless every URL's hostname is in `rules.allowHosts` (loopback by default), so a run
31
+ * cannot touch a real environment by accident.
32
+ *
33
+ * @throws Error naming the first refused host, or a `TypeError` for a URL that does not parse.
34
+ */
8
35
  export declare function assertAllowedTarget(urls: string[], rules: Required<PrivacyRules>): void;
@@ -11,6 +11,11 @@ export const DEFAULT_PRIVACY = {
11
11
  allowEmails: [/@example\.(com|org|net)$/i, /\.(test|example|invalid|localhost|local)$/i],
12
12
  allowHosts: ['127.0.0.1', 'localhost', '::1', '[::1]']
13
13
  };
14
+ /**
15
+ * Combines a project's `PrivacyRules` with `DEFAULT_PRIVACY`: its `deny` and `allowEmails` are added
16
+ * to the defaults, while its `allowHosts`, when given, replaces the default hosts (so list loopback
17
+ * again if you still need it).
18
+ */
14
19
  export function mergePrivacy(rules = {}) {
15
20
  return {
16
21
  deny: [...DEFAULT_PRIVACY.deny, ...(rules.deny ?? [])],
@@ -18,7 +23,14 @@ export function mergePrivacy(rules = {}) {
18
23
  allowHosts: rules.allowHosts ?? DEFAULT_PRIVACY.allowHosts
19
24
  };
20
25
  }
21
- /** What in `text` looks like real personal data, described without repeating it. */
26
+ /**
27
+ * Scans `text` for real-looking personal data and returns one description per finding, each
28
+ * prefixed by `where` and never containing the matched text (an email is shortened to its first
29
+ * letter and domain). Flags emails not matching `rules.allowEmails` and anything matching a
30
+ * `rules.deny` pattern. Returns an empty array when the text is clean.
31
+ *
32
+ * @param rules the merged rules (`mergePrivacy`).
33
+ */
22
34
  export function privacyFindings(text, where, rules) {
23
35
  const findings = [];
24
36
  for (const email of text.match(EMAIL) ?? []) {
@@ -32,7 +44,12 @@ export function privacyFindings(text, where, rules) {
32
44
  findings.push(`${where}: something shaped like ${name}`);
33
45
  return findings;
34
46
  }
35
- /** Refuse to run against anything but the allowed hosts (loopback by default). */
47
+ /**
48
+ * Throws unless every URL's hostname is in `rules.allowHosts` (loopback by default), so a run
49
+ * cannot touch a real environment by accident.
50
+ *
51
+ * @throws Error naming the first refused host, or a `TypeError` for a URL that does not parse.
52
+ */
36
53
  export function assertAllowedTarget(urls, rules) {
37
54
  for (const url of urls) {
38
55
  const host = new URL(url).hostname;
@@ -1,3 +1,13 @@
1
+ /**
2
+ * @module Run report formats
3
+ *
4
+ * Pure converters from a run's manifest (or a chart) to the formats other tools read: JUnit XML, CTRF
5
+ * JSON, WebVTT captions and a Mermaid state diagram. They take plain data, do no I/O and are
6
+ * deterministic. The manifest is read through a minimal structural type, so only the fields named
7
+ * there are required of it.
8
+ *
9
+ * @see docs/statecharts.md
10
+ */
1
11
  import type { MachineConfig } from '../spec/types.js';
2
12
  import type { TimelineEntry } from '../run/types.js';
3
13
  type ManifestLike = {
@@ -23,9 +33,19 @@ type ManifestLike = {
23
33
  }[];
24
34
  }[];
25
35
  };
26
- /** JUnit XML (the format every CI system reads): one test case per path. */
36
+ /**
37
+ * Renders the manifest as JUnit XML (the format every CI system reads): one test case per path,
38
+ * with `classname` the path kind (`journey` or `generated`). A failed path is a `failure` carrying
39
+ * the last attempt's error, a `not-reached` path is `skipped` (with the blocking reason when there is
40
+ * one), and a flaky path passes with a note in `system-out`. The suite time is the run duration in seconds.
41
+ */
27
42
  export declare function toJUnit(manifest: ManifestLike): string;
28
- /** CTRF (Common Test Report Format, https://ctrf.io) JSON. */
43
+ /**
44
+ * Renders the manifest as CTRF (Common Test Report Format, https://ctrf.io) JSON: one test per
45
+ * path, its steps as `steps`. `flaky` paths are `passed` with `flaky: true`, `not-reached` is
46
+ * `skipped`, and the failed path's trace (if any) is attached. Per-test `duration` is always 0:
47
+ * only the run's start and stop times are recorded.
48
+ */
29
49
  export declare function toCtrf(manifest: ManifestLike): {
30
50
  reportFormat: string;
31
51
  specVersion: string;
@@ -62,8 +82,18 @@ export declare function toCtrf(manifest: ManifestLike): {
62
82
  }[];
63
83
  };
64
84
  };
65
- /** WebVTT captions for a clip, one cue per timeline entry. */
85
+ /**
86
+ * Renders WebVTT captions for a clip, one cue per timeline entry. A cue lasts until the next entry
87
+ * (or the clip's end), at least 500 ms and at most 4 s.
88
+ *
89
+ * @param timeline the step's entries, with `atMs` relative to the start of the clip.
90
+ * @param durationMs the clip's length in milliseconds.
91
+ */
66
92
  export declare function toWebVtt(timeline: TimelineEntry[], durationMs: number): string;
67
- /** A Mermaid `stateDiagram-v2` of a machine, with nested and parallel states. */
93
+ /**
94
+ * Renders a machine as a Mermaid `stateDiagram-v2` with nested and parallel states. States get
95
+ * short ids (`s0`, `s1`, ... in order of first use) and keep their names as labels; `:` and `;` in event
96
+ * names are replaced by spaces because Mermaid reads them as syntax. Written as `chart.mmd` in every run.
97
+ */
68
98
  export declare function toMermaid(machine: MachineConfig): string;
69
99
  export {};
@@ -1,6 +1,11 @@
1
1
  import { targetOf } from '../spec/types.js';
2
2
  const xml = (s) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
3
- /** JUnit XML (the format every CI system reads): one test case per path. */
3
+ /**
4
+ * Renders the manifest as JUnit XML (the format every CI system reads): one test case per path,
5
+ * with `classname` the path kind (`journey` or `generated`). A failed path is a `failure` carrying
6
+ * the last attempt's error, a `not-reached` path is `skipped` (with the blocking reason when there is
7
+ * one), and a flaky path passes with a note in `system-out`. The suite time is the run duration in seconds.
8
+ */
4
9
  export function toJUnit(manifest) {
5
10
  const cases = manifest.paths.map((p) => {
6
11
  const body = p.status === 'failed'
@@ -24,7 +29,12 @@ export function toJUnit(manifest) {
24
29
  ''
25
30
  ].join('\n');
26
31
  }
27
- /** CTRF (Common Test Report Format, https://ctrf.io) JSON. */
32
+ /**
33
+ * Renders the manifest as CTRF (Common Test Report Format, https://ctrf.io) JSON: one test per
34
+ * path, its steps as `steps`. `flaky` paths are `passed` with `flaky: true`, `not-reached` is
35
+ * `skipped`, and the failed path's trace (if any) is attached. Per-test `duration` is always 0:
36
+ * only the run's start and stop times are recorded.
37
+ */
28
38
  export function toCtrf(manifest) {
29
39
  const status = (s) => (s === 'passed' ? 'passed' : s === 'failed' ? 'failed' : s === 'flaky' ? 'passed' : 'skipped');
30
40
  const tests = manifest.paths.map((p) => ({
@@ -62,7 +72,13 @@ function vttTime(ms) {
62
72
  const pad = (n, w = 2) => String(n).padStart(w, '0');
63
73
  return `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}.${pad(d.getUTCMilliseconds(), 3)}`;
64
74
  }
65
- /** WebVTT captions for a clip, one cue per timeline entry. */
75
+ /**
76
+ * Renders WebVTT captions for a clip, one cue per timeline entry. A cue lasts until the next entry
77
+ * (or the clip's end), at least 500 ms and at most 4 s.
78
+ *
79
+ * @param timeline the step's entries, with `atMs` relative to the start of the clip.
80
+ * @param durationMs the clip's length in milliseconds.
81
+ */
66
82
  export function toWebVtt(timeline, durationMs) {
67
83
  const cues = timeline.map((e, i) => {
68
84
  const end = Math.min(timeline[i + 1]?.atMs ?? durationMs, e.atMs + 4_000);
@@ -71,7 +87,11 @@ export function toWebVtt(timeline, durationMs) {
71
87
  });
72
88
  return `WEBVTT\n\n${cues.join('\n\n')}\n`;
73
89
  }
74
- /** A Mermaid `stateDiagram-v2` of a machine, with nested and parallel states. */
90
+ /**
91
+ * Renders a machine as a Mermaid `stateDiagram-v2` with nested and parallel states. States get
92
+ * short ids (`s0`, `s1`, ... in order of first use) and keep their names as labels; `:` and `;` in event
93
+ * names are replaced by spaces because Mermaid reads them as syntax. Written as `chart.mmd` in every run.
94
+ */
75
95
  export function toMermaid(machine) {
76
96
  const ids = new Map();
77
97
  const id = (name) => {
@@ -1,8 +1,23 @@
1
+ /**
2
+ * @module Markdown chart map
3
+ *
4
+ * Renders a chart (usually the composed product) as a Markdown document for the people who own the
5
+ * product, not for developers: plain Markdown with internal links, so it renders on any code host
6
+ * and diffs with the chart. Pure and deterministic.
7
+ */
1
8
  import type { Journey, MachineConfig } from '../spec/types.js';
2
9
  /**
3
10
  * A readable map of a chart for the people who own the product: one section per area (parallel
4
11
  * regions apart), each state with what it means, what the user sees, and every event that can
5
12
  * happen there and where it leads, then the named journeys. Plain Markdown, so it renders on any
6
13
  * code host and diffs with the chart.
14
+ *
15
+ * Top-level states become sections, and each region of a top-level parallel state gets its own. A
16
+ * `snapshot` is shown only when it contains whitespace (so an identifier-like snapshot is left out),
17
+ * and a state with `confidence: 'assumed'` is marked as unconfirmed. Links use GitHub's heading anchors.
18
+ *
19
+ * @param machine the chart, composed if child charts should be inlined.
20
+ * @param journeys the named journeys to list at the end; none by default.
21
+ * @see docs/statecharts.md
7
22
  */
8
23
  export declare function toMarkdown(machine: MachineConfig, journeys?: Journey[]): string;
@@ -47,6 +47,14 @@ const cell = (text) => text.replace(/\|/g, '\\|').replace(/\s*\n\s*/g, ' ');
47
47
  * regions apart), each state with what it means, what the user sees, and every event that can
48
48
  * happen there and where it leads, then the named journeys. Plain Markdown, so it renders on any
49
49
  * code host and diffs with the chart.
50
+ *
51
+ * Top-level states become sections, and each region of a top-level parallel state gets its own. A
52
+ * `snapshot` is shown only when it contains whitespace (so an identifier-like snapshot is left out),
53
+ * and a state with `confidence: 'assumed'` is marked as unconfirmed. Links use GitHub's heading anchors.
54
+ *
55
+ * @param machine the chart, composed if child charts should be inlined.
56
+ * @param journeys the named journeys to list at the end; none by default.
57
+ * @see docs/statecharts.md
50
58
  */
51
59
  export function toMarkdown(machine, journeys = []) {
52
60
  const sections = sectionsOf(machine);
@@ -1,4 +1,5 @@
1
1
  import type { Driver, EventImplementation, Implementation, StateImplementation } from './types.js';
2
+ /** Options for `combineDrivers`. */
2
3
  export type CombineDriversOptions = {
3
4
  /**
4
5
  * `focused` (default) screenshots the client a state is recognised on; `all` also screenshots
@@ -13,16 +14,36 @@ export type CombineDriversOptions = {
13
14
  * act on (`onClient`, `combineImplementations`), so screenshots and clips come from that client's
14
15
  * screen. Timeline entries are tagged with the client that made them.
15
16
  *
16
- * combineDrivers({ member: webdriverDriver(appiumIos), operator: playwrightDriver(), api: httpDriver(url) })
17
+ * The combined driver's `concurrency` is the smallest of the drivers' (1 for any that give none),
18
+ * its `pacing` is the first driver's that has one, and its name lists `<client>:<driver name>`.
19
+ * If any client fails to open, the ones that did open are closed and the open throws naming that client.
20
+ * Closing returns the first client's trace as `trace` and every client's in `traces`. Without
21
+ * a `focus`, `screenshot` and `record` use the first driver that supports them and `text` joins every
22
+ * client's text.
23
+ *
24
+ * @throws Error when `drivers` is empty.
25
+ * @see docs/statecharts.md
26
+ *
27
+ * @example
28
+ * const driver = combineDrivers<{ member: Page; api: HttpClient }>({
29
+ * member: playwrightDriver(),
30
+ * api: httpDriver('http://127.0.0.1:4000')
31
+ * });
17
32
  */
18
33
  export declare function combineDrivers<M extends Record<string, unknown>>(drivers: {
19
34
  [K in keyof M]: Driver<M[K]>;
20
35
  }, options?: CombineDriversOptions): Driver<M>;
21
- /** A state implementation written for one client's context, lifted to a multi-client context. */
36
+ /**
37
+ * Lifts a state implementation written against one client's context to the combined context and
38
+ * sets its `client`, so its screenshot comes from that client's screen.
39
+ */
22
40
  export declare function onClient<K extends string, C>(client: K, impl: StateImplementation<C>): StateImplementation<Record<K, C>>;
23
- /** An event implementation written for one client's context, lifted to a multi-client context. */
41
+ /**
42
+ * Lifts an event implementation written against one client's context to the combined context and
43
+ * sets its `client`, so its clip comes from that client's screen and its timeline entries are tagged with it.
44
+ */
24
45
  export declare function onClient<K extends string, C>(client: K, impl: EventImplementation<C>): EventImplementation<Record<K, C>>;
25
- /** Part of an implementation: what one client does and shows, or what spans clients. */
46
+ /** Part of an implementation (any subset of its fields): what one client does and shows, or what spans clients. */
26
47
  export type ImplementationPart<C> = Partial<Implementation<C>>;
27
48
  /**
28
49
  * Merge per-client implementations into one. Each client's part is written against that client's
@@ -30,6 +51,21 @@ export type ImplementationPart<C> = Partial<Implementation<C>>;
30
51
  * driver work unchanged; `shared` holds what needs several clients at once (read an id on one
31
52
  * screen, act on it on another). `shared.setup` runs first (seed data), then each client's setup
32
53
  * in the order the clients are listed. An event or state implemented twice is an error.
54
+ *
55
+ * A seed with the same name in several parts runs `shared`'s first, then each client's; the combined
56
+ * seed's `at` is the first one's and its `how` joins all of them. Correlation ids are pooled,
57
+ * and `canStart` returns the first reason any part gives.
58
+ *
59
+ * @param parts the implementation of each client, against that client's own context.
60
+ * @param shared events, states, seeds and setup that need several clients at once, against the combined context.
61
+ * @throws Error when an event or state is implemented by more than one part (including `shared`).
62
+ * @see docs/statecharts.md
63
+ *
64
+ * @example
65
+ * const implementation = combineImplementations<{ member: SignalContext; api: HttpClient }>(
66
+ * { member: { events: {}, states: {} }, api: { events: {}, states: {} } },
67
+ * { setup: async ({ api }) => void (await api.post('/test/reset')) }
68
+ * );
33
69
  */
34
70
  export declare function combineImplementations<M extends Record<string, unknown>>(parts: {
35
71
  [K in keyof M]?: ImplementationPart<M[K]>;
@@ -37,6 +73,9 @@ export declare function combineImplementations<M extends Record<string, unknown>
37
73
  /**
38
74
  * Merge parts of one implementation written against the same context, such as one file per area
39
75
  * of a large chart (sign-up, checkout, results). Events, states and seeds must each be
40
- * implemented once; setups run in order, and correlation ids are pooled.
76
+ * implemented once; setups run in order, `canStart` returns the first reason any part gives, and
77
+ * correlation ids are pooled without duplicates.
78
+ *
79
+ * @throws Error when an event, state or seed appears in more than one part.
41
80
  */
42
81
  export declare function mergeImplementations<C>(...parts: ImplementationPart<C>[]): Implementation<C>;
@@ -1,3 +1,14 @@
1
+ /**
2
+ * @module Multi-client composition
3
+ *
4
+ * Lets one run drive several clients at once (a phone, a desktop browser, an API) by combining their
5
+ * drivers into one driver whose context is a record keyed by client name, and their implementations
6
+ * into one implementation. Each event and state records which client it acts on, which decides whose
7
+ * screen is photographed and recorded. Owns no driver behaviour of its own; it only routes to the
8
+ * drivers it is given.
9
+ *
10
+ * @see docs/statecharts.md
11
+ */
1
12
  import path from 'node:path';
2
13
  const inClientDirectory = (file, client) => path.join(path.dirname(file), client, path.basename(file));
3
14
  /**
@@ -7,7 +18,21 @@ const inClientDirectory = (file, client) => path.join(path.dirname(file), client
7
18
  * act on (`onClient`, `combineImplementations`), so screenshots and clips come from that client's
8
19
  * screen. Timeline entries are tagged with the client that made them.
9
20
  *
10
- * combineDrivers({ member: webdriverDriver(appiumIos), operator: playwrightDriver(), api: httpDriver(url) })
21
+ * The combined driver's `concurrency` is the smallest of the drivers' (1 for any that give none),
22
+ * its `pacing` is the first driver's that has one, and its name lists `<client>:<driver name>`.
23
+ * If any client fails to open, the ones that did open are closed and the open throws naming that client.
24
+ * Closing returns the first client's trace as `trace` and every client's in `traces`. Without
25
+ * a `focus`, `screenshot` and `record` use the first driver that supports them and `text` joins every
26
+ * client's text.
27
+ *
28
+ * @throws Error when `drivers` is empty.
29
+ * @see docs/statecharts.md
30
+ *
31
+ * @example
32
+ * const driver = combineDrivers<{ member: Page; api: HttpClient }>({
33
+ * member: playwrightDriver(),
34
+ * api: httpDriver('http://127.0.0.1:4000')
35
+ * });
11
36
  */
12
37
  export function combineDrivers(drivers, options = {}) {
13
38
  const names = Object.keys(drivers);
@@ -95,6 +120,7 @@ export function combineDrivers(drivers, options = {}) {
95
120
  };
96
121
  }
97
122
  const scoped = (tools, client) => ({ ...tools, timeline: tools.timeline.for(client) });
123
+ /** Lifts a state or an event implementation to a client of a multi-client context (see the overloads above); a value with `recognize` is a state. */
98
124
  export function onClient(client, impl) {
99
125
  if ('recognize' in impl) {
100
126
  const { recognize, lookIn, settle, checks, ...rest } = impl;
@@ -121,6 +147,21 @@ export function onClient(client, impl) {
121
147
  * driver work unchanged; `shared` holds what needs several clients at once (read an id on one
122
148
  * screen, act on it on another). `shared.setup` runs first (seed data), then each client's setup
123
149
  * in the order the clients are listed. An event or state implemented twice is an error.
150
+ *
151
+ * A seed with the same name in several parts runs `shared`'s first, then each client's; the combined
152
+ * seed's `at` is the first one's and its `how` joins all of them. Correlation ids are pooled,
153
+ * and `canStart` returns the first reason any part gives.
154
+ *
155
+ * @param parts the implementation of each client, against that client's own context.
156
+ * @param shared events, states, seeds and setup that need several clients at once, against the combined context.
157
+ * @throws Error when an event or state is implemented by more than one part (including `shared`).
158
+ * @see docs/statecharts.md
159
+ *
160
+ * @example
161
+ * const implementation = combineImplementations<{ member: SignalContext; api: HttpClient }>(
162
+ * { member: { events: {}, states: {} }, api: { events: {}, states: {} } },
163
+ * { setup: async ({ api }) => void (await api.post('/test/reset')) }
164
+ * );
124
165
  */
125
166
  export function combineImplementations(parts, shared = {}) {
126
167
  const clients = Object.keys(parts);
@@ -197,7 +238,10 @@ export function combineImplementations(parts, shared = {}) {
197
238
  /**
198
239
  * Merge parts of one implementation written against the same context, such as one file per area
199
240
  * of a large chart (sign-up, checkout, results). Events, states and seeds must each be
200
- * implemented once; setups run in order, and correlation ids are pooled.
241
+ * implemented once; setups run in order, `canStart` returns the first reason any part gives, and
242
+ * correlation ids are pooled without duplicates.
243
+ *
244
+ * @throws Error when an event, state or seed appears in more than one part.
201
245
  */
202
246
  export function mergeImplementations(...parts) {
203
247
  const events = {};
@@ -17,6 +17,7 @@ export type Shard = {
17
17
  };
18
18
  /** What a run reports about: the spec, the scope, and the implementation's metadata. */
19
19
  export type RunContext<C> = {
20
+ /** The loaded charts. Their files are re-read (to hash them into `specVersion`) when the manifest is built. */
20
21
  bundle: SpecBundle;
21
22
  composition: Composition;
22
23
  graph: ChartGraph;
@@ -24,20 +25,27 @@ export type RunContext<C> = {
24
25
  implementation: Implementation<C>;
25
26
  /** The journeys of the plan, as the paths they are cut into; journeys are reported from them. */
26
27
  journeys?: PlannedJourney[];
28
+ /** The plan's seeds, reported in the manifest with the paths that start from and verify each. */
27
29
  seeds?: PlannedSeed[];
30
+ /** How a business event name is recognised, by name; see `EventMatcher`. */
28
31
  eventMatchers?: Record<string, EventMatcher>;
29
32
  privacy?: PrivacyRules;
30
33
  /** Recorded in the manifest as the run's environment. */
31
34
  environment?: Record<string, unknown>;
32
35
  };
36
+ /** Everything `runPaths` needs: the `RunContext`, the paths to run and how to run them. */
33
37
  export type RunOptions<C> = RunContext<C> & {
38
+ /** The whole plan, in plan order. Paths marked `skipRun` are reported but not run. The manifest covers all of them. */
34
39
  paths: PlannedPath[];
35
40
  driver: Driver<C>;
36
41
  mode: RunMode;
37
42
  /** Runs land in `<outputRoot>/<run-id>/`. */
38
43
  outputRoot: string;
44
+ /** Whether a failed path runs a second time to tell flaky from broken; true unless `false`. */
39
45
  retry?: boolean;
46
+ /** How long to wait for a state to be recognised after an event, in milliseconds; 45 000 when omitted. */
40
47
  stepTimeoutMs?: number;
48
+ /** Where business events come from. Sources named with a `log:` prefix are treated as log files, not CloudEvents sources. */
41
49
  eventSources?: EventSource[];
42
50
  /** Path attempts that run at once, capped by the driver's `concurrency`; 1 when omitted. */
43
51
  workers?: number;
@@ -48,7 +56,10 @@ export type RunOptions<C> = RunContext<C> & {
48
56
  runDir: string;
49
57
  outcomes: Record<string, PathOutcome>;
50
58
  };
59
+ /** Receives progress lines; writes to stdout when omitted. */
51
60
  log?: (line: string) => void;
61
+ /** Receives privacy-checked manifest snapshots as paths and steps change. */
62
+ onProgress?: (manifest: Manifest) => void;
52
63
  };
53
64
  type StepResult = {
54
65
  transition: string;
@@ -83,44 +94,68 @@ type Observed = {
83
94
  */
84
95
  export type PathOutcome = {
85
96
  id: string;
97
+ /** The path's `key`; outcomes are matched across runs by it, not by `id`. */
86
98
  key: string;
99
+ /** `failed` when the last attempt failed, `flaky` when the first failed and the retry passed, `not-reached` when the path stopped at a blocked event, else `passed`. */
87
100
  status: Status;
88
101
  attempts: Attempt[];
89
102
  steps: StepResult[];
90
103
  stoppedAt: string | null;
91
104
  observed: Observed[];
105
+ /** Where and why the last attempt failed; `null` when it did not. */
92
106
  failure: {
93
107
  state: string;
94
108
  recognizer: RecognizerResult | null;
95
109
  looksLike: string[];
96
110
  shot: Image | null;
97
111
  } | null;
112
+ /** Privacy findings from the text the driver reported; they fail the run. */
98
113
  leaks: string[];
114
+ /** Wall-clock milliseconds for all attempts of the path. */
99
115
  durationMs: number;
100
116
  /** How long the last attempt took to seed (or set up) and recognise its start. */
101
117
  setupMs?: number;
102
118
  /** The run the outcome was taken from, when it was reused rather than run again. */
103
119
  reusedFrom?: string;
104
120
  };
105
- /** A rough cost of a path before it has ever run: setting it up, then each step. */
121
+ /** A rough cost in milliseconds of a path that has never run (5 s to set up, 2.5 s a step); used to order and shard paths. */
106
122
  export declare const estimateMs: (p: PlannedPath) => number;
107
123
  /**
108
124
  * The paths one shard runs: longest first onto the least loaded shard, by the plan alone, so
109
125
  * every machine computes the same split. Paths reported without running go to the first shard.
110
126
  */
111
127
  export declare function shardPaths(paths: PlannedPath[], shard: Shard): PlannedPath[];
112
- /** The plan keys and outcomes a run wrote, for merging shards and reusing passed paths. */
128
+ /**
129
+ * Reads the `outcomes.json` of a run directory: the run id and each finished path's outcome by key.
130
+ * Returns `null` when the file is missing or unreadable, never throws.
131
+ */
113
132
  export declare function readOutcomes(runDir: string): {
114
133
  runId: string;
115
134
  outcomes: Record<string, PathOutcome>;
116
135
  } | null;
117
- /** How long each path took in the newest run under `outputRoot` that recorded it, by path key. */
136
+ /**
137
+ * Milliseconds each path took, by path key, taken from the newest of the last 10 runs under
138
+ * `outputRoot` that ran it (outcomes reused from elsewhere are ignored). Empty when the directory
139
+ * does not exist. `runPaths` uses it to start the slowest paths first.
140
+ */
118
141
  export declare function durationHistory(outputRoot: string): Record<string, number>;
119
- /** The newest run under `outputRoot` that wrote outcomes. */
142
+ /** The directory of the newest run under `outputRoot` that wrote `outcomes.json` (run ids sort by time), or `null`. */
120
143
  export declare function latestRun(outputRoot: string): string | null;
121
144
  /**
122
- * Fold path outcomes into the run's report, in plan order: the same plan and outcomes always give
123
- * the same manifest, however many workers ran them, in whatever order they finished.
145
+ * Folds path outcomes into the run's manifest object, in plan order: the same plan and outcomes
146
+ * always give the same manifest, however many workers ran them, in whatever order they finished.
147
+ *
148
+ * A state or transition is `passed` when a path reached it, `flaky` when only a flaky path did,
149
+ * `failed` when any failure touched it (a failed check fails its state), else `not-reached`. Reaching a
150
+ * state also marks its ancestors reached. The whole manifest is scanned for privacy findings, and any
151
+ * finding sets `privacy.passed` to false. Reads the chart files (for `specVersion`) and runs `git`
152
+ * in the current directory (for `commit` and `branch`, `null` when that fails). Apart from the
153
+ * wall-clock fields (`finishedAt`, `updatedAt`, `durationMs`) and those that depend on the working
154
+ * directory (`commit`, `branch`, `specDirectory`), two folds of the same outcomes are identical.
155
+ *
156
+ * @param outcomes finished or in-progress outcomes by path key; a path with none is `queued` or `running`.
157
+ * @param run.activePaths ids of the paths in flight; they are reported `running` and not counted complete.
158
+ * @param run.extra extra fields merged into `run` of the manifest (workers, shard, reused, mergedFrom).
124
159
  */
125
160
  export declare function buildManifest<C>(context: RunContext<C>, paths: PlannedPath[], outcomes: Map<string, PathOutcome>, run: {
126
161
  id: string;
@@ -235,6 +270,7 @@ export declare function buildManifest<C>(context: RunContext<C>, paths: PlannedP
235
270
  key: string;
236
271
  name: string;
237
272
  kind: PlannedPath["kind"];
273
+ progress?: "queued" | "running" | "complete";
238
274
  status: Status;
239
275
  attempts: Attempt[];
240
276
  steps: StepResult[];
@@ -305,8 +341,13 @@ export declare function buildManifest<C>(context: RunContext<C>, paths: PlannedP
305
341
  mermaid: string;
306
342
  };
307
343
  };
344
+ /** The manifest object `buildManifest` returns; it is what `manifest.json` contains. */
308
345
  export type Manifest = ReturnType<typeof buildManifest>;
309
- /** Write a run's manifest, reports and outcomes; returns the manifest. */
346
+ /**
347
+ * Writes a run's `junit.xml`, `ctrf.json`, `chart.mmd`, `outcomes.json` and `manifest.json` into
348
+ * `runDir` (each through a temporary file and a rename, so a reader never sees half a file) and returns
349
+ * the manifest. `outcomes.json` holds only finished paths, not those in `run.activePaths`.
350
+ */
310
351
  export declare function writeRun<C>(runDir: string, context: RunContext<C>, paths: PlannedPath[], outcomes: Map<string, PathOutcome>, run: Parameters<typeof buildManifest>[3]): {
311
352
  $schema: string;
312
353
  schemaVersion: number;
@@ -409,6 +450,7 @@ export declare function writeRun<C>(runDir: string, context: RunContext<C>, path
409
450
  key: string;
410
451
  name: string;
411
452
  kind: PlannedPath["kind"];
453
+ progress?: "queued" | "running" | "complete";
412
454
  status: Status;
413
455
  attempts: Attempt[];
414
456
  steps: StepResult[];
@@ -480,9 +522,14 @@ export declare function writeRun<C>(runDir: string, context: RunContext<C>, path
480
522
  };
481
523
  };
482
524
  /**
483
- * Compose the outcomes of several runs of the same plan (the shards of one run, or a rerun of the
484
- * paths that failed) into one run, folded in plan order. Media are copied in, so the merged run
485
- * stands on its own. Later runs win when two ran the same path.
525
+ * Composes the outcomes of several runs of the same plan (the shards of one run, or a rerun and
526
+ * the run before it) into one new run directory under `options.outputRoot`, folded in plan order. Media are
527
+ * copied in, so the merged run stands on its own. Later entries of `runDirs` win when two ran the same
528
+ * path; outcomes whose key is not in `paths` are ignored. The merged run's mode and driver name are
529
+ * taken from the run manifests unless `options` gives them.
530
+ *
531
+ * @returns the new `runDir`, its `manifest`, and `ok` (privacy passed and no path failed).
532
+ * @throws Error when a run directory has no `outcomes.json`.
486
533
  */
487
534
  export declare function mergeRuns<C>(context: RunContext<C>, paths: PlannedPath[], runDirs: string[], options: {
488
535
  outputRoot: string;
@@ -595,6 +642,7 @@ export declare function mergeRuns<C>(context: RunContext<C>, paths: PlannedPath[
595
642
  key: string;
596
643
  name: string;
597
644
  kind: PlannedPath["kind"];
645
+ progress?: "queued" | "running" | "complete";
598
646
  status: Status;
599
647
  attempts: Attempt[];
600
648
  steps: StepResult[];
@@ -668,12 +716,22 @@ export declare function mergeRuns<C>(context: RunContext<C>, paths: PlannedPath[
668
716
  ok: boolean;
669
717
  };
670
718
  /**
671
- * Run planned paths against a system through a driver. Paths start from their seed (or the
672
- * implementation's `setup`) and run on a pool of workers, longest first, each attempt in its own
673
- * driver context; every state is recognised from the outside after every step; a failed path is
674
- * retried once to tell flaky from broken. The manifest is rewritten as each path finishes, from
675
- * all outcomes so far in plan order, so a crash keeps what ran and the order paths finished in
676
- * never changes the report.
719
+ * Runs planned paths against a system through a driver and writes the run to
720
+ * `<outputRoot>/<timestamp>-<mode>/`. Paths start from their seed (or the implementation's
721
+ * `setup`) and run on a pool of workers, longest first (by earlier timings, else `estimateMs`),
722
+ * each attempt in its own driver context; every state is recognised from the outside after every step;
723
+ * a failed path is retried once to tell flaky from broken. The manifest is rewritten as each path
724
+ * finishes, from all outcomes so far in plan order, so a crash keeps what ran and the order paths
725
+ * finished in never changes the report.
726
+ *
727
+ * Workers are capped by `driver.concurrency` (1 if the driver gives none) and by the number of paths.
728
+ * Without `implementation.correlate`, a run on several workers reports business events as "no
729
+ * signal" rather than guess which attempt they belong to. While it runs it installs
730
+ * `uncaughtException` and `unhandledRejection` handlers that log and swallow stray errors from
731
+ * drivers, and removes them when it ends. Passed paths of `options.reuse` are kept instead of re-run.
732
+ *
733
+ * @returns the run directory, the final manifest, and `ok` (privacy passed and no path failed).
734
+ * @see docs/statecharts.md
677
735
  */
678
736
  export declare function runPaths<C>(options: RunOptions<C>): Promise<{
679
737
  runDir: string;
@@ -779,6 +837,7 @@ export declare function runPaths<C>(options: RunOptions<C>): Promise<{
779
837
  key: string;
780
838
  name: string;
781
839
  kind: PlannedPath["kind"];
840
+ progress?: "queued" | "running" | "complete";
782
841
  status: Status;
783
842
  attempts: Attempt[];
784
843
  steps: StepResult[];