@crvouga/atlas 0.0.0-stage → 0.2.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 +11 -0
- package/LICENSE +21 -0
- package/README.md +649 -2
- package/dist/bun/src/driver.d.ts +67 -0
- package/dist/bun/src/driver.js +90 -0
- package/dist/bun/src/index.d.ts +2 -0
- package/dist/bun/src/index.js +2 -0
- package/dist/core/src/cli.d.ts +1 -0
- package/dist/core/src/cli.js +177 -0
- package/dist/core/src/config.d.ts +477 -0
- package/dist/core/src/config.js +100 -0
- package/dist/core/src/events/cloudevents.d.ts +56 -0
- package/dist/core/src/events/cloudevents.js +152 -0
- package/dist/core/src/graph.d.ts +113 -0
- package/dist/core/src/graph.js +221 -0
- package/dist/core/src/index.d.ts +17 -0
- package/dist/core/src/index.js +17 -0
- package/dist/core/src/lint.d.ts +53 -0
- package/dist/core/src/lint.js +138 -0
- package/dist/core/src/plan.d.ts +109 -0
- package/dist/core/src/plan.js +324 -0
- package/dist/core/src/privacy.d.ts +8 -0
- package/dist/core/src/privacy.js +42 -0
- package/dist/core/src/report/formats.d.ts +69 -0
- package/dist/core/src/report/formats.js +109 -0
- package/dist/core/src/report/markdown.d.ts +8 -0
- package/dist/core/src/report/markdown.js +140 -0
- package/dist/core/src/run/clients.d.ts +42 -0
- package/dist/core/src/run/clients.js +250 -0
- package/dist/core/src/run/execute.d.ts +854 -0
- package/dist/core/src/run/execute.js +877 -0
- package/dist/core/src/run/frames.d.ts +16 -0
- package/dist/core/src/run/frames.js +52 -0
- package/dist/core/src/run/http.d.ts +41 -0
- package/dist/core/src/run/http.js +71 -0
- package/dist/core/src/run/types.d.ts +248 -0
- package/dist/core/src/run/types.js +39 -0
- package/dist/core/src/signals.d.ts +110 -0
- package/dist/core/src/signals.js +121 -0
- package/dist/core/src/spec/compose.d.ts +28 -0
- package/dist/core/src/spec/compose.js +71 -0
- package/dist/core/src/spec/index.d.ts +5 -0
- package/dist/core/src/spec/index.js +5 -0
- package/dist/core/src/spec/load.d.ts +8 -0
- package/dist/core/src/spec/load.js +46 -0
- package/dist/core/src/spec/parse.d.ts +5 -0
- package/dist/core/src/spec/parse.js +32 -0
- package/dist/core/src/spec/scxml.d.ts +19 -0
- package/dist/core/src/spec/scxml.js +239 -0
- package/dist/core/src/spec/types.d.ts +96 -0
- package/dist/core/src/spec/types.js +25 -0
- package/dist/detox/src/index.d.ts +75 -0
- package/dist/detox/src/index.js +110 -0
- package/dist/playwright/src/driver.d.ts +44 -0
- package/dist/playwright/src/driver.js +82 -0
- package/dist/playwright/src/index.d.ts +3 -0
- package/dist/playwright/src/index.js +3 -0
- package/dist/playwright/src/media.d.ts +68 -0
- package/dist/playwright/src/media.js +283 -0
- package/dist/playwright/src/signals.d.ts +34 -0
- package/dist/playwright/src/signals.js +56 -0
- package/dist/reports/src/browser-navigation.d.ts +2 -0
- package/dist/reports/src/browser-navigation.js +28 -0
- package/dist/reports/src/bundle.d.ts +24 -0
- package/dist/reports/src/bundle.js +114 -0
- package/dist/reports/src/catalog.d.ts +37 -0
- package/dist/reports/src/catalog.js +127 -0
- package/dist/reports/src/clock.d.ts +14 -0
- package/dist/reports/src/clock.js +4 -0
- package/dist/reports/src/completion-order.d.ts +10 -0
- package/dist/reports/src/completion-order.js +76 -0
- package/dist/reports/src/evidence-live.d.ts +40 -0
- package/dist/reports/src/evidence-live.js +118 -0
- package/dist/reports/src/evidence-types.d.ts +90 -0
- package/dist/reports/src/evidence-types.js +15 -0
- package/dist/reports/src/evidence-view.d.ts +68 -0
- package/dist/reports/src/evidence-view.js +113 -0
- package/dist/reports/src/explorer-types.d.ts +56 -0
- package/dist/reports/src/explorer-types.js +0 -0
- package/dist/reports/src/explorer-versions.d.ts +4 -0
- package/dist/reports/src/explorer-versions.js +21 -0
- package/dist/reports/src/export-evidence.d.ts +11 -0
- package/dist/reports/src/export-evidence.js +94 -0
- package/dist/reports/src/fetcher.d.ts +50 -0
- package/dist/reports/src/fetcher.js +205 -0
- package/dist/reports/src/format-date.d.ts +1 -0
- package/dist/reports/src/format-date.js +10 -0
- package/dist/reports/src/format.d.ts +16 -0
- package/dist/reports/src/format.js +71 -0
- package/dist/reports/src/frames.d.ts +46 -0
- package/dist/reports/src/frames.js +245 -0
- package/dist/reports/src/hash.d.ts +17 -0
- package/dist/reports/src/hash.js +43 -0
- package/dist/reports/src/html-frame.d.ts +13 -0
- package/dist/reports/src/html-frame.js +63 -0
- package/dist/reports/src/http.d.ts +3 -0
- package/dist/reports/src/http.js +0 -0
- package/dist/reports/src/junit.d.ts +23 -0
- package/dist/reports/src/junit.js +119 -0
- package/dist/reports/src/keyboard.d.ts +16 -0
- package/dist/reports/src/keyboard.js +135 -0
- package/dist/reports/src/keys.d.ts +53 -0
- package/dist/reports/src/keys.js +122 -0
- package/dist/reports/src/layer-catalog.d.ts +5 -0
- package/dist/reports/src/layer-catalog.js +39 -0
- package/dist/reports/src/layer-merge.d.ts +43 -0
- package/dist/reports/src/layer-merge.js +154 -0
- package/dist/reports/src/layer-source.d.ts +6 -0
- package/dist/reports/src/layer-source.js +32 -0
- package/dist/reports/src/layer-store.d.ts +10 -0
- package/dist/reports/src/layer-store.js +36 -0
- package/dist/reports/src/layer-types.d.ts +32 -0
- package/dist/reports/src/layer-types.js +0 -0
- package/dist/reports/src/layers-route.d.ts +20 -0
- package/dist/reports/src/layers-route.js +259 -0
- package/dist/reports/src/namespace-guard.d.ts +11 -0
- package/dist/reports/src/namespace-guard.js +40 -0
- package/dist/reports/src/navigation.d.ts +8 -0
- package/dist/reports/src/navigation.js +0 -0
- package/dist/reports/src/object-io.d.ts +9 -0
- package/dist/reports/src/object-io.js +41 -0
- package/dist/reports/src/object-store.d.ts +67 -0
- package/dist/reports/src/object-store.js +32 -0
- package/dist/reports/src/performance-part.d.ts +9 -0
- package/dist/reports/src/performance-part.js +42 -0
- package/dist/reports/src/performance.d.ts +13 -0
- package/dist/reports/src/performance.js +45 -0
- package/dist/reports/src/persist.d.ts +10 -0
- package/dist/reports/src/persist.js +38 -0
- package/dist/reports/src/phone.d.ts +5 -0
- package/dist/reports/src/phone.js +18 -0
- package/dist/reports/src/protocol.d.ts +78 -0
- package/dist/reports/src/protocol.js +36 -0
- package/dist/reports/src/publication.d.ts +4 -0
- package/dist/reports/src/publication.js +35 -0
- package/dist/reports/src/publish.d.ts +52 -0
- package/dist/reports/src/publish.js +189 -0
- package/dist/reports/src/read.d.ts +62 -0
- package/dist/reports/src/read.js +214 -0
- package/dist/reports/src/recording-bundle.d.ts +22 -0
- package/dist/reports/src/recording-bundle.js +4 -0
- package/dist/reports/src/recording-keys.d.ts +9 -0
- package/dist/reports/src/recording-keys.js +50 -0
- package/dist/reports/src/remote-report.d.ts +39 -0
- package/dist/reports/src/remote-report.js +304 -0
- package/dist/reports/src/report-loader.d.ts +22 -0
- package/dist/reports/src/report-loader.js +0 -0
- package/dist/reports/src/report-parts.d.ts +10 -0
- package/dist/reports/src/report-parts.js +112 -0
- package/dist/reports/src/report-types.d.ts +194 -0
- package/dist/reports/src/report-types.js +29 -0
- package/dist/reports/src/reports-explorer-route.d.ts +90 -0
- package/dist/reports/src/reports-explorer-route.js +65 -0
- package/dist/reports/src/reports-list-route.d.ts +23 -0
- package/dist/reports/src/reports-list-route.js +55 -0
- package/dist/reports/src/reports-route.d.ts +267 -0
- package/dist/reports/src/reports-route.js +204 -0
- package/dist/reports/src/reports-store.d.ts +11 -0
- package/dist/reports/src/reports-store.js +28 -0
- package/dist/reports/src/resilient-cache.d.ts +3 -0
- package/dist/reports/src/resilient-cache.js +33 -0
- package/dist/reports/src/retention.d.ts +9 -0
- package/dist/reports/src/retention.js +16 -0
- package/dist/reports/src/scenario.d.ts +15 -0
- package/dist/reports/src/scenario.js +35 -0
- package/dist/reports/src/snapshot-bundle.d.ts +18 -0
- package/dist/reports/src/snapshot-bundle.js +94 -0
- package/dist/reports/src/snapshot-surface.d.ts +29 -0
- package/dist/reports/src/snapshot-surface.js +339 -0
- package/dist/reports/src/source-content.d.ts +30 -0
- package/dist/reports/src/source-content.js +63 -0
- package/dist/reports/src/source-entries.d.ts +4 -0
- package/dist/reports/src/source-entries.js +34 -0
- package/dist/reports/src/source-part.d.ts +4 -0
- package/dist/reports/src/source-part.js +66 -0
- package/dist/reports/src/source-reader.d.ts +6 -0
- package/dist/reports/src/source-reader.js +17 -0
- package/dist/reports/src/spec-evidence.d.ts +6 -0
- package/dist/reports/src/spec-evidence.js +20 -0
- package/dist/reports/src/spec-inventory.d.ts +14 -0
- package/dist/reports/src/spec-inventory.js +75 -0
- package/dist/reports/src/status.d.ts +4 -0
- package/dist/reports/src/status.js +8 -0
- package/dist/reports/src/store-prefix.d.ts +21 -0
- package/dist/reports/src/store-prefix.js +53 -0
- package/dist/reports/src/test-catalog-entity.d.ts +3 -0
- package/dist/reports/src/test-catalog-entity.js +34 -0
- package/dist/reports/src/types.d.ts +5 -0
- package/dist/reports/src/types.js +0 -0
- package/dist/reports/src/use-report-nav.d.ts +25 -0
- package/dist/reports/src/use-report-nav.js +181 -0
- package/dist/schema/src/common.d.ts +57 -0
- package/dist/schema/src/common.js +32 -0
- package/dist/schema/src/index.d.ts +5 -0
- package/dist/schema/src/index.js +5 -0
- package/dist/schema/src/manifest.d.ts +457 -0
- package/dist/schema/src/manifest.js +247 -0
- package/dist/schema/src/report-sources.d.ts +68 -0
- package/dist/schema/src/report-sources.js +53 -0
- package/dist/schema/src/runs-index.d.ts +52 -0
- package/dist/schema/src/runs-index.js +24 -0
- package/dist/schema/src/spec.d.ts +245 -0
- package/dist/schema/src/spec.js +133 -0
- package/dist/vitest/src/index.d.ts +22 -0
- package/dist/vitest/src/index.js +33 -0
- package/dist/webdriver/src/driver.d.ts +69 -0
- package/dist/webdriver/src/driver.js +230 -0
- package/dist/webdriver/src/index.d.ts +11 -0
- package/dist/webdriver/src/index.js +10 -0
- package/dist/webdriver/src/protocol.d.ts +60 -0
- package/dist/webdriver/src/protocol.js +146 -0
- package/package.json +181 -4
- package/packages/bun/README.md +69 -0
- package/packages/core/README.md +78 -0
- package/packages/core/bin/atlas.mjs +8 -0
- package/packages/detox/README.md +73 -0
- package/packages/playwright/README.md +77 -0
- package/packages/reports/README.md +47 -0
- package/packages/reports/STORAGE.md +73 -0
- package/packages/schema/README.md +23 -0
- package/packages/schema/schemas/atlas-change.schema.json +34 -0
- package/packages/schema/schemas/atlas.schema.json +32 -0
- package/packages/schema/schemas/cloud-event.schema.json +40 -0
- package/packages/schema/schemas/journeys.schema.json +17 -0
- package/packages/schema/schemas/manifest.schema.json +160 -0
- package/packages/schema/schemas/path-record.schema.json +151 -0
- package/packages/schema/schemas/report-sources.schema.json +95 -0
- package/packages/schema/schemas/run-info.schema.json +176 -0
- package/packages/schema/schemas/run-summary.schema.json +206 -0
- package/packages/schema/schemas/runs-index.schema.json +23 -0
- package/packages/schema/schemas/state-node.schema.json +238 -0
- package/packages/schema/schemas/state-record.schema.json +354 -0
- package/packages/schema/schemas/timeline-entry.schema.json +124 -0
- package/packages/schema/schemas/transition-record.schema.json +125 -0
- package/packages/visualizer/README.md +154 -0
- package/packages/visualizer/bin/atlas-visualizer.mjs +176 -0
- package/packages/visualizer/example/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/example/specs/coffee/ordering/journeys.yaml +129 -0
- package/packages/visualizer/example/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/example/specs/coffee/ordering/machine.yaml +158 -0
- package/packages/visualizer/example/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/chart.mmd +67 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/ctrf.json +245 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/junit.xml +12 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/manifest.json +2003 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/001.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/002.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/003.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/004.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/005.vtt +17 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/006.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/007.vtt +17 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/008.vtt +17 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/009.vtt +13 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/010.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/011.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/012.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/013.vtt +9 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.mp4 +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.poster.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.mp4 +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.poster.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/03.mp4 +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/03.poster.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/04.mp4 +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/04.poster.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/04.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/04.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/05.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/05.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-2/01.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-2/01.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-3/failed-01.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-3/failed-01.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-4/01.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-4/01.webp +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-5/01.png +0 -0
- package/packages/visualizer/fixtures/failures/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-5/01.webp +0 -0
- package/packages/visualizer/fixtures/failures/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/fixtures/failures/specs/coffee/ordering/journeys.yaml +129 -0
- package/packages/visualizer/fixtures/failures/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/fixtures/failures/specs/coffee/ordering/machine.yaml +158 -0
- package/packages/visualizer/fixtures/failures/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-02T09-10-00-000Z-fast/chart.mmd +67 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-02T09-10-00-000Z-fast/ctrf.json +247 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-02T09-10-00-000Z-fast/junit.xml +12 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-02T09-10-00-000Z-fast/manifest.json +1875 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/chart.mmd +67 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/ctrf.json +244 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/junit.xml +12 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/manifest.json +1977 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/captions/001.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/captions/002.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/captions/003.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/captions/004.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/captions/005.vtt +17 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/captions/006.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/clips/journey-1/01.mp4 +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/clips/journey-1/01.poster.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/clips/journey-1/02.mp4 +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/clips/journey-1/02.poster.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-1/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-1/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-1/02.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-1/02.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-1/03.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-1/03.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-2/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-04T16-20-00-000Z-showcase/media/paths/journey-2/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/chart.mmd +67 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/ctrf.json +472 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/junit.xml +16 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/manifest.json +3701 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/001.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/002.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/003.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/004.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/005.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/006.vtt +13 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/007.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/008.vtt +13 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/009.vtt +17 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/010.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/011.vtt +13 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/012.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/013.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/014.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/015.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/016.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/017.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/018.vtt +17 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/019.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/020.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/021.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/022.vtt +17 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/023.vtt +17 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/024.vtt +13 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/025.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/026.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/027.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/028.vtt +9 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.mp4 +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.poster.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.mp4 +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.poster.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/03.mp4 +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/03.poster.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/04.mp4 +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/04.poster.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/04.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/04.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/05.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/05.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/06.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/06.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/07.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/07.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/08.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/08.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/09.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/09.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/10.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/10.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/11.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/11.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/12.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/12.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/13.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/13.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/14.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/14.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-2/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-2/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-3/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-3/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-4/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-4/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-5/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-5/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-6/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-6/01.webp +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-7/01.png +0 -0
- package/packages/visualizer/fixtures/full/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-7/01.webp +0 -0
- package/packages/visualizer/fixtures/full/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/fixtures/full/specs/coffee/ordering/journeys.yaml +129 -0
- package/packages/visualizer/fixtures/full/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/fixtures/full/specs/coffee/ordering/machine.yaml +158 -0
- package/packages/visualizer/fixtures/full/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/fixtures/large/runs/2026-10-06T14-40-00-000Z-fast/ctrf.json +1280 -0
- package/packages/visualizer/fixtures/large/runs/2026-10-06T14-40-00-000Z-fast/junit.xml +26 -0
- package/packages/visualizer/fixtures/large/runs/2026-10-06T14-40-00-000Z-fast/manifest.json +28393 -0
- package/packages/visualizer/fixtures/large/specs/accounts/sign-up/identity-check.machine.yaml +397 -0
- package/packages/visualizer/fixtures/large/specs/accounts/sign-up/journeys.yaml +129 -0
- package/packages/visualizer/fixtures/large/specs/accounts/sign-up/machine.yaml +830 -0
- package/packages/visualizer/fixtures/large/specs/atlas.yaml +65 -0
- package/packages/visualizer/fixtures/large/specs/billing/invoices/journeys.yaml +132 -0
- package/packages/visualizer/fixtures/large/specs/billing/invoices/machine.yaml +830 -0
- package/packages/visualizer/fixtures/large/specs/billing/invoices/refund-handling.scxml +288 -0
- package/packages/visualizer/fixtures/large/specs/catalog/browsing/journeys.yaml +126 -0
- package/packages/visualizer/fixtures/large/specs/catalog/browsing/machine.yaml +831 -0
- package/packages/visualizer/fixtures/large/specs/catalog/browsing/product-comparison.machine.yaml +395 -0
- package/packages/visualizer/fixtures/large/specs/orders/checkout/journeys.yaml +120 -0
- package/packages/visualizer/fixtures/large/specs/orders/checkout/machine.yaml +724 -0
- package/packages/visualizer/fixtures/large/specs/orders/checkout/open-questions.md +16 -0
- package/packages/visualizer/fixtures/large/specs/orders/checkout/payment.scxml +288 -0
- package/packages/visualizer/fixtures/large/specs/shipping/deliveries/delivery-scheduling.machine.yaml +397 -0
- package/packages/visualizer/fixtures/large/specs/shipping/deliveries/journeys.yaml +132 -0
- package/packages/visualizer/fixtures/large/specs/shipping/deliveries/known-issues.md +13 -0
- package/packages/visualizer/fixtures/large/specs/shipping/deliveries/machine.yaml +830 -0
- package/packages/visualizer/fixtures/large/specs/support/tickets/escalation.machine.yaml +395 -0
- package/packages/visualizer/fixtures/large/specs/support/tickets/journeys.yaml +123 -0
- package/packages/visualizer/fixtures/large/specs/support/tickets/machine.yaml +720 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T10-00-00-000Z-showcase/manifest.json +68 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T11-00-00-000Z-showcase/ctrf.json +50 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T11-00-00-000Z-showcase/junit.xml +6 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T11-00-00-000Z-showcase/manifest.json +1281 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T12-00-00-000Z-showcase/ctrf.json +50 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T12-00-00-000Z-showcase/junit.xml +6 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T12-00-00-000Z-showcase/manifest.json +1232 -0
- package/packages/visualizer/fixtures/malformed/runs/2026-10-06T13-00-00-000Z-showcase/manifest.json +1244 -0
- package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/journeys.yaml +134 -0
- package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/loyalty.scxml +4 -0
- package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/machine.yaml +156 -0
- package/packages/visualizer/fixtures/malformed/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/chart.mmd +67 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/ctrf.json +149 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/junit.xml +9 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/manifest.json +1718 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/001.vtt +9 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/002.vtt +17 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/003.vtt +17 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/004.vtt +9 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/005.vtt +9 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.mp4 +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.poster.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.mp4 +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.poster.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/03.mp4 +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/03.poster.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/05.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/05.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-3/01.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-3/01.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T15-05-00-000Z-showcase/media/paths/journey-1/00-start-01.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T15-05-00-000Z-showcase/media/paths/journey-1/00-start-01.webp +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T15-05-00-000Z-showcase/media/paths/journey-1/02.png +0 -0
- package/packages/visualizer/fixtures/partial/runs/2026-10-06T15-05-00-000Z-showcase/media/paths/journey-1/02.webp +0 -0
- package/packages/visualizer/fixtures/partial/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/fixtures/partial/specs/coffee/ordering/journeys.yaml +129 -0
- package/packages/visualizer/fixtures/partial/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/fixtures/partial/specs/coffee/ordering/machine.yaml +158 -0
- package/packages/visualizer/fixtures/partial/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/ctrf.json +79 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/junit.xml +7 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/manifest.json +1504 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/001.vtt +9 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/002.vtt +9 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/003.vtt +9 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/captions/004.vtt +17 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.mp4 +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/01.poster.webp +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.mp4 +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/clips/journey-1/02.poster.webp +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.png +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/01.webp +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.png +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/02.webp +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.png +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/03.webp +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/04.png +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-1/04.webp +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-2/01.png +0 -0
- package/packages/visualizer/fixtures/removed/runs/2026-10-06T14-40-00-000Z-showcase/media/paths/journey-2/01.webp +0 -0
- package/packages/visualizer/fixtures/removed/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/fixtures/removed/specs/coffee/ordering/journeys.yaml +129 -0
- package/packages/visualizer/fixtures/removed/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/fixtures/removed/specs/coffee/ordering/machine.yaml +158 -0
- package/packages/visualizer/fixtures/removed/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/fixtures/spec-only/runs/.gitkeep +0 -0
- package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/checkout.scxml +82 -0
- package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/journeys.yaml +129 -0
- package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/known-issues.md +14 -0
- package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/machine.yaml +158 -0
- package/packages/visualizer/fixtures/spec-only/specs/coffee/ordering/open-questions.md +25 -0
- package/packages/visualizer/index.html +13 -0
- package/packages/visualizer/scripts/make-fixtures.ts +1490 -0
- package/packages/visualizer/scripts/publish-data.ts +22 -0
- package/packages/visualizer/src/app/AppShell.tsx +56 -0
- package/packages/visualizer/src/app/atlas-context.tsx +23 -0
- package/packages/visualizer/src/app/gazetteer.module.css +97 -0
- package/packages/visualizer/src/app/gazetteer.tsx +105 -0
- package/packages/visualizer/src/app/report-sources.tsx +122 -0
- package/packages/visualizer/src/app/router.tsx +69 -0
- package/packages/visualizer/src/app/search-query.tsx +14 -0
- package/packages/visualizer/src/components/DataIssues.module.css +136 -0
- package/packages/visualizer/src/components/DataIssues.tsx +70 -0
- package/packages/visualizer/src/components/Header.module.css +189 -0
- package/packages/visualizer/src/components/Header.tsx +127 -0
- package/packages/visualizer/src/components/Legend.module.css +84 -0
- package/packages/visualizer/src/components/Legend.tsx +50 -0
- package/packages/visualizer/src/components/Screen.module.css +312 -0
- package/packages/visualizer/src/components/Screen.tsx +141 -0
- package/packages/visualizer/src/components/Status.module.css +116 -0
- package/packages/visualizer/src/components/Status.tsx +60 -0
- package/packages/visualizer/src/components/icons.tsx +156 -0
- package/packages/visualizer/src/components/labels.tsx +22 -0
- package/packages/visualizer/src/data/adapters/adapter.ts +112 -0
- package/packages/visualizer/src/data/adapters/context.tsx +11 -0
- package/packages/visualizer/src/data/adapters/index.ts +29 -0
- package/packages/visualizer/src/data/adapters/report-backend.test.ts +96 -0
- package/packages/visualizer/src/data/adapters/report-backend.ts +42 -0
- package/packages/visualizer/src/data/fixtures.test.ts +407 -0
- package/packages/visualizer/src/data/model/build.ts +418 -0
- package/packages/visualizer/src/data/model/event-kind.test.ts +59 -0
- package/packages/visualizer/src/data/model/event-kind.ts +54 -0
- package/packages/visualizer/src/data/model/index.ts +3 -0
- package/packages/visualizer/src/data/model/journeys.test.ts +159 -0
- package/packages/visualizer/src/data/model/journeys.ts +29 -0
- package/packages/visualizer/src/data/model/simulation.test.ts +115 -0
- package/packages/visualizer/src/data/model/simulation.ts +187 -0
- package/packages/visualizer/src/data/model/status.test.ts +34 -0
- package/packages/visualizer/src/data/model/status.ts +43 -0
- package/packages/visualizer/src/data/model/types.ts +280 -0
- package/packages/visualizer/src/data/parse/issues.test.ts +82 -0
- package/packages/visualizer/src/data/parse/issues.ts +114 -0
- package/packages/visualizer/src/data/parse/manifest.ts +173 -0
- package/packages/visualizer/src/data/parse/markdown.test.ts +119 -0
- package/packages/visualizer/src/data/parse/markdown.ts +133 -0
- package/packages/visualizer/src/data/parse/spec.test.ts +106 -0
- package/packages/visualizer/src/data/parse/spec.ts +557 -0
- package/packages/visualizer/src/data/parse/structured.ts +44 -0
- package/packages/visualizer/src/data/queries.ts +369 -0
- package/packages/visualizer/src/data/testing/load-fixture.ts +63 -0
- package/packages/visualizer/src/evidence/api.ts +41 -0
- package/packages/visualizer/src/evidence/check-detail.tsx +257 -0
- package/packages/visualizer/src/evidence/decision-table.tsx +68 -0
- package/packages/visualizer/src/evidence/document-page.tsx +40 -0
- package/packages/visualizer/src/evidence/evidence-context.tsx +159 -0
- package/packages/visualizer/src/evidence/evidence.module.css +877 -0
- package/packages/visualizer/src/evidence/feature-page.tsx +88 -0
- package/packages/visualizer/src/evidence/format.ts +56 -0
- package/packages/visualizer/src/evidence/gherkin.ts +98 -0
- package/packages/visualizer/src/evidence/marks.tsx +118 -0
- package/packages/visualizer/src/evidence/model-page.tsx +60 -0
- package/packages/visualizer/src/evidence/model-trace.tsx +57 -0
- package/packages/visualizer/src/evidence/overview.tsx +134 -0
- package/packages/visualizer/src/evidence/quint.ts +45 -0
- package/packages/visualizer/src/evidence/recording-page.tsx +69 -0
- package/packages/visualizer/src/evidence/recording.module.css +464 -0
- package/packages/visualizer/src/evidence/recording.tsx +197 -0
- package/packages/visualizer/src/evidence/snapshot.tsx +108 -0
- package/packages/visualizer/src/evidence/sources-panel.tsx +134 -0
- package/packages/visualizer/src/evidence/sources.module.css +168 -0
- package/packages/visualizer/src/evidence/spec-header.tsx +64 -0
- package/packages/visualizer/src/evidence/spec-index.tsx +82 -0
- package/packages/visualizer/src/evidence/spec-page.tsx +92 -0
- package/packages/visualizer/src/evidence/spec-snapshot.tsx +26 -0
- package/packages/visualizer/src/layout/graph.test.ts +113 -0
- package/packages/visualizer/src/layout/graph.ts +324 -0
- package/packages/visualizer/src/layout/layout.ts +237 -0
- package/packages/visualizer/src/layout/use-chart-layout.ts +18 -0
- package/packages/visualizer/src/main.tsx +31 -0
- package/packages/visualizer/src/map/ChartMap.tsx +252 -0
- package/packages/visualizer/src/map/EventEdge.tsx +138 -0
- package/packages/visualizer/src/map/map.module.css +546 -0
- package/packages/visualizer/src/map/nodes.tsx +145 -0
- package/packages/visualizer/src/map/path.ts +24 -0
- package/packages/visualizer/src/reachable.test.ts +54 -0
- package/packages/visualizer/src/spec-kind.test.ts +27 -0
- package/packages/visualizer/src/spec-kind.ts +56 -0
- package/packages/visualizer/src/state/ui-store.ts +44 -0
- package/packages/visualizer/src/styles/global.css +105 -0
- package/packages/visualizer/src/styles/tokens.css +80 -0
- package/packages/visualizer/src/views/ChartPage.tsx +52 -0
- package/packages/visualizer/src/views/ProductPage.tsx +35 -0
- package/packages/visualizer/src/views/SidePanel.tsx +339 -0
- package/packages/visualizer/src/views/views.module.css +546 -0
- package/packages/visualizer/vite/atlas-dev-plugin.ts +169 -0
- package/packages/visualizer/vite/atlas-files.test.ts +119 -0
- package/packages/visualizer/vite/atlas-files.ts +199 -0
- package/packages/visualizer/vite/publish.test.ts +52 -0
- package/packages/visualizer/vite/publish.ts +99 -0
- package/packages/visualizer/vite/reports-dev-plugin.ts +82 -0
- package/packages/visualizer/vite.config.ts +13 -0
- package/packages/vitest/README.md +58 -0
- package/packages/webdriver/README.md +77 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object-store key layout of the shared reports store. Historical recording addresses use
|
|
3
|
+
* the full commit sha. Immutable report layers combine across those addresses:
|
|
4
|
+
*
|
|
5
|
+
* index/<13-digit inverted start ms>-<sha>.json one per published commit;
|
|
6
|
+
* sorted keys = newest first
|
|
7
|
+
* commits/<sha>/commit.json the commit's run record
|
|
8
|
+
* commits/<sha>/frame.css stylesheet for its snapshots
|
|
9
|
+
* commits/<sha>/sources/<source>.json one source's test metas
|
|
10
|
+
* commits/<sha>/bundles/<source>.json logical file locations
|
|
11
|
+
* commits/<sha>/blobs/<content hash>.gz compressed chunks
|
|
12
|
+
*
|
|
13
|
+
* Logical test and frame keys below are entries in the bundle indexes.
|
|
14
|
+
*
|
|
15
|
+
* A source is one report bucket of one package (`libs-chess--part-2`).
|
|
16
|
+
* Writers put a source's tests first and its `sources/` record last, so a
|
|
17
|
+
* reader that sees the record can read every test it names.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Where the reports live in their bucket. Every reader and writer scopes its
|
|
21
|
+
* store to it, so the keys below are relative to it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const REPORTS_ROOT_PREFIX = "spec-reports";
|
|
24
|
+
export declare const COMMITS_INDEX_PREFIX = "index/";
|
|
25
|
+
export declare function isCommitSha(value: string): boolean;
|
|
26
|
+
/** One path segment the harness could have written (never `.` or `..`). */
|
|
27
|
+
export declare function isKeySegment(value: string): boolean;
|
|
28
|
+
/** A frame file relative to its test (`frames/f-0001.state.json`). */
|
|
29
|
+
export declare function isFramePath(value: string): boolean;
|
|
30
|
+
/** `libs/chess` + `part-2` → `libs-chess--part-2`. */
|
|
31
|
+
export declare function sourceId(packageDir: string, bucket: string): string;
|
|
32
|
+
export declare function commitIndexKey(sha: string, startedAtMs: number): string;
|
|
33
|
+
/** The sha an index key names, or null for anything else. */
|
|
34
|
+
export declare function shaOfIndexKey(key: string): string | null;
|
|
35
|
+
export declare function commitPrefix(sha: string): string;
|
|
36
|
+
export declare function commitKey(sha: string): string;
|
|
37
|
+
export declare function frameCssKey(sha: string): string;
|
|
38
|
+
export declare function sourcesPrefix(sha: string): string;
|
|
39
|
+
export declare function sourceKey(sha: string, source: string): string;
|
|
40
|
+
/** The source a `sources/` key names, or null for anything else. */
|
|
41
|
+
export declare function sourceOfKey(sha: string, key: string): string | null;
|
|
42
|
+
export declare function remoteTestPrefix(sha: string, source: string, testId: string): string;
|
|
43
|
+
export declare function remoteTestReportKey(sha: string, source: string, testId: string): string;
|
|
44
|
+
export declare function remoteTestFileKey(sha: string, source: string, testId: string, file: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* The id a viewer shows for a test of a source (`libs-chess--part-2/monkey`):
|
|
47
|
+
* unique across the commit, since two packages may both name a test `monkey`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function viewerTestId(source: string, testId: string): string;
|
|
50
|
+
export declare function splitViewerTestId(id: string): {
|
|
51
|
+
readonly source: string;
|
|
52
|
+
readonly testId: string;
|
|
53
|
+
} | null;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object-store key layout of the shared reports store. Historical recording addresses use
|
|
3
|
+
* the full commit sha. Immutable report layers combine across those addresses:
|
|
4
|
+
*
|
|
5
|
+
* index/<13-digit inverted start ms>-<sha>.json one per published commit;
|
|
6
|
+
* sorted keys = newest first
|
|
7
|
+
* commits/<sha>/commit.json the commit's run record
|
|
8
|
+
* commits/<sha>/frame.css stylesheet for its snapshots
|
|
9
|
+
* commits/<sha>/sources/<source>.json one source's test metas
|
|
10
|
+
* commits/<sha>/bundles/<source>.json logical file locations
|
|
11
|
+
* commits/<sha>/blobs/<content hash>.gz compressed chunks
|
|
12
|
+
*
|
|
13
|
+
* Logical test and frame keys below are entries in the bundle indexes.
|
|
14
|
+
*
|
|
15
|
+
* A source is one report bucket of one package (`libs-chess--part-2`).
|
|
16
|
+
* Writers put a source's tests first and its `sources/` record last, so a
|
|
17
|
+
* reader that sees the record can read every test it names.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Where the reports live in their bucket. Every reader and writer scopes its
|
|
21
|
+
* store to it, so the keys below are relative to it.
|
|
22
|
+
*/
|
|
23
|
+
export const REPORTS_ROOT_PREFIX = 'spec-reports';
|
|
24
|
+
const SHA = /^[0-9a-f]{40}$/;
|
|
25
|
+
/** `sanitizeTestId` output: what the harness names tests and runs. */
|
|
26
|
+
const SEGMENT = /^[a-zA-Z0-9._-]+$/;
|
|
27
|
+
/** Inverted start times sort newest first while there are 13-digit ms. */
|
|
28
|
+
const INVERT_FROM = 9_999_999_999_999;
|
|
29
|
+
export const COMMITS_INDEX_PREFIX = 'index/';
|
|
30
|
+
export function isCommitSha(value) {
|
|
31
|
+
return SHA.test(value);
|
|
32
|
+
}
|
|
33
|
+
/** One path segment the harness could have written (never `.` or `..`). */
|
|
34
|
+
export function isKeySegment(value) {
|
|
35
|
+
return SEGMENT.test(value) && value !== '.' && value !== '..';
|
|
36
|
+
}
|
|
37
|
+
/** A frame file relative to its test (`frames/f-0001.state.json`). */
|
|
38
|
+
export function isFramePath(value) {
|
|
39
|
+
const parts = value.split('/');
|
|
40
|
+
return parts.length > 0 && parts.every(isKeySegment);
|
|
41
|
+
}
|
|
42
|
+
function assertSha(sha) {
|
|
43
|
+
if (!isCommitSha(sha)) {
|
|
44
|
+
throw new Error(`report key needs a full 40-hex commit sha, got "${sha}"`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** `libs/chess` + `part-2` → `libs-chess--part-2`. */
|
|
48
|
+
export function sourceId(packageDir, bucket) {
|
|
49
|
+
const id = `${packageDir.replaceAll('/', '-')}--${bucket}`;
|
|
50
|
+
if (!isKeySegment(id))
|
|
51
|
+
throw new Error(`not a report source: "${id}"`);
|
|
52
|
+
return id;
|
|
53
|
+
}
|
|
54
|
+
export function commitIndexKey(sha, startedAtMs) {
|
|
55
|
+
assertSha(sha);
|
|
56
|
+
const inverted = String(INVERT_FROM - Math.max(0, Math.floor(startedAtMs)));
|
|
57
|
+
return `${COMMITS_INDEX_PREFIX}${inverted.padStart(13, '0')}-${sha}.json`;
|
|
58
|
+
}
|
|
59
|
+
/** The sha an index key names, or null for anything else. */
|
|
60
|
+
export function shaOfIndexKey(key) {
|
|
61
|
+
const m = /^index\/\d{13}-([0-9a-f]{40})\.json$/.exec(key);
|
|
62
|
+
return m === null ? null : (m[1] ?? null);
|
|
63
|
+
}
|
|
64
|
+
export function commitPrefix(sha) {
|
|
65
|
+
assertSha(sha);
|
|
66
|
+
return `commits/${sha}/`;
|
|
67
|
+
}
|
|
68
|
+
export function commitKey(sha) {
|
|
69
|
+
return `${commitPrefix(sha)}commit.json`;
|
|
70
|
+
}
|
|
71
|
+
export function frameCssKey(sha) {
|
|
72
|
+
return `${commitPrefix(sha)}frame.css`;
|
|
73
|
+
}
|
|
74
|
+
export function sourcesPrefix(sha) {
|
|
75
|
+
return `${commitPrefix(sha)}sources/`;
|
|
76
|
+
}
|
|
77
|
+
export function sourceKey(sha, source) {
|
|
78
|
+
if (!isKeySegment(source))
|
|
79
|
+
throw new Error(`not a source: "${source}"`);
|
|
80
|
+
return `${sourcesPrefix(sha)}${source}.json`;
|
|
81
|
+
}
|
|
82
|
+
/** The source a `sources/` key names, or null for anything else. */
|
|
83
|
+
export function sourceOfKey(sha, key) {
|
|
84
|
+
const head = sourcesPrefix(sha);
|
|
85
|
+
if (!key.startsWith(head) || !key.endsWith('.json'))
|
|
86
|
+
return null;
|
|
87
|
+
const source = key.slice(head.length, -'.json'.length);
|
|
88
|
+
return isKeySegment(source) ? source : null;
|
|
89
|
+
}
|
|
90
|
+
export function remoteTestPrefix(sha, source, testId) {
|
|
91
|
+
if (!isKeySegment(source))
|
|
92
|
+
throw new Error(`not a source: "${source}"`);
|
|
93
|
+
if (!isKeySegment(testId))
|
|
94
|
+
throw new Error(`not a test id: "${testId}"`);
|
|
95
|
+
return `${commitPrefix(sha)}tests/${source}/${testId}/`;
|
|
96
|
+
}
|
|
97
|
+
export function remoteTestReportKey(sha, source, testId) {
|
|
98
|
+
return `${remoteTestPrefix(sha, source, testId)}report.json`;
|
|
99
|
+
}
|
|
100
|
+
export function remoteTestFileKey(sha, source, testId, file) {
|
|
101
|
+
const rel = file.replace(/^\/+/, '');
|
|
102
|
+
if (!isFramePath(rel))
|
|
103
|
+
throw new Error(`not a frame file: "${file}"`);
|
|
104
|
+
return `${remoteTestPrefix(sha, source, testId)}${rel}`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The id a viewer shows for a test of a source (`libs-chess--part-2/monkey`):
|
|
108
|
+
* unique across the commit, since two packages may both name a test `monkey`.
|
|
109
|
+
*/
|
|
110
|
+
export function viewerTestId(source, testId) {
|
|
111
|
+
return `${source}/${testId}`;
|
|
112
|
+
}
|
|
113
|
+
export function splitViewerTestId(id) {
|
|
114
|
+
const slash = id.indexOf('/');
|
|
115
|
+
if (slash < 0)
|
|
116
|
+
return null;
|
|
117
|
+
const source = id.slice(0, slash);
|
|
118
|
+
const testId = id.slice(slash + 1);
|
|
119
|
+
return isKeySegment(source) && isKeySegment(testId)
|
|
120
|
+
? { source, testId }
|
|
121
|
+
: null;
|
|
122
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ObjectStore } from './object-store.js';
|
|
2
|
+
import type { LayerSummary } from './layer-types.js';
|
|
3
|
+
/** Read existing recordings in place; opening Atlas never rewrites the evidence store. */
|
|
4
|
+
export declare function catalogEntries(store: ObjectStore): Promise<readonly string[]>;
|
|
5
|
+
export declare function catalogLayers(store: ObjectStore, entry: string): Promise<readonly LayerSummary[]>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readUtf8 } from './object-io.js';
|
|
2
|
+
import { readCommit } from './read.js';
|
|
3
|
+
import { readInventory } from './spec-inventory.js';
|
|
4
|
+
import { readParts } from './report-parts.js';
|
|
5
|
+
import { reportStore } from './publication.js';
|
|
6
|
+
import { readStoredSource } from './source-content.js';
|
|
7
|
+
import { sourceParts } from './source-part.js';
|
|
8
|
+
import { LAYER_INDEX, readLayer, layerSummary } from './layer-store.js';
|
|
9
|
+
import { eachLimited } from './completion-order.js';
|
|
10
|
+
/** Read existing recordings in place; opening Atlas never rewrites the evidence store. */
|
|
11
|
+
export async function catalogEntries(store) {
|
|
12
|
+
const [layers, versions, commits] = await Promise.all([store.listKeys(LAYER_INDEX), store.listKeys('versions/'), store.listKeys('index/')]);
|
|
13
|
+
const shas = new Set([...versions, ...commits].flatMap(key => /([0-9a-f]{40})\.json$/.exec(key)?.[1] ?? []));
|
|
14
|
+
return [...layers.map(key => `layer:${key}`), ...[...shas].sort().map(sha => `commit:${sha}`)];
|
|
15
|
+
}
|
|
16
|
+
export async function catalogLayers(store, entry) {
|
|
17
|
+
if (entry.startsWith('layer:')) {
|
|
18
|
+
const raw = await readUtf8(store, entry.slice(6));
|
|
19
|
+
const id = raw && JSON.parse(raw).id;
|
|
20
|
+
const layer = id ? await readLayer(store, id) : null;
|
|
21
|
+
if (!layer)
|
|
22
|
+
throw new Error('An indexed report layer is unavailable');
|
|
23
|
+
return [layerSummary(layer)];
|
|
24
|
+
}
|
|
25
|
+
const sha = entry.slice(7);
|
|
26
|
+
const [commit, inventory, parts, scoped] = await Promise.all([readCommit(store, sha), readInventory(store, sha), readParts(store, sha), reportStore(store, sha)]);
|
|
27
|
+
const specs = inventory?.entries ?? [];
|
|
28
|
+
const layers = parts.map(part => ({ ...(part.freshness ? { freshness: part.freshness } : {}), id: `part-${sha}-${part.id}`, producer: part.id, recordedAtMs: part.recordedAtMs, sha, branch: commit?.branch ?? null, runUrl: commit?.runUrl ?? null, parameters: part.parameters ?? {}, specs, parts: [part], source: null, recording: null }));
|
|
29
|
+
await eachLimited(await scoped.listKeys(`commits/${sha}/sources/`), 8, async (key) => {
|
|
30
|
+
const sourceId = key.split('/').at(-1).replace(/\.json$/, '');
|
|
31
|
+
const stored = await readStoredSource(store, sha, sourceId);
|
|
32
|
+
if (!stored)
|
|
33
|
+
return;
|
|
34
|
+
layers.push({ id: `source-${sha}-${sourceId}`, producer: sourceId, recordedAtMs: Math.max(commit?.startedAtMs ?? 0, stored.record.updatedAtMs), sha, branch: commit?.branch ?? null, runUrl: commit?.runUrl ?? null, parameters: {}, specs, parts: sourceParts(sha, stored.record), source: stored.record, recording: { type: 'commit', sha, source: sourceId } });
|
|
35
|
+
});
|
|
36
|
+
const signature = (part) => JSON.stringify([part.id, part.kind, part.checks]);
|
|
37
|
+
const sourceEvidence = new Set(layers.filter(layer => layer.source).flatMap(layer => layer.parts.map(signature)));
|
|
38
|
+
return layers.filter(layer => layer.source || !layer.parts.every(part => !part.parameters && sourceEvidence.has(signature(part))));
|
|
39
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { EvidenceStatus, SpecEntry } from './explorer-types.js';
|
|
2
|
+
import type { LayerEvidence, LayerHeader, LayerRow, StatusCounts } from './evidence-types.js';
|
|
3
|
+
import type { LayerParameters, LayerSummary, ReportOutline } from './layer-types.js';
|
|
4
|
+
/** Advisory identity, never a cryptographic integrity check. */
|
|
5
|
+
export declare function textFingerprint(text: string): string;
|
|
6
|
+
export declare function specPath(path: string): string;
|
|
7
|
+
export declare function parameterKey(parameters: LayerParameters): string;
|
|
8
|
+
/** Recorded timings qualify an outcome. They are a result of their own only when nothing else checked the same thing. */
|
|
9
|
+
export declare function isDiagnosticKind(kind: string): boolean;
|
|
10
|
+
export declare function emptyCounts(): Record<EvidenceStatus, number>;
|
|
11
|
+
/** Outcomes of a layer: its checks, without the timings that only qualify them. */
|
|
12
|
+
export declare function outcomeCounts(rows: readonly LayerRow[]): StatusCounts;
|
|
13
|
+
/** A layer as the explorer reads it: its origin, and each check as one row. */
|
|
14
|
+
export declare function layerEvidence(summary: LayerSummary, backend: string): LayerEvidence;
|
|
15
|
+
export type EvidenceResult = {
|
|
16
|
+
/** One producer's check of one kind under one parameter set. */
|
|
17
|
+
readonly key: string;
|
|
18
|
+
/** The check itself, whatever kind of evidence and parameters describe it. */
|
|
19
|
+
readonly slot: string;
|
|
20
|
+
readonly layer: LayerHeader;
|
|
21
|
+
readonly row: LayerRow;
|
|
22
|
+
readonly parameters: LayerParameters;
|
|
23
|
+
readonly warning: string | null;
|
|
24
|
+
};
|
|
25
|
+
export type CombinedEvidence = {
|
|
26
|
+
readonly specs: readonly {
|
|
27
|
+
readonly spec: SpecEntry;
|
|
28
|
+
readonly results: EvidenceResult[];
|
|
29
|
+
}[];
|
|
30
|
+
readonly unassigned: EvidenceResult[];
|
|
31
|
+
};
|
|
32
|
+
/** One linear pass. Latest completed result wins only its own check/parameter slot. */
|
|
33
|
+
export declare function combineEvidence(outline: ReportOutline, layers: readonly LayerEvidence[]): CombinedEvidence;
|
|
34
|
+
export declare function slotKey(path: string, id: string): string;
|
|
35
|
+
/** Suppress the mutable address of an execution already archived as an immutable layer. */
|
|
36
|
+
export declare function distinctHeaders<T extends {
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly execution: string;
|
|
39
|
+
}>(layers: readonly T[]): T[];
|
|
40
|
+
export declare function distinctEvidence(layers: readonly LayerEvidence[]): LayerEvidence[];
|
|
41
|
+
/** Suppress the mutable address of an execution already archived as an immutable layer. */
|
|
42
|
+
export declare function distinctLayers(layers: readonly LayerSummary[]): LayerSummary[];
|
|
43
|
+
export declare function layerExecutionKey(layer: LayerSummary): string;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** Advisory identity, never a cryptographic integrity check. */
|
|
2
|
+
export function textFingerprint(text) {
|
|
3
|
+
let a = 2166136261, b = 5381;
|
|
4
|
+
for (let i = 0; i < text.length; i++) {
|
|
5
|
+
a = Math.imul(a ^ text.charCodeAt(i), 16777619);
|
|
6
|
+
b = Math.imul(b, 33) ^ text.charCodeAt(i);
|
|
7
|
+
}
|
|
8
|
+
return `${text.length}:${(a >>> 0).toString(16)}:${(b >>> 0).toString(16)}`;
|
|
9
|
+
}
|
|
10
|
+
export function specPath(path) {
|
|
11
|
+
return path.replaceAll('\\', '/').replace(/^\.\//, '').replace(/^.*?(?=specs\/)/, '');
|
|
12
|
+
}
|
|
13
|
+
export function parameterKey(parameters) {
|
|
14
|
+
return JSON.stringify(Object.entries(parameters).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
|
|
15
|
+
}
|
|
16
|
+
/** Recorded timings qualify an outcome. They are a result of their own only when nothing else checked the same thing. */
|
|
17
|
+
export function isDiagnosticKind(kind) {
|
|
18
|
+
return kind === 'performance';
|
|
19
|
+
}
|
|
20
|
+
export function emptyCounts() {
|
|
21
|
+
return { passed: 0, failed: 0, running: 0, 'not-run': 0 };
|
|
22
|
+
}
|
|
23
|
+
/** Outcomes of a layer: its checks, without the timings that only qualify them. */
|
|
24
|
+
export function outcomeCounts(rows) {
|
|
25
|
+
const outcomes = rows.some(row => !isDiagnosticKind(row.kind)) ? rows.filter(row => !isDiagnosticKind(row.kind)) : rows;
|
|
26
|
+
const counts = emptyCounts();
|
|
27
|
+
for (const row of outcomes)
|
|
28
|
+
counts[row.status] += 1;
|
|
29
|
+
return counts;
|
|
30
|
+
}
|
|
31
|
+
/** A layer as the explorer reads it: its origin, and each check as one row. */
|
|
32
|
+
export function layerEvidence(summary, backend) {
|
|
33
|
+
const source = summary.source;
|
|
34
|
+
const tests = new Map(source?.tests.map(test => [`${source.source}/${test.testId}`, test]) ?? []);
|
|
35
|
+
const rows = summary.parts.flatMap(part => part.checks.map(check => {
|
|
36
|
+
const test = tests.get(check.id);
|
|
37
|
+
const variant = test ? { system: test.system, runtime: test.runtime, seed: test.seed } : {};
|
|
38
|
+
return {
|
|
39
|
+
kind: part.kind,
|
|
40
|
+
id: check.id,
|
|
41
|
+
title: check.title,
|
|
42
|
+
status: check.status,
|
|
43
|
+
specPath: check.specPath ? specPath(check.specPath) : null,
|
|
44
|
+
detail: check.detail,
|
|
45
|
+
measurements: check.measurements,
|
|
46
|
+
testId: test?.testId ?? null,
|
|
47
|
+
variant,
|
|
48
|
+
durationMs: test?.durationMs ?? null,
|
|
49
|
+
};
|
|
50
|
+
}));
|
|
51
|
+
const recording = summary.recording;
|
|
52
|
+
const layer = {
|
|
53
|
+
...(summary.freshness ? { freshness: summary.freshness } : {}),
|
|
54
|
+
id: summary.id,
|
|
55
|
+
backend,
|
|
56
|
+
producer: summary.producer,
|
|
57
|
+
packageDir: source?.packageDir ?? null,
|
|
58
|
+
recordedAtMs: summary.recordedAtMs,
|
|
59
|
+
sha: summary.sha,
|
|
60
|
+
branch: summary.branch,
|
|
61
|
+
runUrl: summary.runUrl,
|
|
62
|
+
parameters: summary.parameters,
|
|
63
|
+
recording: recording === null ? null : recording.type === 'layer' ? { type: 'layer', layer: summary.id } : recording,
|
|
64
|
+
live: false,
|
|
65
|
+
counts: outcomeCounts(rows),
|
|
66
|
+
execution: textFingerprint(layerExecutionKey(summary)),
|
|
67
|
+
};
|
|
68
|
+
const fingerprints = {};
|
|
69
|
+
for (const spec of summary.specs)
|
|
70
|
+
if (spec.fingerprint)
|
|
71
|
+
fingerprints[specPath(spec.path)] = spec.fingerprint;
|
|
72
|
+
return { id: summary.id, layer, rows, fingerprints };
|
|
73
|
+
}
|
|
74
|
+
function warning(layer, path, current, outline, recorded, relatedChanged) {
|
|
75
|
+
if (layer.live)
|
|
76
|
+
return null;
|
|
77
|
+
if (layer.freshness === 'modified')
|
|
78
|
+
return 'Potentially outdated: recorded from a modified checkout';
|
|
79
|
+
if (layer.freshness === 'unknown')
|
|
80
|
+
return 'Freshness unknown: recording origin was not captured';
|
|
81
|
+
if (!path || !current)
|
|
82
|
+
return 'Spec is not in the current outline';
|
|
83
|
+
if (!recorded || !current.fingerprint)
|
|
84
|
+
return 'Freshness unknown: no recorded spec fingerprint';
|
|
85
|
+
if (recorded !== current.fingerprint)
|
|
86
|
+
return 'Potentially outdated: spec changed';
|
|
87
|
+
if (relatedChanged)
|
|
88
|
+
return 'Potentially outdated: related files changed';
|
|
89
|
+
if (!layer.sha || !outline.sha || layer.sha !== outline.sha)
|
|
90
|
+
return 'Potentially outdated: related code has not been compared';
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const RANK = { passed: 0, 'not-run': 1, running: 2, failed: 3 };
|
|
94
|
+
function completed(status) {
|
|
95
|
+
return status === 'passed' || status === 'failed';
|
|
96
|
+
}
|
|
97
|
+
/** A newer completed result takes its slot. An unfinished one never replaces a completed one, and a tie fails. */
|
|
98
|
+
function replaces(next, prior) {
|
|
99
|
+
const done = completed(next.row.status);
|
|
100
|
+
const priorDone = completed(prior.row.status);
|
|
101
|
+
if (done !== priorDone)
|
|
102
|
+
return done;
|
|
103
|
+
if (next.layer.recordedAtMs !== prior.layer.recordedAtMs)
|
|
104
|
+
return next.layer.recordedAtMs > prior.layer.recordedAtMs;
|
|
105
|
+
if (RANK[next.row.status] !== RANK[prior.row.status])
|
|
106
|
+
return RANK[next.row.status] > RANK[prior.row.status];
|
|
107
|
+
return next.layer.id > prior.layer.id;
|
|
108
|
+
}
|
|
109
|
+
/** One linear pass. Latest completed result wins only its own check/parameter slot. */
|
|
110
|
+
export function combineEvidence(outline, layers) {
|
|
111
|
+
const specs = new Map(outline.specs.map(spec => [specPath(spec.path), { spec, results: [] }]));
|
|
112
|
+
const changed = new Set(outline.changedFiles.map(specPath));
|
|
113
|
+
const winners = new Map();
|
|
114
|
+
for (const { layer, rows, fingerprints } of distinctEvidence(layers)) {
|
|
115
|
+
const scope = layer.packageDir;
|
|
116
|
+
const related = outline.changedFiles.some(file => scope ? file.startsWith(`${scope}/`) : !specPath(file).startsWith('specs/'));
|
|
117
|
+
for (const row of rows) {
|
|
118
|
+
const parameters = { ...layer.parameters, ...row.variant };
|
|
119
|
+
const path = row.specPath ?? '';
|
|
120
|
+
const key = JSON.stringify([layer.producer, row.kind, path, row.id, parameterKey(parameters)]);
|
|
121
|
+
const result = { key, slot: slotKey(path, row.id), layer, row, parameters, warning: warning(layer, path, specs.get(path)?.spec, outline, fingerprints[path], related || changed.has(path)) };
|
|
122
|
+
const prior = winners.get(key);
|
|
123
|
+
if (!prior || replaces(result, prior))
|
|
124
|
+
winners.set(key, result);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const unassigned = [];
|
|
128
|
+
for (const result of winners.values())
|
|
129
|
+
(specs.get(result.row.specPath ?? '')?.results ?? unassigned).push(result);
|
|
130
|
+
return { specs: [...specs.values()], unassigned };
|
|
131
|
+
}
|
|
132
|
+
export function slotKey(path, id) {
|
|
133
|
+
return JSON.stringify([path, id]);
|
|
134
|
+
}
|
|
135
|
+
function archived(id) {
|
|
136
|
+
return /^[0-9a-f]{64}$/.test(id);
|
|
137
|
+
}
|
|
138
|
+
/** Suppress the mutable address of an execution already archived as an immutable layer. */
|
|
139
|
+
export function distinctHeaders(layers) {
|
|
140
|
+
const kept = new Set(layers.filter(layer => archived(layer.id)).map(layer => layer.execution));
|
|
141
|
+
return [...new Map(layers.filter(layer => archived(layer.id) || !kept.has(layer.execution)).map(layer => [layer.id, layer])).values()];
|
|
142
|
+
}
|
|
143
|
+
export function distinctEvidence(layers) {
|
|
144
|
+
const kept = new Set(distinctHeaders(layers.map(entry => entry.layer)).map(layer => layer.id));
|
|
145
|
+
return [...new Map(layers.filter(entry => kept.has(entry.id)).map(entry => [entry.id, entry])).values()];
|
|
146
|
+
}
|
|
147
|
+
/** Suppress the mutable address of an execution already archived as an immutable layer. */
|
|
148
|
+
export function distinctLayers(layers) {
|
|
149
|
+
const kept = new Set(layers.filter(layer => archived(layer.id)).map(layerExecutionKey));
|
|
150
|
+
return [...new Map(layers.filter(layer => archived(layer.id) || !kept.has(layerExecutionKey(layer))).map(layer => [layer.id, layer])).values()];
|
|
151
|
+
}
|
|
152
|
+
export function layerExecutionKey(layer) {
|
|
153
|
+
return JSON.stringify([layer.producer, layer.sha, layer.recordedAtMs, layer.parts]);
|
|
154
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HtmlReportTest } from './recording-bundle.js';
|
|
2
|
+
import { type BundleIndex } from './bundle.js';
|
|
3
|
+
import type { ObjectStore } from './object-store.js';
|
|
4
|
+
import type { SourceRecord } from './protocol.js';
|
|
5
|
+
import type { PublishSourceArgs } from './publish.js';
|
|
6
|
+
export declare function archiveSourceLayer(store: ObjectStore, args: PublishSourceArgs, source: SourceRecord, tests: readonly HtmlReportTest[], bundle?: BundleIndex): Promise<import('./layer-types.js').ReportLayer>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { writeBundle } from './bundle.js';
|
|
2
|
+
import { readCommit, readFrameCss } from './read.js';
|
|
3
|
+
import { readInventory } from './spec-inventory.js';
|
|
4
|
+
import { sourceParts } from './source-part.js';
|
|
5
|
+
import { sourceEntries } from './source-entries.js';
|
|
6
|
+
import { publishLayerBundle } from './layer-store.js';
|
|
7
|
+
export async function archiveSourceLayer(store, args, source, tests, bundle) {
|
|
8
|
+
const [commit, inventory, css] = await Promise.all([readCommit(store, args.sha), readInventory(store, args.sha), readFrameCss(store, args.sha)]);
|
|
9
|
+
const recordedAtMs = Math.max(commit?.startedAtMs ?? 0, source.updatedAtMs);
|
|
10
|
+
const runId = args.runId ?? 'latest';
|
|
11
|
+
const prefix = `commits/${args.sha}/tests/${source.source}/`;
|
|
12
|
+
const layerPath = (key) => {
|
|
13
|
+
const tail = key.slice(prefix.length), slash = tail.indexOf('/');
|
|
14
|
+
const test = tail.slice(0, slash), file = tail.slice(slash + 1);
|
|
15
|
+
return `tests/${test}/${file === 'report.json' ? file : `files/${file}`}`;
|
|
16
|
+
};
|
|
17
|
+
async function* entries() {
|
|
18
|
+
if (css)
|
|
19
|
+
yield { key: 'frame.css', bytes: new Uint8Array(await new Response(css.body).arrayBuffer()), contentType: css.contentType };
|
|
20
|
+
if (bundle)
|
|
21
|
+
return;
|
|
22
|
+
for await (const entry of sourceEntries(args, source.source, tests, runId))
|
|
23
|
+
yield { ...entry, key: layerPath(entry.key) };
|
|
24
|
+
}
|
|
25
|
+
const index = await writeBundle(store, entries(), 'layers/blobs/');
|
|
26
|
+
for (const [key, value] of Object.entries(bundle ?? {}))
|
|
27
|
+
index[layerPath(key)] = value;
|
|
28
|
+
return publishLayerBundle(store, {
|
|
29
|
+
...(args.freshness ? { freshness: args.freshness } : {}), producer: source.source, recordedAtMs, sha: args.sha, branch: commit?.branch ?? null, runUrl: commit?.runUrl ?? null,
|
|
30
|
+
parameters: args.parameters ?? {}, specs: inventory?.entries ?? [], parts: sourceParts(args.sha, source), source, recording: { type: 'layer' },
|
|
31
|
+
}, index);
|
|
32
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type BundleIndex, type BundleEntry } from './bundle.js';
|
|
2
|
+
import type { ObjectStore } from './object-store.js';
|
|
3
|
+
import type { LayerSummary, ReportLayer } from './layer-types.js';
|
|
4
|
+
export declare const LAYER_INDEX = "layers/index/";
|
|
5
|
+
export declare function layerKey(id: string): string;
|
|
6
|
+
export declare function publishLayer(store: ObjectStore, summary: Omit<LayerSummary, 'id'>, entries: AsyncIterable<BundleEntry>): Promise<ReportLayer>;
|
|
7
|
+
export declare function publishLayerBundle(store: ObjectStore, summary: Omit<LayerSummary, 'id'>, bundle: BundleIndex): Promise<ReportLayer>;
|
|
8
|
+
export declare function readLayer(store: ObjectStore, id: string): Promise<ReportLayer | null>;
|
|
9
|
+
export declare function readLayerFile(store: ObjectStore, id: string, file: string): Promise<BundleEntry | null>;
|
|
10
|
+
export declare function layerSummary(layer: ReportLayer): LayerSummary;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createBundleReader, writeBundle } from './bundle.js';
|
|
2
|
+
import { readUtf8, writeUtf8 } from './object-io.js';
|
|
3
|
+
export const LAYER_INDEX = 'layers/index/';
|
|
4
|
+
export function layerKey(id) {
|
|
5
|
+
if (!/^[0-9a-f]{64}$/.test(id))
|
|
6
|
+
throw new Error('Invalid layer id');
|
|
7
|
+
return `layers/manifests/${id}.json`;
|
|
8
|
+
}
|
|
9
|
+
export async function publishLayer(store, summary, entries) {
|
|
10
|
+
const bundle = await writeBundle(store, entries, 'layers/blobs/');
|
|
11
|
+
return publishLayerBundle(store, summary, bundle);
|
|
12
|
+
}
|
|
13
|
+
export async function publishLayerBundle(store, summary, bundle) {
|
|
14
|
+
const body = JSON.stringify({ ...summary, bundle });
|
|
15
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(body));
|
|
16
|
+
const id = [...new Uint8Array(digest)].map(byte => byte.toString(16).padStart(2, '0')).join('');
|
|
17
|
+
const layer = { ...summary, id, bundle };
|
|
18
|
+
// Immutable manifest first, independent catalog entry last: concurrent producers never overwrite one another.
|
|
19
|
+
if (!(await store.head(layerKey(id))))
|
|
20
|
+
await writeUtf8(store, layerKey(id), JSON.stringify(layer), 'application/json');
|
|
21
|
+
const inverse = String(Number.MAX_SAFE_INTEGER - Math.max(0, Math.floor(summary.recordedAtMs))).padStart(16, '0');
|
|
22
|
+
await writeUtf8(store, `${LAYER_INDEX}${inverse}-${id}.json`, JSON.stringify({ id }), 'application/json');
|
|
23
|
+
return layer;
|
|
24
|
+
}
|
|
25
|
+
export async function readLayer(store, id) {
|
|
26
|
+
const raw = await readUtf8(store, layerKey(id));
|
|
27
|
+
return raw === null ? null : JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
export async function readLayerFile(store, id, file) {
|
|
30
|
+
const layer = await readLayer(store, id);
|
|
31
|
+
return layer ? createBundleReader(store, layer.bundle)(file) : null;
|
|
32
|
+
}
|
|
33
|
+
export function layerSummary(layer) {
|
|
34
|
+
const { bundle: _, ...summary } = layer;
|
|
35
|
+
return summary;
|
|
36
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BundleIndex } from './bundle.js';
|
|
2
|
+
import type { ReportPart, SpecEntry } from './explorer-types.js';
|
|
3
|
+
import type { SourceRecord } from './protocol.js';
|
|
4
|
+
export type LayerParameters = Readonly<Record<string, string>>;
|
|
5
|
+
export type LayerSummary = {
|
|
6
|
+
readonly freshness?: 'unknown' | 'modified';
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly recordedAtMs: number;
|
|
9
|
+
readonly producer: string;
|
|
10
|
+
readonly sha: string | null;
|
|
11
|
+
readonly branch: string | null;
|
|
12
|
+
readonly runUrl: string | null;
|
|
13
|
+
readonly parameters: LayerParameters;
|
|
14
|
+
readonly specs: readonly SpecEntry[];
|
|
15
|
+
readonly parts: readonly ReportPart[];
|
|
16
|
+
readonly source: SourceRecord | null;
|
|
17
|
+
readonly recording: {
|
|
18
|
+
readonly type: 'layer';
|
|
19
|
+
} | {
|
|
20
|
+
readonly type: 'commit';
|
|
21
|
+
readonly sha: string;
|
|
22
|
+
readonly source: string;
|
|
23
|
+
} | null;
|
|
24
|
+
};
|
|
25
|
+
export type ReportLayer = LayerSummary & {
|
|
26
|
+
readonly bundle: BundleIndex;
|
|
27
|
+
};
|
|
28
|
+
export type ReportOutline = {
|
|
29
|
+
readonly specs: readonly SpecEntry[];
|
|
30
|
+
readonly sha: string | null;
|
|
31
|
+
readonly changedFiles: readonly string[];
|
|
32
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { ObjectStore } from './object-store.js';
|
|
3
|
+
import type { ReportsAppDeps } from './reports-route.js';
|
|
4
|
+
/** A further store whose layers join the combined report, beside the local and the shared one. */
|
|
5
|
+
export type ReportBackend = {
|
|
6
|
+
/** Stable and unique: letters, digits and hyphens. `local` and `shared` are taken. */
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly label: string;
|
|
9
|
+
readonly store: ObjectStore;
|
|
10
|
+
};
|
|
11
|
+
type Backend = ReportBackend & {
|
|
12
|
+
readonly live: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare const LOCAL_BACKEND = "local";
|
|
15
|
+
export declare const SHARED_BACKEND = "shared";
|
|
16
|
+
/** The stores that contribute layers, in the order they answer for a recording. */
|
|
17
|
+
export declare function reportBackends(deps: ReportsAppDeps): Backend[];
|
|
18
|
+
/** Bounded pages of layer origins, each layer's checks read once, and the runs still writing. */
|
|
19
|
+
export declare function createLayersApp(deps: ReportsAppDeps): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
20
|
+
export {};
|