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