@crvouga/atlas 1.0.0 → 1.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/reports/src/artifact-query.d.ts +123 -0
  3. package/dist/reports/src/artifact-query.js +234 -0
  4. package/dist/reports/src/evidence-detail.js +2 -1
  5. package/dist/reports/src/evidence-types.d.ts +2 -0
  6. package/dist/reports/src/test-catalog.d.ts +101 -5
  7. package/dist/reports/src/test-catalog.js +140 -5
  8. package/dist/schema/src/api.d.ts +225 -0
  9. package/dist/schema/src/api.js +41 -2
  10. package/dist/server/src/app.js +16 -5
  11. package/dist/server/src/openapi.js +41 -3
  12. package/docs/reference/http-api.md +84 -2
  13. package/docs/reference/reports.md +371 -7
  14. package/docs/reference/schema.md +32 -0
  15. package/docs/rich-evidence.md +31 -0
  16. package/docs/server.md +4 -1
  17. package/docs/ui.md +8 -1
  18. package/llms-full.txt +127 -4
  19. package/package.json +1 -1
  20. package/packages/schema/schemas/effective-delta.schema.json +14 -0
  21. package/packages/schema/schemas/effective-evidence.schema.json +14 -0
  22. package/packages/schema/schemas/evidence-page.schema.json +7 -0
  23. package/packages/schema/schemas/layer-rows.schema.json +7 -0
  24. package/packages/schema/schemas/report-run.schema.json +35 -0
  25. package/packages/schema/schemas/report-runs.schema.json +221 -0
  26. package/packages/schema/schemas/test-catalog.schema.json +7 -0
  27. package/packages/schema/schemas/test-history.schema.json +14 -0
  28. package/packages/server/openapi.json +2473 -1035
  29. package/packages/visualizer/src/evidence/check-detail.tsx +6 -1
  30. package/packages/visualizer/src/evidence/evidence-context.tsx +9 -2
  31. package/packages/visualizer/src/evidence/load-state.tsx +65 -0
  32. package/packages/visualizer/src/evidence/overview.tsx +4 -6
  33. package/packages/visualizer/src/evidence/recording-page.tsx +17 -7
  34. package/packages/visualizer/src/evidence/spec-header.tsx +8 -6
  35. package/packages/visualizer/src/evidence/spec-page.tsx +98 -15
  36. package/packages/visualizer/src/explorer/ArtifactsView.tsx +162 -0
  37. package/packages/visualizer/src/explorer/Explorer.tsx +28 -3
  38. package/packages/visualizer/src/explorer/RunsView.tsx +43 -19
  39. package/packages/visualizer/src/explorer/catalog.tsx +97 -12
  40. package/packages/visualizer/src/explorer/filters.tsx +279 -0
  41. package/packages/visualizer/src/explorer/search.ts +81 -6
  42. package/packages/visualizer/src/explorer/views.ts +75 -0
  43. package/packages/visualizer/src/find/Finder.tsx +45 -7
  44. package/packages/visualizer/src/spec-kind.test.ts +14 -1
  45. package/packages/visualizer/src/spec-kind.ts +28 -2
package/llms-full.txt CHANGED
@@ -1049,6 +1049,37 @@ attachments with that tag, and says how many match. Tags describe evidence; they
1049
1049
  - **Older layers.** A layer without attachment tags reads exactly as before. Tags on an attachment that cannot be read
1050
1050
  (not a list of strings) are dropped, and the attachment, check and layer stay.
1051
1051
 
1052
+ ## Finding runs and artifacts
1053
+
1054
+ The viewer's **Runs** and **Artifacts** tabs and the API answer one query, so a link means the same thing everywhere.
1055
+ "Demo videos for checkout on iPhone, including failed attempts" is:
1056
+
1057
+ ```sh
1058
+ curl "$ATLAS_SERVER_URL/api/reports/artifacts?artifactTag=demo&type=video&domain=checkout&label=device%3DiPhone"
1059
+ ```
1060
+
1061
+ - **Dimensions.** `artifactTag`, `type` (the media type as a role: `video`, `image`, `audio`, `snapshot`, `text`,
1062
+ `file`; `video` means a playable recording), `label` (`key=value`, or `key`), `domain` and `spec` (artifacts only),
1063
+ `environment` (the device or client), `producer`, `branch`, `sha` (seven or more characters), `outcome` (`passed`,
1064
+ `failed`, `running`, `not-run`), `since` and `until` (epoch milliseconds or an ISO date), and `q` (words).
1065
+ - **Semantics.** Filters combine with AND across dimensions and OR within one (`environment=ios,android`). With both
1066
+ `artifactTag` and `type`, one attachment must be both where the report says which video carries which tag: a tagged
1067
+ screenshot beside an untagged video is not a tagged video. `inherited=1` also counts the tags an attachment inherits
1068
+ from its check and run. A comma or backslash inside a value is written `\,` or `\\`; the viewer encodes `#` and spaces.
1069
+ - **History.** Artifacts are recorded results, not only the report's current winners: a recording tagged `demo` is
1070
+ found with its original run, commit and status even when a later attempt of the test is untagged. Tags a reviewer
1071
+ added after upload are kept apart from the layer and are not searched here.
1072
+ - **Facets.** Each answer carries `facets`: for every dimension the values on offer. The count beside a value is what
1073
+ the list would hold if that value alone were chosen in its dimension with every other filter applied, so the
1074
+ chosen value's count is the list's and the others show what adding them would give.
1075
+ - **Older servers.** A response names the filters it applied in `filters`. A viewer that asked for one that is missing
1076
+ filters what a run summary can answer itself and says plainly that the server cannot filter by the rest (tags, types,
1077
+ labels); it never presents an unfiltered list as narrowed. A server without `/api/reports/artifacts` is reported as
1078
+ such on the Artifacts tab.
1079
+ - **Views.** *Views* saves the current filters under a name in this browser, per project and tab. A saved view is a
1080
+ **live query**: opening it asks again and shows what matches the newest report. It is not a snapshot; an immutable
1081
+ review collection is a separate feature. *Copy link* gives the address, which holds the whole query.
1082
+
1052
1083
  ## Labels describe, parameters split
1053
1084
 
1054
1085
  A result's **slot** is its producer, check id, part kind, spec, environment and **parameters**. The newest completed
@@ -1620,7 +1651,8 @@ with `format=markdown` (or `Accept: text/markdown`), and takes the project prefi
1620
1651
  | Only some: `q` (all words), `status` (or `flaky`), `environment`, `producer`, `domain`, `spec`, `tag`, `run`; `sort`, `offset`, `limit` | `GET /api/reports/tests?status=failed&environment=ios` |
1621
1652
  | One test: every recorded result (status, duration, environment, branch, commit, CI run), newest first | `GET /api/reports/tests/history?key=<key>` |
1622
1653
  | Why Specs, domains and counts disagree: ambiguous spec paths, shared domains, gaps, a reconciliation of the totals | `GET /api/reports/tests/health` |
1623
- | The runs that recorded the report (by CI run URL, else branch and commit); `?video=true` keeps those with a playable video | `GET /api/reports/runs` |
1654
+ | The runs that recorded the report (by CI run URL, else branch and commit); `?video=true` keeps those with a playable video; `artifactTag`, `type`, `label`, `environment`, `branch`, `outcome`, `since`, `until` narrow it ([filtering](rich-evidence.md#finding-runs-and-artifacts)) | `GET /api/reports/runs` |
1655
+ | Recorded results that carry evidence, across the whole history, found by tag, media type, label, feature, environment, branch, revision, outcome and time | `GET /api/reports/artifacts?artifactTag=demo&type=video` |
1624
1656
  | Every test one run recorded | `GET /api/reports/runs/detail?key=<run key>` |
1625
1657
 
1626
1658
  ```sh
@@ -1703,6 +1735,8 @@ curl "$ATLAS_SERVER_URL/api/projects/$ATLAS_PROJECT/reports/tests?format=markdow
1703
1735
  | `POST /api/projects/{project}/reports/artifact-tags` | publish | Tag or untag one attachment after upload. |
1704
1736
  | `GET /api/reports/runs` | read | The runs that recorded the report. |
1705
1737
  | `GET /api/projects/{project}/reports/runs` | read | The runs that recorded the report. |
1738
+ | `GET /api/reports/artifacts` | read | Recorded results that carry evidence, across the whole history. |
1739
+ | `GET /api/projects/{project}/reports/artifacts` | read | Recorded results that carry evidence, across the whole history. |
1706
1740
  | `GET /api/reports/runs/detail` | read | Every test one run recorded. |
1707
1741
  | `GET /api/projects/{project}/reports/runs/detail` | read | Every test one run recorded. |
1708
1742
  | `GET /api/reports/outline` | read | The specs a report is laid over. |
@@ -3768,6 +3802,13 @@ they preserve evidence semantics, provenance, URL selection, or playback behavio
3768
3802
  `Bounded`/show-more controls. Do not fetch unopened results' recordings eagerly.
3769
3803
  - Loading: named `Loader`/`Skeleton` or explicit text with `role="status"`. Error: `Alert color="red"` and
3770
3804
  a retry when possible. Empty: descriptive `Text` and a relevant action. Use built-in loading/disabled states.
3805
+ - Waiting is bounded. A focused page (a spec, a recording) loads what its link names on its own and never waits for
3806
+ the whole catalog. `loadingPolicy.stallMs` in `evidence/load-state.tsx` is how long a read may take before the page
3807
+ names what is affected, keeps the rest usable and offers `Try again` and a way back that keeps the selected scope.
3808
+ A missing spec or layer is an explicit unavailable state with its path, never an endless `Loading…`. Layers that
3809
+ fail to read are counted (`EvidenceIncomplete`) and the rest stays usable. Search disclosed as incomplete (still
3810
+ reading, or specs it could not read) never reports "no match" as final. `tests/resilient-navigation.test.tsx`
3811
+ holds the request budgets for a large catalog.
3771
3812
  - Spec overview links use a centered `Group`: status, flexible title/folder, then outcome and time. Keep gaps
3772
3813
  explicit with theme spacing; stack metadata on narrow screens instead of crowding the title.
3773
3814
 
@@ -3845,7 +3886,7 @@ The narrowly scoped exceptions are:
3845
3886
  | Area | Screens/interactions | Mantine composition |
3846
3887
  | --- | --- | --- |
3847
3888
  | Shared shell | Project switching, spec navigation, run selection, connection status, diagnostics, mobile index | AppShell, Burger, NavLink, Menu, Popover, NativeSelect, Drawer |
3848
- | Project home | Tests/runs tabs, metrics, search, status/environment/domain filters, grouping, sorting, show more | Container, Tabs, SimpleGrid, Paper, TextInput, Button, Accordion |
3889
+ | Project home | Tests/runs/artifacts tabs, metrics, search, status/environment/domain/artifact-tag filters, run and artifact facets with saved views, grouping, sorting, show more | Container, Tabs, SimpleGrid, Paper, TextInput, MultiSelect, Popover, Button, Accordion |
3849
3890
  | Test detail | Current outcomes, statistics, duration graph, history, artifacts, recording; the `layer` address parameter pins it to one run's result, labelled "This run" against "Latest combined evidence" | Drawer, Table, Badge, Alert, Stage |
3850
3891
  | Specs | All six existing kinds, overview/index, Gherkin rules/scenarios/examples, Quint declarations/traces, DMN tables, source text | SpecHeader, Accordion, Table, CodeHighlightTabs, ResultRow |
3851
3892
  | Statecharts | Graph, screen/event/journey details, developer metadata, chart test results | Mantine cards/navigation and product compositions; graph exception above |
@@ -5029,10 +5070,22 @@ Responses: `201` The recorded entry.; `401` No token, or an unknown one. Send `A
5029
5070
 
5030
5071
  `GET /api/reports/runs` · role: read
5031
5072
 
5032
- Every run, newest first: layers grouped by their CI run URL (else branch and commit), with their environments, producers, how many tests they recorded, their results by status, the time they spanned, up to twenty failures and their video counts (references, distinct playable recordings, unavailable). Send `format=markdown` for Markdown.
5073
+ Every run, newest first: layers grouped by their CI run URL (else branch and commit), with their environments, producers, how many tests they recorded, their results by status, the time they spanned, up to twenty failures, their video counts (references, distinct playable recordings, unavailable) and the artifact tags, media types and labels their results carry. Filters narrow the list before `limit`: AND across the parameters, OR within one; `filters` in the answer names those that were applied and `facets` offers each dimension's values with counts. A server that does not know a filter ignores it and does not name it in `filters`. Send `format=markdown` for Markdown.
5033
5074
 
5034
5075
  - `limit` (query): At most this many runs (default 100).
5035
5076
  - `video` (query): `true` to list only runs that have a playable video recording. Applied to every run before `limit`; `total` counts the matches. A server that does not know it answers with every run.
5077
+ - `artifactTag` (query): Artifact tags (`demo` and `#demo` are the same), repeatable or comma-separated. A comma or backslash inside a value is written `\,` or `\\`. OR within the parameter, AND with the other filters.
5078
+ - `inherited` (query): `1` with `artifactTag` to also match the tags attachments inherit from their check and run. Default: the exact artifact query.
5079
+ - `type` (query): Media types as roles (`video`, `image`, `audio`, `snapshot`, `text`, `file`, or a producer's own). `video` means a playable recording. With `artifactTag`, one artifact must be both where the report says which videos carry which tags.
5080
+ - `label` (query): `key=value`, or `key` for any value.
5081
+ - `environment` (query): Environments or devices (`ios`, `desktop-web`).
5082
+ - `producer` (query): Producers.
5083
+ - `branch` (query): Branches.
5084
+ - `sha` (query): Revisions: a full commit id or a prefix of at least seven characters.
5085
+ - `outcome` (query): Statuses: `passed`, `failed`, `running`, `not-run`. A run's outcome is `failed` when any result failed, else `running`, else `passed`, else `not-run`.
5086
+ - `q` (query): Words that must all appear in the title, id, spec, branch, producer, environment, tags or labels.
5087
+ - `since` (query): Only records at or after this time: epoch milliseconds or an ISO date (a date alone is UTC). A result's recording time; a run's end.
5088
+ - `until` (query): Only records at or before this time (same forms as `since`).
5036
5089
  - `format` (query): `markdown` for Markdown instead of JSON.
5037
5090
  - `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
5038
5091
 
@@ -5042,17 +5095,87 @@ Responses: `200` The runs.; `304` Unchanged since the `If-None-Match` ETag.; `40
5042
5095
 
5043
5096
  `GET /api/projects/{project}/reports/runs` · role: read
5044
5097
 
5045
- Every run, newest first: layers grouped by their CI run URL (else branch and commit), with their environments, producers, how many tests they recorded, their results by status, the time they spanned, up to twenty failures and their video counts (references, distinct playable recordings, unavailable). Send `format=markdown` for Markdown.
5098
+ Every run, newest first: layers grouped by their CI run URL (else branch and commit), with their environments, producers, how many tests they recorded, their results by status, the time they spanned, up to twenty failures, their video counts (references, distinct playable recordings, unavailable) and the artifact tags, media types and labels their results carry. Filters narrow the list before `limit`: AND across the parameters, OR within one; `filters` in the answer names those that were applied and `facets` offers each dimension's values with counts. A server that does not know a filter ignores it and does not name it in `filters`. Send `format=markdown` for Markdown.
5046
5099
 
5047
5100
  Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
5048
5101
 
5049
5102
  - `project` (path, required): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
5050
5103
  - `limit` (query): At most this many runs (default 100).
5051
5104
  - `video` (query): `true` to list only runs that have a playable video recording. Applied to every run before `limit`; `total` counts the matches. A server that does not know it answers with every run.
5105
+ - `artifactTag` (query): Artifact tags (`demo` and `#demo` are the same), repeatable or comma-separated. A comma or backslash inside a value is written `\,` or `\\`. OR within the parameter, AND with the other filters.
5106
+ - `inherited` (query): `1` with `artifactTag` to also match the tags attachments inherit from their check and run. Default: the exact artifact query.
5107
+ - `type` (query): Media types as roles (`video`, `image`, `audio`, `snapshot`, `text`, `file`, or a producer's own). `video` means a playable recording. With `artifactTag`, one artifact must be both where the report says which videos carry which tags.
5108
+ - `label` (query): `key=value`, or `key` for any value.
5109
+ - `environment` (query): Environments or devices (`ios`, `desktop-web`).
5110
+ - `producer` (query): Producers.
5111
+ - `branch` (query): Branches.
5112
+ - `sha` (query): Revisions: a full commit id or a prefix of at least seven characters.
5113
+ - `outcome` (query): Statuses: `passed`, `failed`, `running`, `not-run`. A run's outcome is `failed` when any result failed, else `running`, else `passed`, else `not-run`.
5114
+ - `q` (query): Words that must all appear in the title, id, spec, branch, producer, environment, tags or labels.
5115
+ - `since` (query): Only records at or after this time: epoch milliseconds or an ISO date (a date alone is UTC). A result's recording time; a run's end.
5116
+ - `until` (query): Only records at or before this time (same forms as `since`).
5052
5117
  - `format` (query): `markdown` for Markdown instead of JSON.
5053
5118
 
5054
5119
  Responses: `200` The runs.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
5055
5120
 
5121
+ ### Recorded results that carry evidence, across the whole history
5122
+
5123
+ `GET /api/reports/artifacts` · role: read
5124
+
5125
+ Every recorded result that has attachments (recordings, screenshots, traces), newest first, found in the history and not only among the current winners: a recording tagged `demo` is found with its original run, revision and status even when a later attempt is untagged. Narrow it by artifact tag, media type, label, feature (`domain`, `spec`), environment or device, producer, branch, revision, outcome and time: AND across the parameters, OR within one; with both `artifactTag` and `type`, one artifact must be both. `filters` names the filters that were applied and `facets` offers each dimension's values with counts: the count beside a value is what the list would hold if that value alone were chosen in its dimension, every other filter applied. Tags written by reviewers after upload are not searched; only those in the layer are. Send `format=markdown` for Markdown.
5126
+
5127
+ - `limit` (query): At most this many results (default 100).
5128
+ - `offset` (query): Skip this many matches (default 0).
5129
+ - `video` (query): `true` for results with a playable video recording (the same as `type=video`).
5130
+ - `domain` (query): The feature domain of the result's spec.
5131
+ - `spec` (query): Spec paths.
5132
+ - `artifactTag` (query): Artifact tags (`demo` and `#demo` are the same), repeatable or comma-separated. A comma or backslash inside a value is written `\,` or `\\`. OR within the parameter, AND with the other filters.
5133
+ - `inherited` (query): `1` with `artifactTag` to also match the tags attachments inherit from their check and run. Default: the exact artifact query.
5134
+ - `type` (query): Media types as roles (`video`, `image`, `audio`, `snapshot`, `text`, `file`, or a producer's own). `video` means a playable recording. With `artifactTag`, one artifact must be both where the report says which videos carry which tags.
5135
+ - `label` (query): `key=value`, or `key` for any value.
5136
+ - `environment` (query): Environments or devices (`ios`, `desktop-web`).
5137
+ - `producer` (query): Producers.
5138
+ - `branch` (query): Branches.
5139
+ - `sha` (query): Revisions: a full commit id or a prefix of at least seven characters.
5140
+ - `outcome` (query): Statuses: `passed`, `failed`, `running`, `not-run`. A run's outcome is `failed` when any result failed, else `running`, else `passed`, else `not-run`.
5141
+ - `q` (query): Words that must all appear in the title, id, spec, branch, producer, environment, tags or labels.
5142
+ - `since` (query): Only records at or after this time: epoch milliseconds or an ISO date (a date alone is UTC). A result's recording time; a run's end.
5143
+ - `until` (query): Only records at or before this time (same forms as `since`).
5144
+ - `format` (query): `markdown` for Markdown instead of JSON.
5145
+ - `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
5146
+
5147
+ Responses: `200` The matching results and the facets.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
5148
+
5149
+ ### Recorded results that carry evidence, across the whole history
5150
+
5151
+ `GET /api/projects/{project}/reports/artifacts` · role: read
5152
+
5153
+ Every recorded result that has attachments (recordings, screenshots, traces), newest first, found in the history and not only among the current winners: a recording tagged `demo` is found with its original run, revision and status even when a later attempt is untagged. Narrow it by artifact tag, media type, label, feature (`domain`, `spec`), environment or device, producer, branch, revision, outcome and time: AND across the parameters, OR within one; with both `artifactTag` and `type`, one artifact must be both. `filters` names the filters that were applied and `facets` offers each dimension's values with counts: the count beside a value is what the list would hold if that value alone were chosen in its dimension, every other filter applied. Tags written by reviewers after upload are not searched; only those in the layer are. Send `format=markdown` for Markdown.
5154
+
5155
+ Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
5156
+
5157
+ - `project` (path, required): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
5158
+ - `limit` (query): At most this many results (default 100).
5159
+ - `offset` (query): Skip this many matches (default 0).
5160
+ - `video` (query): `true` for results with a playable video recording (the same as `type=video`).
5161
+ - `domain` (query): The feature domain of the result's spec.
5162
+ - `spec` (query): Spec paths.
5163
+ - `artifactTag` (query): Artifact tags (`demo` and `#demo` are the same), repeatable or comma-separated. A comma or backslash inside a value is written `\,` or `\\`. OR within the parameter, AND with the other filters.
5164
+ - `inherited` (query): `1` with `artifactTag` to also match the tags attachments inherit from their check and run. Default: the exact artifact query.
5165
+ - `type` (query): Media types as roles (`video`, `image`, `audio`, `snapshot`, `text`, `file`, or a producer's own). `video` means a playable recording. With `artifactTag`, one artifact must be both where the report says which videos carry which tags.
5166
+ - `label` (query): `key=value`, or `key` for any value.
5167
+ - `environment` (query): Environments or devices (`ios`, `desktop-web`).
5168
+ - `producer` (query): Producers.
5169
+ - `branch` (query): Branches.
5170
+ - `sha` (query): Revisions: a full commit id or a prefix of at least seven characters.
5171
+ - `outcome` (query): Statuses: `passed`, `failed`, `running`, `not-run`. A run's outcome is `failed` when any result failed, else `running`, else `passed`, else `not-run`.
5172
+ - `q` (query): Words that must all appear in the title, id, spec, branch, producer, environment, tags or labels.
5173
+ - `since` (query): Only records at or after this time: epoch milliseconds or an ISO date (a date alone is UTC). A result's recording time; a run's end.
5174
+ - `until` (query): Only records at or before this time (same forms as `since`).
5175
+ - `format` (query): `markdown` for Markdown instead of JSON.
5176
+
5177
+ Responses: `200` The matching results and the facets.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
5178
+
5056
5179
  ### Every test one run recorded
5057
5180
 
5058
5181
  `GET /api/reports/runs/detail` · role: read
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crvouga/atlas",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Atlas: specs of any kind, reported as layered evidence. Publish checks from any runner (JUnit, CTRF, a script), combine them across nodes, branches, environments and backends, gate CI on the result, and run statecharts against the real app.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -178,6 +178,13 @@
178
178
  "description": "The name of the step that holds it",
179
179
  "type": "string"
180
180
  },
181
+ "tags": {
182
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
183
+ "type": "array",
184
+ "items": {
185
+ "type": "string"
186
+ }
187
+ },
181
188
  "recording": {
182
189
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
183
190
  "type": "string"
@@ -468,6 +475,13 @@
468
475
  "description": "The name of the step that holds it",
469
476
  "type": "string"
470
477
  },
478
+ "tags": {
479
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
480
+ "type": "array",
481
+ "items": {
482
+ "type": "string"
483
+ }
484
+ },
471
485
  "recording": {
472
486
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
473
487
  "type": "string"
@@ -178,6 +178,13 @@
178
178
  "description": "The name of the step that holds it",
179
179
  "type": "string"
180
180
  },
181
+ "tags": {
182
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
183
+ "type": "array",
184
+ "items": {
185
+ "type": "string"
186
+ }
187
+ },
181
188
  "recording": {
182
189
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
183
190
  "type": "string"
@@ -468,6 +475,13 @@
468
475
  "description": "The name of the step that holds it",
469
476
  "type": "string"
470
477
  },
478
+ "tags": {
479
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
480
+ "type": "array",
481
+ "items": {
482
+ "type": "string"
483
+ }
484
+ },
471
485
  "recording": {
472
486
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
473
487
  "type": "string"
@@ -223,6 +223,13 @@
223
223
  "description": "The name of the step that holds it",
224
224
  "type": "string"
225
225
  },
226
+ "tags": {
227
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
228
+ "type": "array",
229
+ "items": {
230
+ "type": "string"
231
+ }
232
+ },
226
233
  "recording": {
227
234
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
228
235
  "type": "string"
@@ -169,6 +169,13 @@
169
169
  "description": "The name of the step that holds it",
170
170
  "type": "string"
171
171
  },
172
+ "tags": {
173
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
174
+ "type": "array",
175
+ "items": {
176
+ "type": "string"
177
+ }
178
+ },
172
179
  "recording": {
173
180
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
174
181
  "type": "string"
@@ -170,6 +170,34 @@
170
170
  "unavailable"
171
171
  ],
172
172
  "additionalProperties": {}
173
+ },
174
+ "artifactTags": {
175
+ "description": "The normalized tags of the attachments of its results, sorted and distinct. Absent when none is tagged, and in reports of older servers",
176
+ "type": "array",
177
+ "items": {
178
+ "type": "string"
179
+ }
180
+ },
181
+ "tags": {
182
+ "description": "The tags of its checks and layers, which its attachments inherit (what `inherited=1` also matches). Absent when none",
183
+ "type": "array",
184
+ "items": {
185
+ "type": "string"
186
+ }
187
+ },
188
+ "types": {
189
+ "description": "The media types (roles) of its attachments, sorted and distinct; `video` only for a playable recording. Absent when it has no attachment",
190
+ "type": "array",
191
+ "items": {
192
+ "type": "string"
193
+ }
194
+ },
195
+ "labels": {
196
+ "description": "The `key=value` labels of its results and layers, sorted and distinct. Absent when it has none",
197
+ "type": "array",
198
+ "items": {
199
+ "type": "string"
200
+ }
173
201
  }
174
202
  },
175
203
  "required": [
@@ -267,6 +295,13 @@
267
295
  "description": "The name of the step that holds it",
268
296
  "type": "string"
269
297
  },
298
+ "tags": {
299
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
300
+ "type": "array",
301
+ "items": {
302
+ "type": "string"
303
+ }
304
+ },
270
305
  "recording": {
271
306
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
272
307
  "type": "string"
@@ -178,6 +178,34 @@
178
178
  "unavailable"
179
179
  ],
180
180
  "additionalProperties": {}
181
+ },
182
+ "artifactTags": {
183
+ "description": "The normalized tags of the attachments of its results, sorted and distinct. Absent when none is tagged, and in reports of older servers",
184
+ "type": "array",
185
+ "items": {
186
+ "type": "string"
187
+ }
188
+ },
189
+ "tags": {
190
+ "description": "The tags of its checks and layers, which its attachments inherit (what `inherited=1` also matches). Absent when none",
191
+ "type": "array",
192
+ "items": {
193
+ "type": "string"
194
+ }
195
+ },
196
+ "types": {
197
+ "description": "The media types (roles) of its attachments, sorted and distinct; `video` only for a playable recording. Absent when it has no attachment",
198
+ "type": "array",
199
+ "items": {
200
+ "type": "string"
201
+ }
202
+ },
203
+ "labels": {
204
+ "description": "The `key=value` labels of its results and layers, sorted and distinct. Absent when it has none",
205
+ "type": "array",
206
+ "items": {
207
+ "type": "string"
208
+ }
181
209
  }
182
210
  },
183
211
  "required": [
@@ -204,6 +232,199 @@
204
232
  "type": "integer",
205
233
  "minimum": 0,
206
234
  "maximum": 9007199254740991
235
+ },
236
+ "filters": {
237
+ "description": "The filter parameters this server applied (`artifactTag`, `type`, `outcome`…). A viewer that asked for one that is missing here knows the server ignored it. Absent on servers that predate filtering",
238
+ "type": "array",
239
+ "items": {
240
+ "type": "string"
241
+ }
242
+ },
243
+ "facets": {
244
+ "description": "The values each filter dimension offers, counted over every run. Absent on servers that predate filtering",
245
+ "type": "object",
246
+ "properties": {
247
+ "artifactTags": {
248
+ "type": "array",
249
+ "items": {
250
+ "type": "object",
251
+ "properties": {
252
+ "value": {
253
+ "type": "string"
254
+ },
255
+ "count": {
256
+ "type": "integer",
257
+ "minimum": 0,
258
+ "maximum": 9007199254740991
259
+ }
260
+ },
261
+ "required": [
262
+ "value",
263
+ "count"
264
+ ],
265
+ "additionalProperties": {}
266
+ }
267
+ },
268
+ "types": {
269
+ "type": "array",
270
+ "items": {
271
+ "type": "object",
272
+ "properties": {
273
+ "value": {
274
+ "type": "string"
275
+ },
276
+ "count": {
277
+ "type": "integer",
278
+ "minimum": 0,
279
+ "maximum": 9007199254740991
280
+ }
281
+ },
282
+ "required": [
283
+ "value",
284
+ "count"
285
+ ],
286
+ "additionalProperties": {}
287
+ }
288
+ },
289
+ "labels": {
290
+ "type": "array",
291
+ "items": {
292
+ "type": "object",
293
+ "properties": {
294
+ "value": {
295
+ "type": "string"
296
+ },
297
+ "count": {
298
+ "type": "integer",
299
+ "minimum": 0,
300
+ "maximum": 9007199254740991
301
+ }
302
+ },
303
+ "required": [
304
+ "value",
305
+ "count"
306
+ ],
307
+ "additionalProperties": {}
308
+ },
309
+ "description": "Values are `key=value`"
310
+ },
311
+ "environments": {
312
+ "type": "array",
313
+ "items": {
314
+ "type": "object",
315
+ "properties": {
316
+ "value": {
317
+ "type": "string"
318
+ },
319
+ "count": {
320
+ "type": "integer",
321
+ "minimum": 0,
322
+ "maximum": 9007199254740991
323
+ }
324
+ },
325
+ "required": [
326
+ "value",
327
+ "count"
328
+ ],
329
+ "additionalProperties": {}
330
+ }
331
+ },
332
+ "producers": {
333
+ "type": "array",
334
+ "items": {
335
+ "type": "object",
336
+ "properties": {
337
+ "value": {
338
+ "type": "string"
339
+ },
340
+ "count": {
341
+ "type": "integer",
342
+ "minimum": 0,
343
+ "maximum": 9007199254740991
344
+ }
345
+ },
346
+ "required": [
347
+ "value",
348
+ "count"
349
+ ],
350
+ "additionalProperties": {}
351
+ }
352
+ },
353
+ "branches": {
354
+ "type": "array",
355
+ "items": {
356
+ "type": "object",
357
+ "properties": {
358
+ "value": {
359
+ "type": "string"
360
+ },
361
+ "count": {
362
+ "type": "integer",
363
+ "minimum": 0,
364
+ "maximum": 9007199254740991
365
+ }
366
+ },
367
+ "required": [
368
+ "value",
369
+ "count"
370
+ ],
371
+ "additionalProperties": {}
372
+ }
373
+ },
374
+ "outcomes": {
375
+ "type": "array",
376
+ "items": {
377
+ "type": "object",
378
+ "properties": {
379
+ "value": {
380
+ "type": "string"
381
+ },
382
+ "count": {
383
+ "type": "integer",
384
+ "minimum": 0,
385
+ "maximum": 9007199254740991
386
+ }
387
+ },
388
+ "required": [
389
+ "value",
390
+ "count"
391
+ ],
392
+ "additionalProperties": {}
393
+ }
394
+ },
395
+ "domains": {
396
+ "description": "Only for artifacts: runs have no domain",
397
+ "type": "array",
398
+ "items": {
399
+ "type": "object",
400
+ "properties": {
401
+ "value": {
402
+ "type": "string"
403
+ },
404
+ "count": {
405
+ "type": "integer",
406
+ "minimum": 0,
407
+ "maximum": 9007199254740991
408
+ }
409
+ },
410
+ "required": [
411
+ "value",
412
+ "count"
413
+ ],
414
+ "additionalProperties": {}
415
+ }
416
+ }
417
+ },
418
+ "required": [
419
+ "artifactTags",
420
+ "types",
421
+ "labels",
422
+ "environments",
423
+ "producers",
424
+ "branches",
425
+ "outcomes"
426
+ ],
427
+ "additionalProperties": {}
207
428
  }
208
429
  },
209
430
  "required": [
@@ -923,6 +923,13 @@
923
923
  "description": "The name of the step that holds it",
924
924
  "type": "string"
925
925
  },
926
+ "tags": {
927
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
928
+ "type": "array",
929
+ "items": {
930
+ "type": "string"
931
+ }
932
+ },
926
933
  "recording": {
927
934
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
928
935
  "type": "string"
@@ -243,6 +243,13 @@
243
243
  "description": "The name of the step that holds it",
244
244
  "type": "string"
245
245
  },
246
+ "tags": {
247
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
248
+ "type": "array",
249
+ "items": {
250
+ "type": "string"
251
+ }
252
+ },
246
253
  "recording": {
247
254
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
248
255
  "type": "string"
@@ -681,6 +688,13 @@
681
688
  "description": "The name of the step that holds it",
682
689
  "type": "string"
683
690
  },
691
+ "tags": {
692
+ "description": "The normalized tags of this attachment itself. Absent when it has none (and in documents of older servers)",
693
+ "type": "array",
694
+ "items": {
695
+ "type": "string"
696
+ }
697
+ },
684
698
  "recording": {
685
699
  "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
686
700
  "type": "string"