@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,152 @@
|
|
|
1
|
+
import { closeSync, openSync, readSync, statSync } from 'node:fs';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
function readBody(req) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
let body = '';
|
|
7
|
+
req.setEncoding('utf8');
|
|
8
|
+
req.on('data', (chunk) => (body += chunk));
|
|
9
|
+
req.on('end', () => resolve(body));
|
|
10
|
+
req.on('error', reject);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/** Parse an HTTP delivery in either CloudEvents content mode (structured, binary or batch). */
|
|
14
|
+
export function cloudEventsFromHttp(headers, body) {
|
|
15
|
+
const header = (name) => {
|
|
16
|
+
const value = headers[name];
|
|
17
|
+
return Array.isArray(value) ? value[0] : value;
|
|
18
|
+
};
|
|
19
|
+
const contentType = header('content-type') ?? '';
|
|
20
|
+
if (contentType.startsWith('application/cloudevents-batch+json'))
|
|
21
|
+
return JSON.parse(body);
|
|
22
|
+
if (contentType.startsWith('application/cloudevents+json'))
|
|
23
|
+
return [JSON.parse(body)];
|
|
24
|
+
const type = header('ce-type');
|
|
25
|
+
if (!type)
|
|
26
|
+
return [];
|
|
27
|
+
const time = header('ce-time');
|
|
28
|
+
const subject = header('ce-subject');
|
|
29
|
+
const extensions = Object.fromEntries(Object.entries(headers)
|
|
30
|
+
.filter(([k]) => k.startsWith('ce-') && !['ce-specversion', 'ce-id', 'ce-source', 'ce-type', 'ce-time', 'ce-subject'].includes(k))
|
|
31
|
+
.map(([k, v]) => [k.slice(3), Array.isArray(v) ? v[0] : v]));
|
|
32
|
+
let data = body;
|
|
33
|
+
if (contentType.includes('json') && body) {
|
|
34
|
+
try {
|
|
35
|
+
data = JSON.parse(body);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
data = body;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
...extensions,
|
|
44
|
+
specversion: '1.0',
|
|
45
|
+
id: header('ce-id') ?? randomUUID(),
|
|
46
|
+
source: header('ce-source') ?? 'unknown',
|
|
47
|
+
type,
|
|
48
|
+
...(time ? { time } : {}),
|
|
49
|
+
...(subject ? { subject } : {}),
|
|
50
|
+
...(contentType ? { datacontenttype: contentType } : {}),
|
|
51
|
+
data
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* An HTTP endpoint the system under test sends CloudEvents to (any content mode). Point the
|
|
57
|
+
* product's event bus, webhook relay or OpenTelemetry collector's CloudEvents exporter at it.
|
|
58
|
+
*/
|
|
59
|
+
export async function cloudEventsHttpSource(options = {}) {
|
|
60
|
+
const received = [];
|
|
61
|
+
const server = createServer(async (req, res) => {
|
|
62
|
+
try {
|
|
63
|
+
const events = cloudEventsFromHttp(req.headers, await readBody(req));
|
|
64
|
+
received.push(...events);
|
|
65
|
+
res.writeHead(202).end();
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
res.writeHead(400).end();
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
await new Promise((resolve) => server.listen(options.port ?? 0, options.host ?? '127.0.0.1', resolve));
|
|
72
|
+
const address = server.address();
|
|
73
|
+
const port = typeof address === 'object' && address ? address.port : options.port;
|
|
74
|
+
return {
|
|
75
|
+
name: 'cloudevents-http',
|
|
76
|
+
url: `http://${options.host ?? '127.0.0.1'}:${port}/`,
|
|
77
|
+
mark: () => received.length,
|
|
78
|
+
collect: async (from) => ({ events: received.slice(typeof from === 'number' ? from : 0) }),
|
|
79
|
+
close: () => new Promise((resolve) => server.close(() => resolve()))
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Lines appended to a log file during a step, for products whose only event stream is a log. */
|
|
83
|
+
export function logFileSource(file, options = {}) {
|
|
84
|
+
return {
|
|
85
|
+
name: `log:${file}`,
|
|
86
|
+
mark: () => {
|
|
87
|
+
try {
|
|
88
|
+
return statSync(file).size;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
collect: async (from) => {
|
|
95
|
+
await new Promise((r) => setTimeout(r, options.settleMs ?? 1_000));
|
|
96
|
+
const offset = typeof from === 'number' ? from : 0;
|
|
97
|
+
try {
|
|
98
|
+
const size = statSync(file).size;
|
|
99
|
+
const length = Math.max(0, size - offset);
|
|
100
|
+
const buffer = Buffer.alloc(length);
|
|
101
|
+
const fd = openSync(file, 'r');
|
|
102
|
+
readSync(fd, buffer, 0, length, offset);
|
|
103
|
+
closeSync(fd);
|
|
104
|
+
return { events: [], text: buffer.toString('utf8') };
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return { events: [], text: '' };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Keep what belongs to one attempt when attempts run side by side: events and log lines that
|
|
114
|
+
* mention one of its correlation ids. With no ids, everything is kept.
|
|
115
|
+
*/
|
|
116
|
+
export function correlated(collected, ids) {
|
|
117
|
+
const wanted = ids.filter(Boolean);
|
|
118
|
+
if (!wanted.length)
|
|
119
|
+
return collected;
|
|
120
|
+
const mentions = (value) => wanted.some((id) => value.includes(id));
|
|
121
|
+
return {
|
|
122
|
+
events: collected.events.filter((e) => mentions(JSON.stringify(e))),
|
|
123
|
+
text: collected.text.split('\n').filter(mentions).join('\n')
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Compare the business events a state expects with what the sources saw. A business event is
|
|
128
|
+
* observed when its matcher matches; with no matcher, a CloudEvent whose `type` equals the name.
|
|
129
|
+
* Events with neither a matcher nor any CloudEvents source are "no signal", never "missing".
|
|
130
|
+
*/
|
|
131
|
+
export function compareBusinessEvents(expected, collected, matchers, hasCloudEvents) {
|
|
132
|
+
const result = { expected, observed: [], missing: [], noSignal: [], events: collected.events };
|
|
133
|
+
for (const name of expected) {
|
|
134
|
+
const matcher = matchers[name];
|
|
135
|
+
let seen;
|
|
136
|
+
if (typeof matcher === 'function')
|
|
137
|
+
seen = matcher(collected.events, collected.text);
|
|
138
|
+
else if (matcher && 'type' in matcher)
|
|
139
|
+
seen = collected.events.some((e) => e.type === matcher.type);
|
|
140
|
+
else if (matcher && 'pattern' in matcher)
|
|
141
|
+
seen = matcher.pattern.test(collected.text);
|
|
142
|
+
else
|
|
143
|
+
seen = hasCloudEvents ? collected.events.some((e) => e.type === name) : null;
|
|
144
|
+
if (seen === null)
|
|
145
|
+
result.noSignal.push(name);
|
|
146
|
+
else if (seen)
|
|
147
|
+
result.observed.push(name);
|
|
148
|
+
else
|
|
149
|
+
result.missing.push(name);
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { HandOff } from './spec/compose.js';
|
|
2
|
+
import type { MachineConfig, StateConfig } from './spec/types.js';
|
|
3
|
+
export type StateValue = string | {
|
|
4
|
+
[key: string]: StateValue;
|
|
5
|
+
};
|
|
6
|
+
export type Step = {
|
|
7
|
+
event: string;
|
|
8
|
+
transitions: string[];
|
|
9
|
+
handOff: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type Config = {
|
|
12
|
+
value: StateValue;
|
|
13
|
+
active: string[];
|
|
14
|
+
};
|
|
15
|
+
/** A configuration's identity: its state value with keys sorted, so equal configurations compare equal. */
|
|
16
|
+
export declare function configKey(value: StateValue): string;
|
|
17
|
+
export declare function activeKeys(value: StateValue): string[];
|
|
18
|
+
/**
|
|
19
|
+
* A pure simulator over a composed machine: XState computes the next configuration, and this
|
|
20
|
+
* names which transitions fired, so coverage and the report can talk about transitions.
|
|
21
|
+
*/
|
|
22
|
+
export declare class ChartGraph {
|
|
23
|
+
readonly config: MachineConfig;
|
|
24
|
+
readonly machine: import("xstate").StateMachine<import("xstate").MachineContext, import("xstate").AnyEventObject, Record<string, import("xstate").AnyActorRef>, import("xstate").ProvidedActor, import("xstate").ParameterizedObject, import("xstate").ParameterizedObject, string, import("xstate").StateValue, string, unknown, {} | null | undefined, import("xstate").EventObject, import("xstate").MetaObject, any, import("xstate").MetaObject>;
|
|
25
|
+
private readonly nodes;
|
|
26
|
+
private readonly parentOf;
|
|
27
|
+
readonly handOffStates: Map<string, string>;
|
|
28
|
+
constructor(config: MachineConfig, handOffs?: HandOff[]);
|
|
29
|
+
node(name: string): StateConfig | undefined;
|
|
30
|
+
/** The state a transition leads to, by name. */
|
|
31
|
+
target(source: string, event: string): string | undefined;
|
|
32
|
+
isLeaf(name: string): boolean;
|
|
33
|
+
parent(name: string): string | null;
|
|
34
|
+
stateNames(): string[];
|
|
35
|
+
/** The parallel regions a state sits in, outermost first: each the child of a parallel ancestor. */
|
|
36
|
+
regionsOf(state: string): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Whether an event can matter to what happens in `regions`: some state that handles it sits in
|
|
39
|
+
* those regions or outside them (never only in a sibling region). Regions of a statechart
|
|
40
|
+
* without guards are independent, so exploring one region with the others held still loses
|
|
41
|
+
* nothing and keeps the search from multiplying across regions.
|
|
42
|
+
*/
|
|
43
|
+
actsIn(event: string, regions: string[]): boolean;
|
|
44
|
+
/** Every distinct set of regions a state sits in, the empty set (outside every parallel) first. */
|
|
45
|
+
regionSets(): string[][];
|
|
46
|
+
initial(): Config;
|
|
47
|
+
/** The state value that names `state`: its ancestors down to it, defaults filled in by `resolve`. */
|
|
48
|
+
valueOf(state: string): StateValue;
|
|
49
|
+
resolve(value: StateValue): Config;
|
|
50
|
+
enabledEvents(config: Config): string[];
|
|
51
|
+
/** The transitions `event` fires from `config`: in each region, the deepest active state that handles it. */
|
|
52
|
+
firedBy(config: Config, event: string): string[];
|
|
53
|
+
private isDescendant;
|
|
54
|
+
step(config: Config, event: string): {
|
|
55
|
+
config: Config;
|
|
56
|
+
fired: string[];
|
|
57
|
+
} | null;
|
|
58
|
+
/** Hand-off states active in `config` (a child's former final states), with the event each passes on. */
|
|
59
|
+
pendingHandOffs(config: Config): {
|
|
60
|
+
state: string;
|
|
61
|
+
event: string;
|
|
62
|
+
}[];
|
|
63
|
+
/**
|
|
64
|
+
* Replay member- and system-sent events, inserting hand-off events whenever a hand-off state
|
|
65
|
+
* becomes active, as the composed spec says the parent receives them automatically.
|
|
66
|
+
*/
|
|
67
|
+
replay(start: Config, events: readonly string[]): {
|
|
68
|
+
ok: false;
|
|
69
|
+
steps: (Step & {
|
|
70
|
+
from: Config;
|
|
71
|
+
to: Config;
|
|
72
|
+
})[];
|
|
73
|
+
config: Config;
|
|
74
|
+
failedAt: string;
|
|
75
|
+
} | {
|
|
76
|
+
ok: true;
|
|
77
|
+
steps: (Step & {
|
|
78
|
+
from: Config;
|
|
79
|
+
to: Config;
|
|
80
|
+
})[];
|
|
81
|
+
config: Config;
|
|
82
|
+
failedAt?: undefined;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Breadth-first from one or several starts at once: every configuration reachable using only
|
|
86
|
+
* `allowed` events, each with the shortest event path from its nearest start (`origin` is that
|
|
87
|
+
* start's index; ties go to the earlier start). `firstFired` holds, for every transition, the
|
|
88
|
+
* shortest way to take it: the configuration it fires from and how that configuration was
|
|
89
|
+
* reached. Exploration order is fixed by the chart, so the result is deterministic.
|
|
90
|
+
*/
|
|
91
|
+
explore(start: Config | Config[], allowed: (event: string) => boolean, maxConfigs?: number): {
|
|
92
|
+
seen: Map<string, {
|
|
93
|
+
config: Config;
|
|
94
|
+
path: string[];
|
|
95
|
+
origin: number;
|
|
96
|
+
}>;
|
|
97
|
+
edges: {
|
|
98
|
+
from: string;
|
|
99
|
+
event: string;
|
|
100
|
+
to: string;
|
|
101
|
+
fired: string[];
|
|
102
|
+
}[];
|
|
103
|
+
key: (c: Config) => string;
|
|
104
|
+
firstFired: Map<string, {
|
|
105
|
+
from: {
|
|
106
|
+
config: Config;
|
|
107
|
+
path: string[];
|
|
108
|
+
origin: number;
|
|
109
|
+
};
|
|
110
|
+
event: string;
|
|
111
|
+
}>;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { createMachine, initialTransition, transition } from 'xstate';
|
|
2
|
+
import { targetOf, transitionId, walkStates } from './spec/types.js';
|
|
3
|
+
/** A configuration's identity: its state value with keys sorted, so equal configurations compare equal. */
|
|
4
|
+
export function configKey(value) {
|
|
5
|
+
const canonical = (v) => typeof v === 'string' ? v : Object.fromEntries(Object.keys(v).sort().map((k) => [k, canonical(v[k])]));
|
|
6
|
+
return JSON.stringify(canonical(value));
|
|
7
|
+
}
|
|
8
|
+
export function activeKeys(value) {
|
|
9
|
+
if (typeof value === 'string')
|
|
10
|
+
return [value];
|
|
11
|
+
return Object.entries(value).flatMap(([key, child]) => [key, ...activeKeys(child)]);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A pure simulator over a composed machine: XState computes the next configuration, and this
|
|
15
|
+
* names which transitions fired, so coverage and the report can talk about transitions.
|
|
16
|
+
*/
|
|
17
|
+
export class ChartGraph {
|
|
18
|
+
config;
|
|
19
|
+
machine;
|
|
20
|
+
nodes = new Map();
|
|
21
|
+
parentOf = new Map();
|
|
22
|
+
handOffStates;
|
|
23
|
+
constructor(config, handOffs = []) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.machine = createMachine(config);
|
|
26
|
+
for (const { name, node, trail } of walkStates(config)) {
|
|
27
|
+
this.nodes.set(name, node);
|
|
28
|
+
this.parentOf.set(name, trail.at(-1) ?? null);
|
|
29
|
+
}
|
|
30
|
+
this.handOffStates = new Map(handOffs.map((h) => [h.finalState, h.event]));
|
|
31
|
+
}
|
|
32
|
+
node(name) {
|
|
33
|
+
return this.nodes.get(name);
|
|
34
|
+
}
|
|
35
|
+
/** The state a transition leads to, by name. */
|
|
36
|
+
target(source, event) {
|
|
37
|
+
return targetOf(this.nodes.get(source)?.on?.[event]);
|
|
38
|
+
}
|
|
39
|
+
isLeaf(name) {
|
|
40
|
+
return !this.nodes.get(name)?.states;
|
|
41
|
+
}
|
|
42
|
+
parent(name) {
|
|
43
|
+
return this.parentOf.get(name) ?? null;
|
|
44
|
+
}
|
|
45
|
+
stateNames() {
|
|
46
|
+
return [...this.nodes.keys()];
|
|
47
|
+
}
|
|
48
|
+
/** The parallel regions a state sits in, outermost first: each the child of a parallel ancestor. */
|
|
49
|
+
regionsOf(state) {
|
|
50
|
+
const regions = [];
|
|
51
|
+
for (let child = state, parent = this.parent(state); parent; child = parent, parent = this.parent(parent)) {
|
|
52
|
+
if (this.nodes.get(parent)?.type === 'parallel')
|
|
53
|
+
regions.unshift(child);
|
|
54
|
+
}
|
|
55
|
+
return regions;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether an event can matter to what happens in `regions`: some state that handles it sits in
|
|
59
|
+
* those regions or outside them (never only in a sibling region). Regions of a statechart
|
|
60
|
+
* without guards are independent, so exploring one region with the others held still loses
|
|
61
|
+
* nothing and keeps the search from multiplying across regions.
|
|
62
|
+
*/
|
|
63
|
+
actsIn(event, regions) {
|
|
64
|
+
let handled = false;
|
|
65
|
+
for (const [name, node] of this.nodes) {
|
|
66
|
+
if (!node.on?.[event])
|
|
67
|
+
continue;
|
|
68
|
+
handled = true;
|
|
69
|
+
const own = this.regionsOf(name);
|
|
70
|
+
if (own.every((region, i) => regions[i] === region))
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return !handled;
|
|
74
|
+
}
|
|
75
|
+
/** Every distinct set of regions a state sits in, the empty set (outside every parallel) first. */
|
|
76
|
+
regionSets() {
|
|
77
|
+
const keyed = new Map([['', []]]);
|
|
78
|
+
for (const name of this.nodes.keys()) {
|
|
79
|
+
const regions = this.regionsOf(name);
|
|
80
|
+
keyed.set(regions.join('\u0000'), regions);
|
|
81
|
+
}
|
|
82
|
+
return [...keyed.values()];
|
|
83
|
+
}
|
|
84
|
+
initial() {
|
|
85
|
+
const [snapshot] = initialTransition(this.machine);
|
|
86
|
+
return {
|
|
87
|
+
value: snapshot.value,
|
|
88
|
+
active: activeKeys(snapshot.value)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** The state value that names `state`: its ancestors down to it, defaults filled in by `resolve`. */
|
|
92
|
+
valueOf(state) {
|
|
93
|
+
if (!this.nodes.has(state))
|
|
94
|
+
throw new Error(`There is no state "${state}"`);
|
|
95
|
+
const trail = [];
|
|
96
|
+
for (let n = state; n; n = this.parent(n))
|
|
97
|
+
trail.unshift(n);
|
|
98
|
+
return trail.reduceRight((inner, name) => (inner === null ? name : { [name]: inner }), null);
|
|
99
|
+
}
|
|
100
|
+
resolve(value) {
|
|
101
|
+
const snapshot = this.machine.resolveState({ value });
|
|
102
|
+
return {
|
|
103
|
+
value: snapshot.value,
|
|
104
|
+
active: activeKeys(snapshot.value)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
enabledEvents(config) {
|
|
108
|
+
const events = new Set();
|
|
109
|
+
for (const name of config.active) {
|
|
110
|
+
for (const event of Object.keys(this.nodes.get(name)?.on ?? {}))
|
|
111
|
+
events.add(event);
|
|
112
|
+
}
|
|
113
|
+
return [...events];
|
|
114
|
+
}
|
|
115
|
+
/** The transitions `event` fires from `config`: in each region, the deepest active state that handles it. */
|
|
116
|
+
firedBy(config, event) {
|
|
117
|
+
const candidates = config.active.filter((name) => this.nodes.get(name)?.on?.[event]);
|
|
118
|
+
const hasActiveDescendantCandidate = (name) => candidates.some((other) => other !== name && this.isDescendant(other, name));
|
|
119
|
+
return candidates
|
|
120
|
+
.filter((name) => !hasActiveDescendantCandidate(name))
|
|
121
|
+
.map((name) => transitionId(name, event));
|
|
122
|
+
}
|
|
123
|
+
isDescendant(name, ancestor) {
|
|
124
|
+
for (let p = this.parentOf.get(name); p; p = this.parentOf.get(p)) {
|
|
125
|
+
if (p === ancestor)
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
step(config, event) {
|
|
131
|
+
const fired = this.firedBy(config, event);
|
|
132
|
+
if (fired.length === 0)
|
|
133
|
+
return null;
|
|
134
|
+
const snapshot = this.machine.resolveState({ value: config.value });
|
|
135
|
+
const [next] = transition(this.machine, snapshot, { type: event });
|
|
136
|
+
const value = next.value;
|
|
137
|
+
return { config: { value, active: activeKeys(value) }, fired };
|
|
138
|
+
}
|
|
139
|
+
/** Hand-off states active in `config` (a child's former final states), with the event each passes on. */
|
|
140
|
+
pendingHandOffs(config) {
|
|
141
|
+
return config.active
|
|
142
|
+
.filter((name) => this.handOffStates.has(name))
|
|
143
|
+
.map((name) => ({ state: name, event: this.handOffStates.get(name) }));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Replay member- and system-sent events, inserting hand-off events whenever a hand-off state
|
|
147
|
+
* becomes active, as the composed spec says the parent receives them automatically.
|
|
148
|
+
*/
|
|
149
|
+
replay(start, events) {
|
|
150
|
+
let config = start;
|
|
151
|
+
const steps = [];
|
|
152
|
+
const settle = () => {
|
|
153
|
+
for (;;) {
|
|
154
|
+
const pending = this.pendingHandOffs(config);
|
|
155
|
+
if (pending.length === 0)
|
|
156
|
+
return;
|
|
157
|
+
const handOff = pending[0];
|
|
158
|
+
const next = this.step(config, handOff.event);
|
|
159
|
+
if (!next)
|
|
160
|
+
return;
|
|
161
|
+
steps.push({
|
|
162
|
+
event: handOff.event,
|
|
163
|
+
transitions: next.fired,
|
|
164
|
+
handOff: true,
|
|
165
|
+
from: config,
|
|
166
|
+
to: next.config
|
|
167
|
+
});
|
|
168
|
+
config = next.config;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
for (const event of events) {
|
|
172
|
+
const next = this.step(config, event);
|
|
173
|
+
if (!next) {
|
|
174
|
+
return { ok: false, steps, config, failedAt: event };
|
|
175
|
+
}
|
|
176
|
+
steps.push({ event, transitions: next.fired, handOff: false, from: config, to: next.config });
|
|
177
|
+
config = next.config;
|
|
178
|
+
settle();
|
|
179
|
+
}
|
|
180
|
+
return { ok: true, steps, config };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Breadth-first from one or several starts at once: every configuration reachable using only
|
|
184
|
+
* `allowed` events, each with the shortest event path from its nearest start (`origin` is that
|
|
185
|
+
* start's index; ties go to the earlier start). `firstFired` holds, for every transition, the
|
|
186
|
+
* shortest way to take it: the configuration it fires from and how that configuration was
|
|
187
|
+
* reached. Exploration order is fixed by the chart, so the result is deterministic.
|
|
188
|
+
*/
|
|
189
|
+
explore(start, allowed, maxConfigs = 20_000) {
|
|
190
|
+
const starts = Array.isArray(start) ? start : [start];
|
|
191
|
+
const key = (c) => configKey(c.value);
|
|
192
|
+
const seen = new Map();
|
|
193
|
+
const queue = [];
|
|
194
|
+
starts.forEach((config, origin) => {
|
|
195
|
+
if (seen.has(key(config)))
|
|
196
|
+
return;
|
|
197
|
+
seen.set(key(config), { config, path: [], origin });
|
|
198
|
+
queue.push(config);
|
|
199
|
+
});
|
|
200
|
+
const edges = [];
|
|
201
|
+
const firstFired = new Map();
|
|
202
|
+
for (let head = 0; head < queue.length && seen.size < maxConfigs; head++) {
|
|
203
|
+
const config = queue[head];
|
|
204
|
+
const here = seen.get(key(config));
|
|
205
|
+
for (const event of this.enabledEvents(config).filter(allowed)) {
|
|
206
|
+
const next = this.step(config, event);
|
|
207
|
+
if (!next)
|
|
208
|
+
continue;
|
|
209
|
+
edges.push({ from: key(config), event, to: key(next.config), fired: next.fired });
|
|
210
|
+
for (const t of next.fired)
|
|
211
|
+
if (!firstFired.has(t))
|
|
212
|
+
firstFired.set(t, { from: here, event });
|
|
213
|
+
if (!seen.has(key(next.config))) {
|
|
214
|
+
seen.set(key(next.config), { config: next.config, path: [...here.path, event], origin: here.origin });
|
|
215
|
+
queue.push(next.config);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { seen, edges, key, firstFired };
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './spec/types.js';
|
|
2
|
+
export { parseChart, parseJourneys, loadSpecDirectory, bundleOf, childChartIds } from './spec/load.js';
|
|
3
|
+
export { scxmlToMachine, machineToScxml, scxmlToken, ATLAS_NS } from './spec/scxml.js';
|
|
4
|
+
export { composeCharts, type Composition, type HandOff } from './spec/compose.js';
|
|
5
|
+
export { ChartGraph, activeKeys, configKey, type Config, type StateValue } from './graph.js';
|
|
6
|
+
export { lintBundle, type LintFinding, type LintOptions } from './lint.js';
|
|
7
|
+
export { chartScope, pathKey, planChart, runnableSteps, type ChartScope, type PlannedJourney, type PlannedPath, type PlannedStep, type PlanOptions, type ScopeOptions, type SeedPoint } from './plan.js';
|
|
8
|
+
export * from './run/types.js';
|
|
9
|
+
export { buildManifest, durationHistory, estimateMs, latestRun, mergeRuns, readOutcomes, runPaths, shardPaths, writeRun, type Manifest, type PathOutcome, type PlannedSeed, type RunContext, type RunOptions, type Shard } from './run/execute.js';
|
|
10
|
+
export { combineDrivers, combineImplementations, mergeImplementations, onClient, type CombineDriversOptions, type ImplementationPart } from './run/clients.js';
|
|
11
|
+
export { recordFrames, type FrameRecorderOptions } from './run/frames.js';
|
|
12
|
+
export { httpDriver, httpClient, type HttpClient, type HttpDriverOptions, type HttpRequestOptions, type HttpResponse } from './run/http.js';
|
|
13
|
+
export { cloudEventsHttpSource, cloudEventsFromHttp, logFileSource, compareBusinessEvents, correlated, type CloudEvent, type BusinessEventResult } from './events/cloudevents.js';
|
|
14
|
+
export { DEFAULT_PRIVACY, mergePrivacy, privacyFindings, assertAllowedTarget } from './privacy.js';
|
|
15
|
+
export { toJUnit, toCtrf, toWebVtt, toMermaid } from './report/formats.js';
|
|
16
|
+
export { toMarkdown } from './report/markdown.js';
|
|
17
|
+
export { defineConfig, mergeConfigRuns, prepare, runConfig, type AtlasConfig, type PrepareOptions, type RunCommandOptions } from './config.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './spec/types.js';
|
|
2
|
+
export { parseChart, parseJourneys, loadSpecDirectory, bundleOf, childChartIds } from './spec/load.js';
|
|
3
|
+
export { scxmlToMachine, machineToScxml, scxmlToken, ATLAS_NS } from './spec/scxml.js';
|
|
4
|
+
export { composeCharts } from './spec/compose.js';
|
|
5
|
+
export { ChartGraph, activeKeys, configKey } from './graph.js';
|
|
6
|
+
export { lintBundle } from './lint.js';
|
|
7
|
+
export { chartScope, pathKey, planChart, runnableSteps } from './plan.js';
|
|
8
|
+
export * from './run/types.js';
|
|
9
|
+
export { buildManifest, durationHistory, estimateMs, latestRun, mergeRuns, readOutcomes, runPaths, shardPaths, writeRun } from './run/execute.js';
|
|
10
|
+
export { combineDrivers, combineImplementations, mergeImplementations, onClient } from './run/clients.js';
|
|
11
|
+
export { recordFrames } from './run/frames.js';
|
|
12
|
+
export { httpDriver, httpClient } from './run/http.js';
|
|
13
|
+
export { cloudEventsHttpSource, cloudEventsFromHttp, logFileSource, compareBusinessEvents, correlated } from './events/cloudevents.js';
|
|
14
|
+
export { DEFAULT_PRIVACY, mergePrivacy, privacyFindings, assertAllowedTarget } from './privacy.js';
|
|
15
|
+
export { toJUnit, toCtrf, toWebVtt, toMermaid } from './report/formats.js';
|
|
16
|
+
export { toMarkdown } from './report/markdown.js';
|
|
17
|
+
export { defineConfig, mergeConfigRuns, prepare, runConfig } from './config.js';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { SpecBundle } from './spec/types.js';
|
|
2
|
+
import { ChartGraph } from './graph.js';
|
|
3
|
+
export type LintFinding = {
|
|
4
|
+
rule: string;
|
|
5
|
+
message: string;
|
|
6
|
+
};
|
|
7
|
+
export type LintOptions = {
|
|
8
|
+
/** Meta fields every state must carry; `description` by default. */
|
|
9
|
+
requiredMeta?: readonly string[];
|
|
10
|
+
/** Only these states and events need implementations (a chart being brought up). */
|
|
11
|
+
scope?: {
|
|
12
|
+
states: ReadonlySet<string>;
|
|
13
|
+
events: ReadonlySet<string>;
|
|
14
|
+
};
|
|
15
|
+
implementations?: {
|
|
16
|
+
events: ReadonlySet<string>;
|
|
17
|
+
states: ReadonlySet<string>;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Checks a spec bundle is executable: pure (no guards, actions, context or delays), every state
|
|
22
|
+
* reachable, no dead ends without `meta.deadEnd`, every journey replays to its `endsIn` states, and
|
|
23
|
+
* (when implementations are given) every event and state in scope has one.
|
|
24
|
+
*/
|
|
25
|
+
export declare function lintBundle(bundle: SpecBundle, options?: LintOptions): {
|
|
26
|
+
findings: LintFinding[];
|
|
27
|
+
composition: import('./index.js').Composition;
|
|
28
|
+
graph: ChartGraph;
|
|
29
|
+
journeys: {
|
|
30
|
+
journey: import('./index.js').Journey;
|
|
31
|
+
replay: {
|
|
32
|
+
ok: false;
|
|
33
|
+
steps: (import('./graph.js').Step & {
|
|
34
|
+
from: import('./graph.js').Config;
|
|
35
|
+
to: import('./graph.js').Config;
|
|
36
|
+
})[];
|
|
37
|
+
config: import('./graph.js').Config;
|
|
38
|
+
failedAt: string;
|
|
39
|
+
} | {
|
|
40
|
+
ok: true;
|
|
41
|
+
steps: (import('./graph.js').Step & {
|
|
42
|
+
from: import('./graph.js').Config;
|
|
43
|
+
to: import('./graph.js').Config;
|
|
44
|
+
})[];
|
|
45
|
+
config: import('./graph.js').Config;
|
|
46
|
+
failedAt?: undefined;
|
|
47
|
+
};
|
|
48
|
+
}[];
|
|
49
|
+
unimplemented: {
|
|
50
|
+
events: string[];
|
|
51
|
+
states: string[];
|
|
52
|
+
};
|
|
53
|
+
};
|