@crvouga/atlas 0.16.0 → 0.17.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 (38) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/reports/src/attachment-files.d.ts +3 -1
  3. package/dist/reports/src/attachment-files.js +14 -4
  4. package/dist/reports/src/evidence-types.d.ts +22 -0
  5. package/dist/reports/src/layer-merge.js +5 -0
  6. package/dist/reports/src/layer-types.d.ts +1 -1
  7. package/dist/reports/src/publish-checks.js +11 -3
  8. package/dist/reports/src/recording-receipt.d.ts +48 -0
  9. package/dist/reports/src/recording-receipt.js +103 -0
  10. package/dist/reports/src/report-cli.d.ts +1 -1
  11. package/dist/reports/src/report-cli.js +20 -2
  12. package/dist/reports/src/report-status.d.ts +2 -0
  13. package/dist/reports/src/report-status.js +17 -1
  14. package/dist/reports/src/reports-explorer-route.d.ts +8 -0
  15. package/dist/reports/src/reports-route.d.ts +8 -0
  16. package/dist/schema/src/api.d.ts +65 -0
  17. package/dist/schema/src/api.js +7 -2
  18. package/dist/schema/src/cli-results.d.ts +107 -2
  19. package/dist/schema/src/cli-results.js +11 -3
  20. package/dist/schema/src/layer.d.ts +165 -0
  21. package/dist/schema/src/layer.js +72 -1
  22. package/docs/reference/cli.md +5 -0
  23. package/docs/reference/reports.md +94 -2
  24. package/docs/reference/schema.md +59 -0
  25. package/docs/rich-evidence.md +29 -0
  26. package/llms-full.txt +34 -0
  27. package/package.json +1 -1
  28. package/packages/schema/schemas/check-detail.schema.json +20 -0
  29. package/packages/schema/schemas/effective-delta.schema.json +61 -0
  30. package/packages/schema/schemas/effective-evidence.schema.json +61 -0
  31. package/packages/schema/schemas/evidence-page.schema.json +45 -0
  32. package/packages/schema/schemas/layer-rows.schema.json +16 -0
  33. package/packages/schema/schemas/layer.schema.json +153 -0
  34. package/packages/schema/schemas/publish-checks.schema.json +24 -0
  35. package/packages/schema/schemas/publish-result.schema.json +161 -1
  36. package/packages/schema/schemas/report-status.schema.json +104 -0
  37. package/packages/server/openapi.json +331 -0
  38. package/packages/visualizer/src/evidence/marks.tsx +16 -0
@@ -121,6 +121,7 @@ export declare const AttachmentSchema: z.ZodObject<{
121
121
  height: z.ZodOptional<z.ZodNumber>;
122
122
  durationMs: z.ZodOptional<z.ZodNumber>;
123
123
  description: z.ZodOptional<z.ZodString>;
124
+ omitted: z.ZodOptional<z.ZodString>;
124
125
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
125
126
  at: z.ZodOptional<z.ZodObject<{
126
127
  step: z.ZodOptional<z.ZodString>;
@@ -132,6 +133,59 @@ export declare const AttachmentSchema: z.ZodObject<{
132
133
  }, z.core.$loose>;
133
134
  /** An attachment as stored in a layer, parsed from `AttachmentSchema`. */
134
135
  export type Attachment = z.output<typeof AttachmentSchema>;
136
+ /**
137
+ * Whether a check is expected to have a screen recording (a video). `required`: the producer expects one, and the layer's
138
+ * recording receipt says whether it arrived. `not-applicable`: the check is intentionally unrecorded (an API-only check),
139
+ * so it counts as neither a recorded pass nor a missing video. An open string: a reader treats any other value, and its
140
+ * absence, as no expectation.
141
+ */
142
+ export declare const RECORDING_EXPECTATIONS: readonly ["required", "not-applicable"];
143
+ /**
144
+ * The state of one check's recording in a receipt, in an open vocabulary. Conventions: `uploaded` (the video's bytes are in
145
+ * the layer, with a checksum), `referenced` (only a `uri` was given: Atlas cannot vouch for it), `skipped` (the video was
146
+ * captured but its bytes were left out, with a reason), `unresolved` (no video was attached at all), `not-applicable`
147
+ * (intentionally unrecorded). A reader shows a state it does not know as it is and never counts it as uploaded.
148
+ */
149
+ export declare const RecordingItemSchema: z.ZodObject<{
150
+ check: z.ZodString;
151
+ state: z.ZodString;
152
+ reason: z.ZodOptional<z.ZodString>;
153
+ files: z.ZodOptional<z.ZodArray<z.ZodObject<{
154
+ name: z.ZodString;
155
+ state: z.ZodOptional<z.ZodString>;
156
+ bytes: z.ZodOptional<z.ZodNumber>;
157
+ sha256: z.ZodOptional<z.ZodString>;
158
+ reason: z.ZodOptional<z.ZodString>;
159
+ }, z.core.$loose>>>;
160
+ }, z.core.$loose>;
161
+ /**
162
+ * What a layer's producer published about the recordings it expected: counts and one item per check that expected a
163
+ * recording (or declared itself not applicable). Written by `publishChecks` when any check declares a
164
+ * `recordingExpectation`; a layer without it says nothing, which a reader reports as Unknown, never Complete. It only
165
+ * describes publication: it never changes a check's status, its slot or which result wins.
166
+ */
167
+ export declare const RecordingReceiptSchema: z.ZodObject<{
168
+ expected: z.ZodNumber;
169
+ uploaded: z.ZodNumber;
170
+ referenced: z.ZodNumber;
171
+ skipped: z.ZodNumber;
172
+ unresolved: z.ZodNumber;
173
+ notApplicable: z.ZodNumber;
174
+ items: z.ZodArray<z.ZodObject<{
175
+ check: z.ZodString;
176
+ state: z.ZodString;
177
+ reason: z.ZodOptional<z.ZodString>;
178
+ files: z.ZodOptional<z.ZodArray<z.ZodObject<{
179
+ name: z.ZodString;
180
+ state: z.ZodOptional<z.ZodString>;
181
+ bytes: z.ZodOptional<z.ZodNumber>;
182
+ sha256: z.ZodOptional<z.ZodString>;
183
+ reason: z.ZodOptional<z.ZodString>;
184
+ }, z.core.$loose>>>;
185
+ }, z.core.$loose>>;
186
+ }, z.core.$loose>;
187
+ /** A recording receipt as stored in a layer, parsed from `RecordingReceiptSchema`. */
188
+ export type RecordingReceipt = z.output<typeof RecordingReceiptSchema>;
135
189
  /** A note about a result: a warning, a deprecation, a coverage figure, an accessibility finding, anything. */
136
190
  export declare const AnnotationSchema: z.ZodObject<{
137
191
  type: z.ZodString;
@@ -182,6 +236,7 @@ export declare const StepSchema: z.ZodObject<{
182
236
  height: z.ZodOptional<z.ZodNumber>;
183
237
  durationMs: z.ZodOptional<z.ZodNumber>;
184
238
  description: z.ZodOptional<z.ZodString>;
239
+ omitted: z.ZodOptional<z.ZodString>;
185
240
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
186
241
  at: z.ZodOptional<z.ZodObject<{
187
242
  step: z.ZodOptional<z.ZodString>;
@@ -250,6 +305,7 @@ export declare const AttemptSchema: z.ZodObject<{
250
305
  height: z.ZodOptional<z.ZodNumber>;
251
306
  durationMs: z.ZodOptional<z.ZodNumber>;
252
307
  description: z.ZodOptional<z.ZodString>;
308
+ omitted: z.ZodOptional<z.ZodString>;
253
309
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
254
310
  at: z.ZodOptional<z.ZodObject<{
255
311
  step: z.ZodOptional<z.ZodString>;
@@ -295,6 +351,7 @@ export declare const AttemptSchema: z.ZodObject<{
295
351
  height: z.ZodOptional<z.ZodNumber>;
296
352
  durationMs: z.ZodOptional<z.ZodNumber>;
297
353
  description: z.ZodOptional<z.ZodString>;
354
+ omitted: z.ZodOptional<z.ZodString>;
298
355
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
299
356
  at: z.ZodOptional<z.ZodObject<{
300
357
  step: z.ZodOptional<z.ZodString>;
@@ -359,6 +416,7 @@ export declare const CheckSchema: z.ZodObject<{
359
416
  height: z.ZodOptional<z.ZodNumber>;
360
417
  durationMs: z.ZodOptional<z.ZodNumber>;
361
418
  description: z.ZodOptional<z.ZodString>;
419
+ omitted: z.ZodOptional<z.ZodString>;
362
420
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
363
421
  at: z.ZodOptional<z.ZodObject<{
364
422
  step: z.ZodOptional<z.ZodString>;
@@ -424,6 +482,7 @@ export declare const CheckSchema: z.ZodObject<{
424
482
  height: z.ZodOptional<z.ZodNumber>;
425
483
  durationMs: z.ZodOptional<z.ZodNumber>;
426
484
  description: z.ZodOptional<z.ZodString>;
485
+ omitted: z.ZodOptional<z.ZodString>;
427
486
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
428
487
  at: z.ZodOptional<z.ZodObject<{
429
488
  step: z.ZodOptional<z.ZodString>;
@@ -469,6 +528,7 @@ export declare const CheckSchema: z.ZodObject<{
469
528
  height: z.ZodOptional<z.ZodNumber>;
470
529
  durationMs: z.ZodOptional<z.ZodNumber>;
471
530
  description: z.ZodOptional<z.ZodString>;
531
+ omitted: z.ZodOptional<z.ZodString>;
472
532
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
473
533
  at: z.ZodOptional<z.ZodObject<{
474
534
  step: z.ZodOptional<z.ZodString>;
@@ -521,6 +581,7 @@ export declare const CheckSchema: z.ZodObject<{
521
581
  height: z.ZodOptional<z.ZodNumber>;
522
582
  durationMs: z.ZodOptional<z.ZodNumber>;
523
583
  description: z.ZodOptional<z.ZodString>;
584
+ omitted: z.ZodOptional<z.ZodString>;
524
585
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
525
586
  at: z.ZodOptional<z.ZodObject<{
526
587
  step: z.ZodOptional<z.ZodString>;
@@ -568,6 +629,7 @@ export declare const CheckSchema: z.ZodObject<{
568
629
  limit: z.ZodOptional<z.ZodNumber>;
569
630
  }, z.core.$loose>>>;
570
631
  durationMs: z.ZodOptional<z.ZodNumber>;
632
+ recordingExpectation: z.ZodOptional<z.ZodString>;
571
633
  }, z.core.$loose>;
572
634
  /** A check as stored in a layer, parsed from `CheckSchema`. */
573
635
  export type Check = z.output<typeof CheckSchema>;
@@ -608,6 +670,7 @@ export declare const ReportPartSchema: z.ZodObject<{
608
670
  height: z.ZodOptional<z.ZodNumber>;
609
671
  durationMs: z.ZodOptional<z.ZodNumber>;
610
672
  description: z.ZodOptional<z.ZodString>;
673
+ omitted: z.ZodOptional<z.ZodString>;
611
674
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
612
675
  at: z.ZodOptional<z.ZodObject<{
613
676
  step: z.ZodOptional<z.ZodString>;
@@ -672,6 +735,7 @@ export declare const ReportPartSchema: z.ZodObject<{
672
735
  height: z.ZodOptional<z.ZodNumber>;
673
736
  durationMs: z.ZodOptional<z.ZodNumber>;
674
737
  description: z.ZodOptional<z.ZodString>;
738
+ omitted: z.ZodOptional<z.ZodString>;
675
739
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
676
740
  at: z.ZodOptional<z.ZodObject<{
677
741
  step: z.ZodOptional<z.ZodString>;
@@ -737,6 +801,7 @@ export declare const ReportPartSchema: z.ZodObject<{
737
801
  height: z.ZodOptional<z.ZodNumber>;
738
802
  durationMs: z.ZodOptional<z.ZodNumber>;
739
803
  description: z.ZodOptional<z.ZodString>;
804
+ omitted: z.ZodOptional<z.ZodString>;
740
805
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
741
806
  at: z.ZodOptional<z.ZodObject<{
742
807
  step: z.ZodOptional<z.ZodString>;
@@ -782,6 +847,7 @@ export declare const ReportPartSchema: z.ZodObject<{
782
847
  height: z.ZodOptional<z.ZodNumber>;
783
848
  durationMs: z.ZodOptional<z.ZodNumber>;
784
849
  description: z.ZodOptional<z.ZodString>;
850
+ omitted: z.ZodOptional<z.ZodString>;
785
851
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
786
852
  at: z.ZodOptional<z.ZodObject<{
787
853
  step: z.ZodOptional<z.ZodString>;
@@ -834,6 +900,7 @@ export declare const ReportPartSchema: z.ZodObject<{
834
900
  height: z.ZodOptional<z.ZodNumber>;
835
901
  durationMs: z.ZodOptional<z.ZodNumber>;
836
902
  description: z.ZodOptional<z.ZodString>;
903
+ omitted: z.ZodOptional<z.ZodString>;
837
904
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
838
905
  at: z.ZodOptional<z.ZodObject<{
839
906
  step: z.ZodOptional<z.ZodString>;
@@ -881,6 +948,7 @@ export declare const ReportPartSchema: z.ZodObject<{
881
948
  limit: z.ZodOptional<z.ZodNumber>;
882
949
  }, z.core.$loose>>>;
883
950
  durationMs: z.ZodOptional<z.ZodNumber>;
951
+ recordingExpectation: z.ZodOptional<z.ZodString>;
884
952
  }, z.core.$loose>>;
885
953
  }, z.core.$loose>;
886
954
  /** A suite that recorded timelines and captured files, beside its checks. Absent for a layer of plain checks. */
@@ -923,6 +991,7 @@ export declare const LayerSourceSchema: z.ZodObject<{
923
991
  height: z.ZodOptional<z.ZodNumber>;
924
992
  durationMs: z.ZodOptional<z.ZodNumber>;
925
993
  description: z.ZodOptional<z.ZodString>;
994
+ omitted: z.ZodOptional<z.ZodString>;
926
995
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
927
996
  at: z.ZodOptional<z.ZodObject<{
928
997
  step: z.ZodOptional<z.ZodString>;
@@ -988,6 +1057,7 @@ export declare const LayerSourceSchema: z.ZodObject<{
988
1057
  height: z.ZodOptional<z.ZodNumber>;
989
1058
  durationMs: z.ZodOptional<z.ZodNumber>;
990
1059
  description: z.ZodOptional<z.ZodString>;
1060
+ omitted: z.ZodOptional<z.ZodString>;
991
1061
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
992
1062
  at: z.ZodOptional<z.ZodObject<{
993
1063
  step: z.ZodOptional<z.ZodString>;
@@ -1033,6 +1103,7 @@ export declare const LayerSourceSchema: z.ZodObject<{
1033
1103
  height: z.ZodOptional<z.ZodNumber>;
1034
1104
  durationMs: z.ZodOptional<z.ZodNumber>;
1035
1105
  description: z.ZodOptional<z.ZodString>;
1106
+ omitted: z.ZodOptional<z.ZodString>;
1036
1107
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1037
1108
  at: z.ZodOptional<z.ZodObject<{
1038
1109
  step: z.ZodOptional<z.ZodString>;
@@ -1085,6 +1156,7 @@ export declare const LayerSourceSchema: z.ZodObject<{
1085
1156
  height: z.ZodOptional<z.ZodNumber>;
1086
1157
  durationMs: z.ZodOptional<z.ZodNumber>;
1087
1158
  description: z.ZodOptional<z.ZodString>;
1159
+ omitted: z.ZodOptional<z.ZodString>;
1088
1160
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1089
1161
  at: z.ZodOptional<z.ZodObject<{
1090
1162
  step: z.ZodOptional<z.ZodString>;
@@ -1132,6 +1204,7 @@ export declare const LayerSourceSchema: z.ZodObject<{
1132
1204
  limit: z.ZodOptional<z.ZodNumber>;
1133
1205
  }, z.core.$loose>>>;
1134
1206
  durationMs: z.ZodOptional<z.ZodNumber>;
1207
+ recordingExpectation: z.ZodOptional<z.ZodString>;
1135
1208
  }, z.core.$loose>>;
1136
1209
  }, z.core.$loose>>>;
1137
1210
  tests: z.ZodArray<z.ZodObject<{
@@ -1200,6 +1273,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1200
1273
  height: z.ZodOptional<z.ZodNumber>;
1201
1274
  durationMs: z.ZodOptional<z.ZodNumber>;
1202
1275
  description: z.ZodOptional<z.ZodString>;
1276
+ omitted: z.ZodOptional<z.ZodString>;
1203
1277
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1204
1278
  at: z.ZodOptional<z.ZodObject<{
1205
1279
  step: z.ZodOptional<z.ZodString>;
@@ -1278,6 +1352,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1278
1352
  height: z.ZodOptional<z.ZodNumber>;
1279
1353
  durationMs: z.ZodOptional<z.ZodNumber>;
1280
1354
  description: z.ZodOptional<z.ZodString>;
1355
+ omitted: z.ZodOptional<z.ZodString>;
1281
1356
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1282
1357
  at: z.ZodOptional<z.ZodObject<{
1283
1358
  step: z.ZodOptional<z.ZodString>;
@@ -1342,6 +1417,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1342
1417
  height: z.ZodOptional<z.ZodNumber>;
1343
1418
  durationMs: z.ZodOptional<z.ZodNumber>;
1344
1419
  description: z.ZodOptional<z.ZodString>;
1420
+ omitted: z.ZodOptional<z.ZodString>;
1345
1421
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1346
1422
  at: z.ZodOptional<z.ZodObject<{
1347
1423
  step: z.ZodOptional<z.ZodString>;
@@ -1407,6 +1483,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1407
1483
  height: z.ZodOptional<z.ZodNumber>;
1408
1484
  durationMs: z.ZodOptional<z.ZodNumber>;
1409
1485
  description: z.ZodOptional<z.ZodString>;
1486
+ omitted: z.ZodOptional<z.ZodString>;
1410
1487
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1411
1488
  at: z.ZodOptional<z.ZodObject<{
1412
1489
  step: z.ZodOptional<z.ZodString>;
@@ -1452,6 +1529,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1452
1529
  height: z.ZodOptional<z.ZodNumber>;
1453
1530
  durationMs: z.ZodOptional<z.ZodNumber>;
1454
1531
  description: z.ZodOptional<z.ZodString>;
1532
+ omitted: z.ZodOptional<z.ZodString>;
1455
1533
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1456
1534
  at: z.ZodOptional<z.ZodObject<{
1457
1535
  step: z.ZodOptional<z.ZodString>;
@@ -1504,6 +1582,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1504
1582
  height: z.ZodOptional<z.ZodNumber>;
1505
1583
  durationMs: z.ZodOptional<z.ZodNumber>;
1506
1584
  description: z.ZodOptional<z.ZodString>;
1585
+ omitted: z.ZodOptional<z.ZodString>;
1507
1586
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1508
1587
  at: z.ZodOptional<z.ZodObject<{
1509
1588
  step: z.ZodOptional<z.ZodString>;
@@ -1551,6 +1630,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1551
1630
  limit: z.ZodOptional<z.ZodNumber>;
1552
1631
  }, z.core.$loose>>>;
1553
1632
  durationMs: z.ZodOptional<z.ZodNumber>;
1633
+ recordingExpectation: z.ZodOptional<z.ZodString>;
1554
1634
  }, z.core.$loose>>;
1555
1635
  }, z.core.$loose>>;
1556
1636
  source: z.ZodDefault<z.ZodNullable<z.ZodObject<{
@@ -1592,6 +1672,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1592
1672
  height: z.ZodOptional<z.ZodNumber>;
1593
1673
  durationMs: z.ZodOptional<z.ZodNumber>;
1594
1674
  description: z.ZodOptional<z.ZodString>;
1675
+ omitted: z.ZodOptional<z.ZodString>;
1595
1676
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1596
1677
  at: z.ZodOptional<z.ZodObject<{
1597
1678
  step: z.ZodOptional<z.ZodString>;
@@ -1657,6 +1738,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1657
1738
  height: z.ZodOptional<z.ZodNumber>;
1658
1739
  durationMs: z.ZodOptional<z.ZodNumber>;
1659
1740
  description: z.ZodOptional<z.ZodString>;
1741
+ omitted: z.ZodOptional<z.ZodString>;
1660
1742
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1661
1743
  at: z.ZodOptional<z.ZodObject<{
1662
1744
  step: z.ZodOptional<z.ZodString>;
@@ -1702,6 +1784,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1702
1784
  height: z.ZodOptional<z.ZodNumber>;
1703
1785
  durationMs: z.ZodOptional<z.ZodNumber>;
1704
1786
  description: z.ZodOptional<z.ZodString>;
1787
+ omitted: z.ZodOptional<z.ZodString>;
1705
1788
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1706
1789
  at: z.ZodOptional<z.ZodObject<{
1707
1790
  step: z.ZodOptional<z.ZodString>;
@@ -1754,6 +1837,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1754
1837
  height: z.ZodOptional<z.ZodNumber>;
1755
1838
  durationMs: z.ZodOptional<z.ZodNumber>;
1756
1839
  description: z.ZodOptional<z.ZodString>;
1840
+ omitted: z.ZodOptional<z.ZodString>;
1757
1841
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1758
1842
  at: z.ZodOptional<z.ZodObject<{
1759
1843
  step: z.ZodOptional<z.ZodString>;
@@ -1801,6 +1885,7 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1801
1885
  limit: z.ZodOptional<z.ZodNumber>;
1802
1886
  }, z.core.$loose>>>;
1803
1887
  durationMs: z.ZodOptional<z.ZodNumber>;
1888
+ recordingExpectation: z.ZodOptional<z.ZodString>;
1804
1889
  }, z.core.$loose>>;
1805
1890
  }, z.core.$loose>>>;
1806
1891
  tests: z.ZodArray<z.ZodObject<{
@@ -1832,6 +1917,26 @@ export declare const LayerDocumentSchema: z.ZodObject<{
1832
1917
  size: z.ZodNumber;
1833
1918
  }, z.core.$loose>>;
1834
1919
  }, z.core.$loose>>>;
1920
+ recordings: z.ZodOptional<z.ZodObject<{
1921
+ expected: z.ZodNumber;
1922
+ uploaded: z.ZodNumber;
1923
+ referenced: z.ZodNumber;
1924
+ skipped: z.ZodNumber;
1925
+ unresolved: z.ZodNumber;
1926
+ notApplicable: z.ZodNumber;
1927
+ items: z.ZodArray<z.ZodObject<{
1928
+ check: z.ZodString;
1929
+ state: z.ZodString;
1930
+ reason: z.ZodOptional<z.ZodString>;
1931
+ files: z.ZodOptional<z.ZodArray<z.ZodObject<{
1932
+ name: z.ZodString;
1933
+ state: z.ZodOptional<z.ZodString>;
1934
+ bytes: z.ZodOptional<z.ZodNumber>;
1935
+ sha256: z.ZodOptional<z.ZodString>;
1936
+ reason: z.ZodOptional<z.ZodString>;
1937
+ }, z.core.$loose>>>;
1938
+ }, z.core.$loose>>;
1939
+ }, z.core.$loose>>;
1835
1940
  }, z.core.$loose>;
1836
1941
  /** A layer as a reader holds it: the output of `LayerDocumentSchema`, with defaults applied. */
1837
1942
  export type LayerDocument = z.output<typeof LayerDocumentSchema>;
@@ -1882,6 +1987,7 @@ export declare const AttachmentInputSchema: z.ZodObject<{
1882
1987
  height: z.ZodOptional<z.ZodNumber>;
1883
1988
  durationMs: z.ZodOptional<z.ZodNumber>;
1884
1989
  description: z.ZodOptional<z.ZodString>;
1990
+ omitted: z.ZodOptional<z.ZodString>;
1885
1991
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1886
1992
  at: z.ZodOptional<z.ZodObject<{
1887
1993
  step: z.ZodOptional<z.ZodString>;
@@ -1949,6 +2055,7 @@ export declare const PublishChecksSchema: z.ZodObject<{
1949
2055
  limit: z.ZodOptional<z.ZodNumber>;
1950
2056
  }, z.core.$loose>>>;
1951
2057
  durationMs: z.ZodOptional<z.ZodNumber>;
2058
+ recordingExpectation: z.ZodOptional<z.ZodString>;
1952
2059
  attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
1953
2060
  id: z.ZodOptional<z.ZodString>;
1954
2061
  name: z.ZodString;
@@ -1963,6 +2070,7 @@ export declare const PublishChecksSchema: z.ZodObject<{
1963
2070
  height: z.ZodOptional<z.ZodNumber>;
1964
2071
  durationMs: z.ZodOptional<z.ZodNumber>;
1965
2072
  description: z.ZodOptional<z.ZodString>;
2073
+ omitted: z.ZodOptional<z.ZodString>;
1966
2074
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
1967
2075
  at: z.ZodOptional<z.ZodObject<{
1968
2076
  step: z.ZodOptional<z.ZodString>;
@@ -2019,6 +2127,7 @@ export declare const PublishChecksSchema: z.ZodObject<{
2019
2127
  height: z.ZodOptional<z.ZodNumber>;
2020
2128
  durationMs: z.ZodOptional<z.ZodNumber>;
2021
2129
  description: z.ZodOptional<z.ZodString>;
2130
+ omitted: z.ZodOptional<z.ZodString>;
2022
2131
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2023
2132
  at: z.ZodOptional<z.ZodObject<{
2024
2133
  step: z.ZodOptional<z.ZodString>;
@@ -2108,6 +2217,7 @@ export declare const PublishChecksSchema: z.ZodObject<{
2108
2217
  height: z.ZodOptional<z.ZodNumber>;
2109
2218
  durationMs: z.ZodOptional<z.ZodNumber>;
2110
2219
  description: z.ZodOptional<z.ZodString>;
2220
+ omitted: z.ZodOptional<z.ZodString>;
2111
2221
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2112
2222
  at: z.ZodOptional<z.ZodObject<{
2113
2223
  step: z.ZodOptional<z.ZodString>;
@@ -2135,6 +2245,7 @@ export declare const PublishChecksSchema: z.ZodObject<{
2135
2245
  height: z.ZodOptional<z.ZodNumber>;
2136
2246
  durationMs: z.ZodOptional<z.ZodNumber>;
2137
2247
  description: z.ZodOptional<z.ZodString>;
2248
+ omitted: z.ZodOptional<z.ZodString>;
2138
2249
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2139
2250
  at: z.ZodOptional<z.ZodObject<{
2140
2251
  step: z.ZodOptional<z.ZodString>;
@@ -2195,6 +2306,7 @@ export declare const PublishChecksSchema: z.ZodObject<{
2195
2306
  height: z.ZodOptional<z.ZodNumber>;
2196
2307
  durationMs: z.ZodOptional<z.ZodNumber>;
2197
2308
  description: z.ZodOptional<z.ZodString>;
2309
+ omitted: z.ZodOptional<z.ZodString>;
2198
2310
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2199
2311
  at: z.ZodOptional<z.ZodObject<{
2200
2312
  step: z.ZodOptional<z.ZodString>;
@@ -2231,6 +2343,36 @@ export declare const PublishChecksSchema: z.ZodObject<{
2231
2343
  }, z.core.$loose>;
2232
2344
  /** What a caller passes to `publishChecks`: the input type of `PublishChecksSchema`, before defaults. */
2233
2345
  export type PublishChecksInput = z.input<typeof PublishChecksSchema>;
2346
+ /**
2347
+ * Recording completeness across the winning results of a report: `complete` (every expected recording was published),
2348
+ * `incomplete` (at least one is skipped or unresolved), `none-expected` (every layer declared its expectations, and none
2349
+ * required a recording) or `unknown` (a layer has no receipt, so nothing is claimed). Independent of the checks' outcomes.
2350
+ */
2351
+ export declare const RecordingCompletenessSchema: z.ZodObject<{
2352
+ state: z.ZodEnum<{
2353
+ unknown: "unknown";
2354
+ complete: "complete";
2355
+ incomplete: "incomplete";
2356
+ "none-expected": "none-expected";
2357
+ }>;
2358
+ expected: z.ZodNumber;
2359
+ uploaded: z.ZodNumber;
2360
+ referenced: z.ZodNumber;
2361
+ skipped: z.ZodNumber;
2362
+ unresolved: z.ZodNumber;
2363
+ notApplicable: z.ZodNumber;
2364
+ layersWithoutReceipt: z.ZodNumber;
2365
+ gaps: z.ZodArray<z.ZodObject<{
2366
+ spec: z.ZodNullable<z.ZodString>;
2367
+ check: z.ZodString;
2368
+ layer: z.ZodString;
2369
+ environment: z.ZodNullable<z.ZodString>;
2370
+ state: z.ZodString;
2371
+ reason: z.ZodOptional<z.ZodString>;
2372
+ }, z.core.$loose>>;
2373
+ }, z.core.$loose>;
2374
+ /** A parsed `RecordingCompletenessSchema` value. */
2375
+ export type RecordingCompleteness = z.output<typeof RecordingCompletenessSchema>;
2234
2376
  /** The `schemaVersion` of the `ReportStatus` JSON, currently 1. */
2235
2377
  export declare const REPORT_STATUS_SCHEMA_VERSION = 1;
2236
2378
  /**
@@ -2300,6 +2442,29 @@ export declare const ReportStatusSchema: z.ZodObject<{
2300
2442
  runUrl: z.ZodNullable<z.ZodString>;
2301
2443
  detail: z.ZodString;
2302
2444
  }, z.core.$loose>>;
2445
+ recordings: z.ZodOptional<z.ZodObject<{
2446
+ state: z.ZodEnum<{
2447
+ unknown: "unknown";
2448
+ complete: "complete";
2449
+ incomplete: "incomplete";
2450
+ "none-expected": "none-expected";
2451
+ }>;
2452
+ expected: z.ZodNumber;
2453
+ uploaded: z.ZodNumber;
2454
+ referenced: z.ZodNumber;
2455
+ skipped: z.ZodNumber;
2456
+ unresolved: z.ZodNumber;
2457
+ notApplicable: z.ZodNumber;
2458
+ layersWithoutReceipt: z.ZodNumber;
2459
+ gaps: z.ZodArray<z.ZodObject<{
2460
+ spec: z.ZodNullable<z.ZodString>;
2461
+ check: z.ZodString;
2462
+ layer: z.ZodString;
2463
+ environment: z.ZodNullable<z.ZodString>;
2464
+ state: z.ZodString;
2465
+ reason: z.ZodOptional<z.ZodString>;
2466
+ }, z.core.$loose>>;
2467
+ }, z.core.$loose>>;
2303
2468
  }, z.core.$loose>;
2304
2469
  /** A parsed `ReportStatusSchema` value. */
2305
2470
  export type ReportStatus = z.output<typeof ReportStatusSchema>;
@@ -109,12 +109,53 @@ export const AttachmentSchema = z.looseObject({
109
109
  height: z.number().nonnegative().optional(),
110
110
  durationMs: z.number().nonnegative().optional().describe('For video and audio'),
111
111
  description: z.string().optional(),
112
+ omitted: z.string().optional().describe('Why the producer did not include its bytes, in an open vocabulary: too-large, not-found, not-allowed, over-budget, policy… Present on a metadata-only attachment, so a reader can tell "left out" from "never recorded"'),
112
113
  tags: z.array(z.string()).optional().describe('Free labels of this one attachment, such as `demo`: shown as `#demo`, searchable, and normalized by `normalizeTag` (a leading `#` and letter case never matter). Unlike the tags of a check they say nothing about its result'),
113
114
  at: MomentSchema.optional(),
114
115
  poster: z.string().optional().describe('The `id` of an attachment that stands for this one before it is opened'),
115
116
  captions: z.array(z.string()).optional().describe('The `id`s of attachments (WebVTT, SRT) that caption this one'),
116
117
  extensions: ExtensionsSchema.optional()
117
118
  });
119
+ /**
120
+ * Whether a check is expected to have a screen recording (a video). `required`: the producer expects one, and the layer's
121
+ * recording receipt says whether it arrived. `not-applicable`: the check is intentionally unrecorded (an API-only check),
122
+ * so it counts as neither a recorded pass nor a missing video. An open string: a reader treats any other value, and its
123
+ * absence, as no expectation.
124
+ */
125
+ export const RECORDING_EXPECTATIONS = ['required', 'not-applicable'];
126
+ /**
127
+ * The state of one check's recording in a receipt, in an open vocabulary. Conventions: `uploaded` (the video's bytes are in
128
+ * the layer, with a checksum), `referenced` (only a `uri` was given: Atlas cannot vouch for it), `skipped` (the video was
129
+ * captured but its bytes were left out, with a reason), `unresolved` (no video was attached at all), `not-applicable`
130
+ * (intentionally unrecorded). A reader shows a state it does not know as it is and never counts it as uploaded.
131
+ */
132
+ export const RecordingItemSchema = z.looseObject({
133
+ check: z.string().min(1).describe('The id of the check'),
134
+ state: z.string().min(1),
135
+ reason: z.string().optional().describe('Why the recording is not uploaded. Never contains a path, a token or payload data'),
136
+ files: z.array(z.looseObject({
137
+ name: z.string(),
138
+ state: z.string().optional(),
139
+ bytes: z.number().int().nonnegative().optional(),
140
+ sha256: z.string().optional().describe('The checksum of the stored bytes: proof the layer holds this exact file'),
141
+ reason: z.string().optional()
142
+ })).optional().describe('Every video attachment of the check, at any level')
143
+ });
144
+ /**
145
+ * What a layer's producer published about the recordings it expected: counts and one item per check that expected a
146
+ * recording (or declared itself not applicable). Written by `publishChecks` when any check declares a
147
+ * `recordingExpectation`; a layer without it says nothing, which a reader reports as Unknown, never Complete. It only
148
+ * describes publication: it never changes a check's status, its slot or which result wins.
149
+ */
150
+ export const RecordingReceiptSchema = z.looseObject({
151
+ expected: z.number().int().nonnegative().describe('Checks that required a recording: uploaded + referenced + skipped + unresolved'),
152
+ uploaded: z.number().int().nonnegative(),
153
+ referenced: z.number().int().nonnegative(),
154
+ skipped: z.number().int().nonnegative(),
155
+ unresolved: z.number().int().nonnegative(),
156
+ notApplicable: z.number().int().nonnegative().describe('Checks intentionally unrecorded. They are not expected and not missing'),
157
+ items: z.array(RecordingItemSchema)
158
+ });
118
159
  /** A note about a result: a warning, a deprecation, a coverage figure, an accessibility finding, anything. */
119
160
  export const AnnotationSchema = z.looseObject({
120
161
  type: z.string().min(1).describe('An open vocabulary: note, warning, deprecation, issue, accessibility, coverage…'),
@@ -178,6 +219,7 @@ export const CheckSchema = z.looseObject({
178
219
  specPath: z.string().optional().describe('The spec this check belongs to, relative to the repository, such as specs/join.feature'),
179
220
  measurements: z.array(MeasurementSchema).default([]),
180
221
  durationMs: z.number().nonnegative().optional().describe('How long the check took, when the producer measured it'),
222
+ recordingExpectation: z.string().optional().describe('`required`: expect a video of this check, and report whether it was published. `not-applicable`: intentionally unrecorded. Absent: no expectation. Never changes the check\'s status'),
181
223
  ...evidenceShape,
182
224
  steps: z.array(StepSchema).optional().describe("The check's timeline"),
183
225
  attempts: z.array(AttemptSchema).optional().describe('Every try, when the check was retried')
@@ -269,6 +311,7 @@ export const LayerDocumentSchema = z.looseObject({
269
311
  source: LayerSourceSchema.nullable().default(null),
270
312
  recording: RecordingAddressSchema.nullable().default(null),
271
313
  bundle: BundleIndexSchema.default({}),
314
+ recordings: RecordingReceiptSchema.optional().describe('Which expected recordings were published. Absent: the producer expected none, or predates this field; a reader reports Unknown'),
272
315
  ...evidenceShape
273
316
  });
274
317
  /**
@@ -321,6 +364,14 @@ function lenientEvidence(holder, nested = []) {
321
364
  }
322
365
  function lenientLayer(raw) {
323
366
  const layer = lenientEvidence(raw);
367
+ // A receipt a reader cannot read is no receipt: recording completeness is then Unknown, and the layer is kept.
368
+ if ('recordings' in layer) {
369
+ const receipt = RecordingReceiptSchema.safeParse(layer.recordings);
370
+ if (receipt.success)
371
+ layer.recordings = receipt.data;
372
+ else
373
+ delete layer.recordings;
374
+ }
324
375
  // The execution only groups and labels: one that cannot be read leaves the layer to the documented grouping, never refuses it.
325
376
  if ('run' in layer && !LayerRunSchema.safeParse(layer.run).success)
326
377
  delete layer.run;
@@ -426,6 +477,25 @@ const CountsSchema = z.object({
426
477
  'not-run': z.number().int().nonnegative(),
427
478
  total: z.number().int().nonnegative()
428
479
  });
480
+ /**
481
+ * Recording completeness across the winning results of a report: `complete` (every expected recording was published),
482
+ * `incomplete` (at least one is skipped or unresolved), `none-expected` (every layer declared its expectations, and none
483
+ * required a recording) or `unknown` (a layer has no receipt, so nothing is claimed). Independent of the checks' outcomes.
484
+ */
485
+ export const RecordingCompletenessSchema = z.looseObject({
486
+ state: z.enum(['complete', 'incomplete', 'none-expected', 'unknown']),
487
+ expected: z.number().int().nonnegative(),
488
+ uploaded: z.number().int().nonnegative(),
489
+ referenced: z.number().int().nonnegative(),
490
+ skipped: z.number().int().nonnegative(),
491
+ unresolved: z.number().int().nonnegative(),
492
+ notApplicable: z.number().int().nonnegative(),
493
+ layersWithoutReceipt: z.number().int().nonnegative().describe('Layers that contribute results but declared no recording expectations: their completeness is unknown'),
494
+ gaps: z.array(z.looseObject({
495
+ spec: z.string().nullable(), check: z.string(), layer: z.string(), environment: z.string().nullable(),
496
+ state: z.string(), reason: z.string().optional()
497
+ })).describe('Each expected recording that is skipped or unresolved')
498
+ });
429
499
  /** The `schemaVersion` of the `ReportStatus` JSON, currently 1. */
430
500
  export const REPORT_STATUS_SCHEMA_VERSION = 1;
431
501
  /**
@@ -463,7 +533,8 @@ export const ReportStatusSchema = z.looseObject({
463
533
  backend: z.string(),
464
534
  runUrl: z.string().nullable(),
465
535
  detail: z.string()
466
- })).describe('Each slot whose newest completed result failed, or that is still running')
536
+ })).describe('Each slot whose newest completed result failed, or that is still running'),
537
+ recordings: RecordingCompletenessSchema.optional().describe('Whether the recordings the producers expected were published, separately from `ok`. It never changes `ok`')
467
538
  });
468
539
  /**
469
540
  * The specs of one version of a project, as published: what the report is laid over. Layers of
@@ -91,6 +91,7 @@ atlas report — layered evidence for any kind of spec
91
91
  [--param key=value]... [--kind <k>] [--title <t>] [--recorded-at <iso|ms>]
92
92
  [--attach [role=]<file>]... [--label key=value]... [--link [name=]<url>]...
93
93
  [--attach-root <dir>]... [--max-attachment-mb <n>] [--max-total-attachment-mb <n>]
94
+ [--require-recordings]
94
95
  atlas report stream [--store <dir|s3://…|https://atlas.example.com>] --producer <name> [--environment <name>]
95
96
  [--branch <b>] [--sha <s>] [--run-url <u>] [--kind <k>] [--param key=value]...
96
97
  [--run-id <id>] [--run-title <t>]
@@ -127,6 +128,10 @@ atlas report — layered evidence for any kind of spec
127
128
  Files a report names (CTRF attachments, JUnit [[ATTACHMENT|path]] lines) come from the report's own
128
129
  folder and each --attach-root, and never from a hidden file or a link out: a report is data from a
129
130
  test run, not instructions. One that is missing or not allowed is skipped with a warning.
131
+ --require-recordings exit 1 when a check that declared recordingExpectation "required" has no
132
+ uploaded video (absent, left out as too large or not allowed, or refused). The layer is
133
+ still written and the checks keep their results; only this command fails. The receipt of
134
+ what was uploaded (counts, sizes, checksums) is in the JSON result under layer.recordings.
130
135
  From a checkout with uncommitted changes the layer is marked "modified".
131
136
  stream Send checks as they finish: one JSON object per line on standard input (the fields of one
132
137
  check: id, title, status, and any evidence). Each second's worth becomes one layer, so a server