@crvouga/atlas 0.15.0 → 0.16.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 (30) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/reports/src/evidence-detail.d.ts +19 -2
  3. package/dist/reports/src/evidence-detail.js +63 -14
  4. package/dist/reports/src/evidence-types.d.ts +31 -0
  5. package/dist/reports/src/layer-merge.js +2 -2
  6. package/dist/reports/src/test-catalog.d.ts +24 -3
  7. package/dist/reports/src/test-catalog.js +37 -11
  8. package/dist/schema/src/api.d.ts +167 -0
  9. package/dist/schema/src/api.js +28 -4
  10. package/dist/server/src/app.js +3 -2
  11. package/dist/server/src/llms.js +2 -1
  12. package/dist/server/src/openapi.js +2 -1
  13. package/docs/reference/http-api.md +4 -2
  14. package/docs/reference/reports.md +110 -3
  15. package/docs/reference/schema.md +16 -0
  16. package/docs/server.md +1 -1
  17. package/llms-full.txt +5 -3
  18. package/package.json +1 -1
  19. package/packages/schema/schemas/effective-delta.schema.json +82 -0
  20. package/packages/schema/schemas/effective-evidence.schema.json +82 -0
  21. package/packages/schema/schemas/evidence-page.schema.json +41 -0
  22. package/packages/schema/schemas/layer-rows.schema.json +41 -0
  23. package/packages/schema/schemas/report-run.schema.json +71 -0
  24. package/packages/schema/schemas/report-runs.schema.json +38 -1
  25. package/packages/schema/schemas/test-catalog.schema.json +41 -0
  26. package/packages/schema/schemas/test-history.schema.json +82 -0
  27. package/packages/server/openapi.json +498 -3
  28. package/packages/visualizer/src/explorer/RunsView.tsx +128 -10
  29. package/packages/visualizer/src/explorer/catalog.tsx +16 -6
  30. package/packages/visualizer/src/explorer/search.ts +4 -1
package/llms-full.txt CHANGED
@@ -1492,7 +1492,7 @@ with `format=markdown` (or `Accept: text/markdown`), and takes the project prefi
1492
1492
  | 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` |
1493
1493
  | One test: every recorded result (status, duration, environment, branch, commit, CI run), newest first | `GET /api/reports/tests/history?key=<key>` |
1494
1494
  | Why Specs, domains and counts disagree: ambiguous spec paths, shared domains, gaps, a reconciliation of the totals | `GET /api/reports/tests/health` |
1495
- | The runs that recorded the report (by CI run URL, else branch and commit) | `GET /api/reports/runs` |
1495
+ | 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` |
1496
1496
  | Every test one run recorded | `GET /api/reports/runs/detail?key=<run key>` |
1497
1497
 
1498
1498
  ```sh
@@ -4998,9 +4998,10 @@ Responses: `201` The recorded entry.; `401` No token, or an unknown one. Send `A
4998
4998
 
4999
4999
  `GET /api/reports/runs` · role: read
5000
5000
 
5001
- 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 and up to twenty failures. Send `format=markdown` for Markdown.
5001
+ 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.
5002
5002
 
5003
5003
  - `limit` (query): At most this many runs (default 100).
5004
+ - `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.
5004
5005
  - `format` (query): `markdown` for Markdown instead of JSON.
5005
5006
  - `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
5006
5007
 
@@ -5010,12 +5011,13 @@ Responses: `200` The runs.; `304` Unchanged since the `If-None-Match` ETag.; `40
5010
5011
 
5011
5012
  `GET /api/projects/{project}/reports/runs` · role: read
5012
5013
 
5013
- 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 and up to twenty failures. Send `format=markdown` for Markdown.
5014
+ 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.
5014
5015
 
5015
5016
  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.
5016
5017
 
5017
5018
  - `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.
5018
5019
  - `limit` (query): At most this many runs (default 100).
5020
+ - `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.
5019
5021
  - `format` (query): `markdown` for Markdown instead of JSON.
5020
5022
 
5021
5023
  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`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crvouga/atlas",
3
- "version": "0.15.0",
3
+ "version": "0.16.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",
@@ -153,6 +153,47 @@
153
153
  "items": {
154
154
  "type": "string"
155
155
  }
156
+ },
157
+ "videos": {
158
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
159
+ "type": "array",
160
+ "items": {
161
+ "type": "object",
162
+ "properties": {
163
+ "name": {
164
+ "type": "string",
165
+ "description": "The attachment name"
166
+ },
167
+ "owner": {
168
+ "type": "string",
169
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
170
+ },
171
+ "attempt": {
172
+ "description": "The retry attempt that holds it, or that holds the step that does",
173
+ "type": "integer",
174
+ "minimum": 0,
175
+ "maximum": 9007199254740991
176
+ },
177
+ "step": {
178
+ "description": "The name of the step that holds it",
179
+ "type": "string"
180
+ },
181
+ "recording": {
182
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
183
+ "type": "string"
184
+ },
185
+ "available": {
186
+ "type": "boolean",
187
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
188
+ }
189
+ },
190
+ "required": [
191
+ "name",
192
+ "owner",
193
+ "available"
194
+ ],
195
+ "additionalProperties": {}
196
+ }
156
197
  }
157
198
  },
158
199
  "required": [
@@ -386,6 +427,47 @@
386
427
  "items": {
387
428
  "type": "string"
388
429
  }
430
+ },
431
+ "videos": {
432
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
433
+ "type": "array",
434
+ "items": {
435
+ "type": "object",
436
+ "properties": {
437
+ "name": {
438
+ "type": "string",
439
+ "description": "The attachment name"
440
+ },
441
+ "owner": {
442
+ "type": "string",
443
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
444
+ },
445
+ "attempt": {
446
+ "description": "The retry attempt that holds it, or that holds the step that does",
447
+ "type": "integer",
448
+ "minimum": 0,
449
+ "maximum": 9007199254740991
450
+ },
451
+ "step": {
452
+ "description": "The name of the step that holds it",
453
+ "type": "string"
454
+ },
455
+ "recording": {
456
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
457
+ "type": "string"
458
+ },
459
+ "available": {
460
+ "type": "boolean",
461
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
462
+ }
463
+ },
464
+ "required": [
465
+ "name",
466
+ "owner",
467
+ "available"
468
+ ],
469
+ "additionalProperties": {}
470
+ }
389
471
  }
390
472
  },
391
473
  "required": [
@@ -153,6 +153,47 @@
153
153
  "items": {
154
154
  "type": "string"
155
155
  }
156
+ },
157
+ "videos": {
158
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
159
+ "type": "array",
160
+ "items": {
161
+ "type": "object",
162
+ "properties": {
163
+ "name": {
164
+ "type": "string",
165
+ "description": "The attachment name"
166
+ },
167
+ "owner": {
168
+ "type": "string",
169
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
170
+ },
171
+ "attempt": {
172
+ "description": "The retry attempt that holds it, or that holds the step that does",
173
+ "type": "integer",
174
+ "minimum": 0,
175
+ "maximum": 9007199254740991
176
+ },
177
+ "step": {
178
+ "description": "The name of the step that holds it",
179
+ "type": "string"
180
+ },
181
+ "recording": {
182
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
183
+ "type": "string"
184
+ },
185
+ "available": {
186
+ "type": "boolean",
187
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
188
+ }
189
+ },
190
+ "required": [
191
+ "name",
192
+ "owner",
193
+ "available"
194
+ ],
195
+ "additionalProperties": {}
196
+ }
156
197
  }
157
198
  },
158
199
  "required": [
@@ -386,6 +427,47 @@
386
427
  "items": {
387
428
  "type": "string"
388
429
  }
430
+ },
431
+ "videos": {
432
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
433
+ "type": "array",
434
+ "items": {
435
+ "type": "object",
436
+ "properties": {
437
+ "name": {
438
+ "type": "string",
439
+ "description": "The attachment name"
440
+ },
441
+ "owner": {
442
+ "type": "string",
443
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
444
+ },
445
+ "attempt": {
446
+ "description": "The retry attempt that holds it, or that holds the step that does",
447
+ "type": "integer",
448
+ "minimum": 0,
449
+ "maximum": 9007199254740991
450
+ },
451
+ "step": {
452
+ "description": "The name of the step that holds it",
453
+ "type": "string"
454
+ },
455
+ "recording": {
456
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
457
+ "type": "string"
458
+ },
459
+ "available": {
460
+ "type": "boolean",
461
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
462
+ }
463
+ },
464
+ "required": [
465
+ "name",
466
+ "owner",
467
+ "available"
468
+ ],
469
+ "additionalProperties": {}
470
+ }
389
471
  }
390
472
  },
391
473
  "required": [
@@ -198,6 +198,47 @@
198
198
  "items": {
199
199
  "type": "string"
200
200
  }
201
+ },
202
+ "videos": {
203
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
204
+ "type": "array",
205
+ "items": {
206
+ "type": "object",
207
+ "properties": {
208
+ "name": {
209
+ "type": "string",
210
+ "description": "The attachment name"
211
+ },
212
+ "owner": {
213
+ "type": "string",
214
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
215
+ },
216
+ "attempt": {
217
+ "description": "The retry attempt that holds it, or that holds the step that does",
218
+ "type": "integer",
219
+ "minimum": 0,
220
+ "maximum": 9007199254740991
221
+ },
222
+ "step": {
223
+ "description": "The name of the step that holds it",
224
+ "type": "string"
225
+ },
226
+ "recording": {
227
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
228
+ "type": "string"
229
+ },
230
+ "available": {
231
+ "type": "boolean",
232
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
233
+ }
234
+ },
235
+ "required": [
236
+ "name",
237
+ "owner",
238
+ "available"
239
+ ],
240
+ "additionalProperties": {}
241
+ }
201
242
  }
202
243
  },
203
244
  "required": [
@@ -144,6 +144,47 @@
144
144
  "items": {
145
145
  "type": "string"
146
146
  }
147
+ },
148
+ "videos": {
149
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
150
+ "type": "array",
151
+ "items": {
152
+ "type": "object",
153
+ "properties": {
154
+ "name": {
155
+ "type": "string",
156
+ "description": "The attachment name"
157
+ },
158
+ "owner": {
159
+ "type": "string",
160
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
161
+ },
162
+ "attempt": {
163
+ "description": "The retry attempt that holds it, or that holds the step that does",
164
+ "type": "integer",
165
+ "minimum": 0,
166
+ "maximum": 9007199254740991
167
+ },
168
+ "step": {
169
+ "description": "The name of the step that holds it",
170
+ "type": "string"
171
+ },
172
+ "recording": {
173
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
174
+ "type": "string"
175
+ },
176
+ "available": {
177
+ "type": "boolean",
178
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
179
+ }
180
+ },
181
+ "required": [
182
+ "name",
183
+ "owner",
184
+ "available"
185
+ ],
186
+ "additionalProperties": {}
187
+ }
147
188
  }
148
189
  },
149
190
  "required": [
@@ -140,6 +140,36 @@
140
140
  ],
141
141
  "additionalProperties": {}
142
142
  }
143
+ },
144
+ "videos": {
145
+ "description": "Its videos, from its layers and the last result of each test. Absent when it has none or the report carries no video information",
146
+ "type": "object",
147
+ "properties": {
148
+ "references": {
149
+ "type": "integer",
150
+ "minimum": 0,
151
+ "maximum": 9007199254740991,
152
+ "description": "Every reference to a video; identical bytes referenced twice count twice"
153
+ },
154
+ "recordings": {
155
+ "type": "integer",
156
+ "minimum": 0,
157
+ "maximum": 9007199254740991,
158
+ "description": "Distinct playable recordings"
159
+ },
160
+ "unavailable": {
161
+ "type": "integer",
162
+ "minimum": 0,
163
+ "maximum": 9007199254740991,
164
+ "description": "References that name no bytes"
165
+ }
166
+ },
167
+ "required": [
168
+ "references",
169
+ "recordings",
170
+ "unavailable"
171
+ ],
172
+ "additionalProperties": {}
143
173
  }
144
174
  },
145
175
  "required": [
@@ -212,6 +242,47 @@
212
242
  },
213
243
  "detail": {
214
244
  "type": "string"
245
+ },
246
+ "videos": {
247
+ "description": "Every video its evidence references, with who holds it",
248
+ "type": "array",
249
+ "items": {
250
+ "type": "object",
251
+ "properties": {
252
+ "name": {
253
+ "type": "string",
254
+ "description": "The attachment name"
255
+ },
256
+ "owner": {
257
+ "type": "string",
258
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
259
+ },
260
+ "attempt": {
261
+ "description": "The retry attempt that holds it, or that holds the step that does",
262
+ "type": "integer",
263
+ "minimum": 0,
264
+ "maximum": 9007199254740991
265
+ },
266
+ "step": {
267
+ "description": "The name of the step that holds it",
268
+ "type": "string"
269
+ },
270
+ "recording": {
271
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
272
+ "type": "string"
273
+ },
274
+ "available": {
275
+ "type": "boolean",
276
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
277
+ }
278
+ },
279
+ "required": [
280
+ "name",
281
+ "owner",
282
+ "available"
283
+ ],
284
+ "additionalProperties": {}
285
+ }
215
286
  }
216
287
  },
217
288
  "required": [
@@ -13,7 +13,8 @@
13
13
  "total": {
14
14
  "type": "integer",
15
15
  "minimum": 0,
16
- "maximum": 9007199254740991
16
+ "maximum": 9007199254740991,
17
+ "description": "Runs that matched, before `limit`"
17
18
  },
18
19
  "runs": {
19
20
  "type": "array",
@@ -147,6 +148,36 @@
147
148
  ],
148
149
  "additionalProperties": {}
149
150
  }
151
+ },
152
+ "videos": {
153
+ "description": "Its videos, from its layers and the last result of each test. Absent when it has none or the report carries no video information",
154
+ "type": "object",
155
+ "properties": {
156
+ "references": {
157
+ "type": "integer",
158
+ "minimum": 0,
159
+ "maximum": 9007199254740991,
160
+ "description": "Every reference to a video; identical bytes referenced twice count twice"
161
+ },
162
+ "recordings": {
163
+ "type": "integer",
164
+ "minimum": 0,
165
+ "maximum": 9007199254740991,
166
+ "description": "Distinct playable recordings"
167
+ },
168
+ "unavailable": {
169
+ "type": "integer",
170
+ "minimum": 0,
171
+ "maximum": 9007199254740991,
172
+ "description": "References that name no bytes"
173
+ }
174
+ },
175
+ "required": [
176
+ "references",
177
+ "recordings",
178
+ "unavailable"
179
+ ],
180
+ "additionalProperties": {}
150
181
  }
151
182
  },
152
183
  "required": [
@@ -167,6 +198,12 @@
167
198
  ],
168
199
  "additionalProperties": {}
169
200
  }
201
+ },
202
+ "withVideo": {
203
+ "description": "How many of all runs (before `video` and `limit`) have a playable video recording",
204
+ "type": "integer",
205
+ "minimum": 0,
206
+ "maximum": 9007199254740991
170
207
  }
171
208
  },
172
209
  "required": [
@@ -898,6 +898,47 @@
898
898
  "items": {
899
899
  "type": "string"
900
900
  }
901
+ },
902
+ "videos": {
903
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
904
+ "type": "array",
905
+ "items": {
906
+ "type": "object",
907
+ "properties": {
908
+ "name": {
909
+ "type": "string",
910
+ "description": "The attachment name"
911
+ },
912
+ "owner": {
913
+ "type": "string",
914
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
915
+ },
916
+ "attempt": {
917
+ "description": "The retry attempt that holds it, or that holds the step that does",
918
+ "type": "integer",
919
+ "minimum": 0,
920
+ "maximum": 9007199254740991
921
+ },
922
+ "step": {
923
+ "description": "The name of the step that holds it",
924
+ "type": "string"
925
+ },
926
+ "recording": {
927
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
928
+ "type": "string"
929
+ },
930
+ "available": {
931
+ "type": "boolean",
932
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
933
+ }
934
+ },
935
+ "required": [
936
+ "name",
937
+ "owner",
938
+ "available"
939
+ ],
940
+ "additionalProperties": {}
941
+ }
901
942
  }
902
943
  },
903
944
  "required": [
@@ -218,6 +218,47 @@
218
218
  "items": {
219
219
  "type": "string"
220
220
  }
221
+ },
222
+ "videos": {
223
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
224
+ "type": "array",
225
+ "items": {
226
+ "type": "object",
227
+ "properties": {
228
+ "name": {
229
+ "type": "string",
230
+ "description": "The attachment name"
231
+ },
232
+ "owner": {
233
+ "type": "string",
234
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
235
+ },
236
+ "attempt": {
237
+ "description": "The retry attempt that holds it, or that holds the step that does",
238
+ "type": "integer",
239
+ "minimum": 0,
240
+ "maximum": 9007199254740991
241
+ },
242
+ "step": {
243
+ "description": "The name of the step that holds it",
244
+ "type": "string"
245
+ },
246
+ "recording": {
247
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
248
+ "type": "string"
249
+ },
250
+ "available": {
251
+ "type": "boolean",
252
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
253
+ }
254
+ },
255
+ "required": [
256
+ "name",
257
+ "owner",
258
+ "available"
259
+ ],
260
+ "additionalProperties": {}
261
+ }
221
262
  }
222
263
  },
223
264
  "required": [
@@ -615,6 +656,47 @@
615
656
  "items": {
616
657
  "type": "string"
617
658
  }
659
+ },
660
+ "videos": {
661
+ "description": "Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded",
662
+ "type": "array",
663
+ "items": {
664
+ "type": "object",
665
+ "properties": {
666
+ "name": {
667
+ "type": "string",
668
+ "description": "The attachment name"
669
+ },
670
+ "owner": {
671
+ "type": "string",
672
+ "description": "Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check"
673
+ },
674
+ "attempt": {
675
+ "description": "The retry attempt that holds it, or that holds the step that does",
676
+ "type": "integer",
677
+ "minimum": 0,
678
+ "maximum": 9007199254740991
679
+ },
680
+ "step": {
681
+ "description": "The name of the step that holds it",
682
+ "type": "string"
683
+ },
684
+ "recording": {
685
+ "description": "What identifies the bytes; references with the same value are one recording. Absent when it cannot be played",
686
+ "type": "string"
687
+ },
688
+ "available": {
689
+ "type": "boolean",
690
+ "description": "False when the reference names no bytes (no bundle key, address or inline text)"
691
+ }
692
+ },
693
+ "required": [
694
+ "name",
695
+ "owner",
696
+ "available"
697
+ ],
698
+ "additionalProperties": {}
699
+ }
618
700
  }
619
701
  },
620
702
  "required": [