@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
@@ -276,7 +276,9 @@ recursively), and hands their bytes over as `data` with a `contentType` guessed
276
276
  attachment gave none.
277
277
 
278
278
  A file that is missing, not allowed or too large is left out with a warning: evidence that could not be
279
- found never stops the results from being published. Attachments without a `path` are kept untouched.
279
+ found never stops the results from being published. The exception in kind is a video of a check that declared
280
+ `recordingExpectation: "required"`: it stays as an attachment without bytes whose `omitted` says why (`not-found`,
281
+ `not-allowed`, `too-large`, `over-budget`), so the recording receipt can name the gap. Attachments without a `path` are kept untouched.
280
282
 
281
283
  - `holder`: A check, step, attempt or any object that may have `attachments`, `steps` and `attempts`.
282
284
 
@@ -1747,11 +1749,34 @@ export type LayerHeader = {
1747
1749
  readonly execution: string;
1748
1750
  /** What the run as a whole carries: its logs, links and labels. */
1749
1751
  readonly evidence?: EvidenceSummary;
1752
+ /** Counts from the layer's recording receipt: how many expected recordings were published. Absent when the layer declared no expectations: its completeness is unknown, not complete. Never changes a status. */
1753
+ readonly recordings?: RecordingCounts;
1750
1754
  };
1751
1755
  ```
1752
1756
 
1753
1757
  A report layer's origin and totals. Its checks are read separately, once.
1754
1758
 
1759
+ #### `RecordingCounts`
1760
+
1761
+ ```ts
1762
+ export type RecordingCounts = {
1763
+ /** Checks that required a recording: `uploaded + referenced + skipped + unresolved`. */
1764
+ readonly expected: number;
1765
+ /** Stored in the layer, with a checksum. */
1766
+ readonly uploaded: number;
1767
+ /** Given only by `uri`: Atlas cannot vouch for it. */
1768
+ readonly referenced: number;
1769
+ /** Captured but left out, with a reason (too large, not allowed…). */
1770
+ readonly skipped: number;
1771
+ /** No video was attached at all. */
1772
+ readonly unresolved: number;
1773
+ /** Intentionally unrecorded checks: neither expected nor missing. */
1774
+ readonly notApplicable: number;
1775
+ };
1776
+ ```
1777
+
1778
+ How many recordings a layer expected and what became of them (see `RecordingReceipt`).
1779
+
1755
1780
  #### `LayerRow`
1756
1781
 
1757
1782
  ```ts
@@ -1775,6 +1800,8 @@ export type LayerRow = {
1775
1800
  readonly durationMs: number | null;
1776
1801
  /** What this result carries beyond its outcome. Absent when nothing. */
1777
1802
  readonly evidence?: EvidenceSummary;
1803
+ /** What became of this check's expected recording: `uploaded`, `referenced`, `skipped`, `unresolved` or `not-applicable`, with a reason when it is not uploaded. Absent when the check declared no expectation. Independent of `status`. */
1804
+ readonly recording?: { readonly state: string; readonly reason?: string };
1778
1805
  };
1779
1806
  ```
1780
1807
 
@@ -3983,7 +4010,7 @@ String choices (such as `{ device: 'iphone-15' }`) that make a result its own sl
3983
4010
  #### `LayerExtras`
3984
4011
 
3985
4012
  ```ts
3986
- export type LayerExtras = Partial<Pick<import('../../schema/src/layer').LayerDocument, 'tags' | 'labels' | 'links' | 'attachments' | 'annotations' | 'extensions'>>;
4013
+ export type LayerExtras = Partial<Pick<import('../../schema/src/layer').LayerDocument, 'tags' | 'labels' | 'links' | 'attachments' | 'annotations' | 'extensions' | 'recordings'>>;
3987
4014
  ```
3988
4015
 
3989
4016
  What a layer may carry as a whole. All optional and open: see docs/extending.md.
@@ -5381,6 +5408,69 @@ export function contentTypeForMedia(media: string): string
5381
5408
 
5382
5409
  The media type for a snapshot media kind (`html`, `png`, `json`, `text`, `bytes`, `video`); an unknown kind is `application/octet-stream`.
5383
5410
 
5411
+ ### Recording receipts
5412
+
5413
+ Source: `packages/reports/src/recording-receipt.ts`. Import: `@crvouga/atlas/reports/recording-receipt`
5414
+
5415
+ Answers "did the recordings we expected get published?" apart from "did the tests pass?". `recordingReceipt` reads the
5416
+ checks a producer is about to publish (after their files were stored) and describes, per check that declared a
5417
+ `recordingExpectation`, whether its video was uploaded, only referenced, left out (with a reason) or never attached.
5418
+ `recordingCompleteness` reduces the winning results of a report to the figures `atlas report status` prints. Neither
5419
+ reads a clock or the environment, and neither changes a status, a slot or a winner: a receipt describes publication, it
5420
+ does not decide a result. A layer with no receipt is Unknown, never Complete.
5421
+
5422
+ See docs/rich-evidence.md#recording-completeness
5423
+
5424
+ #### `isVideoAttachment`
5425
+
5426
+ ```ts
5427
+ export function isVideoAttachment(attachment: Loose): boolean
5428
+ ```
5429
+
5430
+ Is this attachment a screen recording: a role of `video`, or a `video/*` media type?
5431
+
5432
+ #### `recordingReceipt`
5433
+
5434
+ ```ts
5435
+ export function recordingReceipt(checks: readonly Loose[]): RecordingReceipt | undefined
5436
+ ```
5437
+
5438
+ The receipt for the checks of one layer, or `undefined` when no check declares a `recordingExpectation` (the layer then
5439
+ claims nothing). Call it with checks whose attachment bytes are already stored (`bundleKey`, `bytes` and `sha256` set).
5440
+
5441
+ A `required` check is `uploaded` when any video of it has stored bytes, `referenced` when one has only a `uri`,
5442
+ `skipped` when its videos were left out (the attachment's `omitted` is the reason) and `unresolved` when it has no
5443
+ video at all. A `not-applicable` check is listed but is neither expected nor missing. Items are sorted by check id so the
5444
+ same input is always the same receipt.
5445
+
5446
+ #### `RecordingResult`
5447
+
5448
+ ```ts
5449
+ export type RecordingResult = {
5450
+ readonly spec: string | null;
5451
+ readonly check: string;
5452
+ readonly environment: string | null;
5453
+ readonly layer: string;
5454
+ /** Whether the layer the result came from carried a receipt. */
5455
+ readonly hasReceipt: boolean;
5456
+ /** The result's item in that receipt, when its check declared an expectation. */
5457
+ readonly recording?: { readonly state: string; readonly reason?: string };
5458
+ };
5459
+ ```
5460
+
5461
+ One result as {@link recordingCompleteness} reads it.
5462
+
5463
+ #### `recordingCompleteness`
5464
+
5465
+ ```ts
5466
+ export function recordingCompleteness(results: readonly RecordingResult[]): RecordingCompleteness
5467
+ ```
5468
+
5469
+ Reduces the winning results of a report to its recording completeness. `incomplete` when any expected recording is
5470
+ skipped or unresolved; otherwise `unknown` when a contributing layer has no receipt (nothing is claimed for it, and a
5471
+ report with no results at all is unknown too); otherwise `complete` when something was expected and `none-expected` when
5472
+ nothing was. Gaps are sorted so the output never depends on read order.
5473
+
5384
5474
  ### Remote commit report
5385
5475
 
5386
5476
  Source: `packages/reports/src/remote-report.ts`. Import: `@crvouga/atlas/reports/remote-report`
@@ -5756,6 +5846,8 @@ checks (or none completed), failed checks, running checks, specs without results
5756
5846
  each required environment with no checks (the name is normalised, so `iOS` means `ios`), then every notice of the
5757
5847
  report (an unreadable layer or backend). `failing` lists each failed or running winner, in a fixed order that does
5758
5848
  not depend on read order; diagnostic `performance` checks are left out unless nothing else was recorded.
5849
+ `recordings` reports recording completeness of the same results apart from `ok`: an incomplete or unknown
5850
+ completeness never changes the gate (use `atlas report publish --require-recordings` to fail on a missing video).
5759
5851
 
5760
5852
  **Example**
5761
5853
 
@@ -764,6 +764,47 @@ export type Attachment = z.output<typeof AttachmentSchema>;
764
764
 
765
765
  An attachment as stored in a layer, parsed from `AttachmentSchema`.
766
766
 
767
+ #### `RECORDING_EXPECTATIONS`
768
+
769
+ ```ts
770
+ export const RECORDING_EXPECTATIONS = …
771
+ ```
772
+
773
+ Whether a check is expected to have a screen recording (a video). `required`: the producer expects one, and the layer's
774
+ recording receipt says whether it arrived. `not-applicable`: the check is intentionally unrecorded (an API-only check),
775
+ so it counts as neither a recorded pass nor a missing video. An open string: a reader treats any other value, and its
776
+ absence, as no expectation.
777
+
778
+ #### `RecordingItemSchema`
779
+
780
+ ```ts
781
+ export const RecordingItemSchema = …
782
+ ```
783
+
784
+ The state of one check's recording in a receipt, in an open vocabulary. Conventions: `uploaded` (the video's bytes are in
785
+ the layer, with a checksum), `referenced` (only a `uri` was given: Atlas cannot vouch for it), `skipped` (the video was
786
+ captured but its bytes were left out, with a reason), `unresolved` (no video was attached at all), `not-applicable`
787
+ (intentionally unrecorded). A reader shows a state it does not know as it is and never counts it as uploaded.
788
+
789
+ #### `RecordingReceiptSchema`
790
+
791
+ ```ts
792
+ export const RecordingReceiptSchema = …
793
+ ```
794
+
795
+ What a layer's producer published about the recordings it expected: counts and one item per check that expected a
796
+ recording (or declared itself not applicable). Written by `publishChecks` when any check declares a
797
+ `recordingExpectation`; a layer without it says nothing, which a reader reports as Unknown, never Complete. It only
798
+ describes publication: it never changes a check's status, its slot or which result wins.
799
+
800
+ #### `RecordingReceipt`
801
+
802
+ ```ts
803
+ export type RecordingReceipt = z.output<typeof RecordingReceiptSchema>;
804
+ ```
805
+
806
+ A recording receipt as stored in a layer, parsed from `RecordingReceiptSchema`.
807
+
767
808
  #### `AnnotationSchema`
768
809
 
769
810
  ```ts
@@ -962,6 +1003,24 @@ export type PublishChecksInput = z.input<typeof PublishChecksSchema>;
962
1003
 
963
1004
  What a caller passes to `publishChecks`: the input type of `PublishChecksSchema`, before defaults.
964
1005
 
1006
+ #### `RecordingCompletenessSchema`
1007
+
1008
+ ```ts
1009
+ export const RecordingCompletenessSchema = …
1010
+ ```
1011
+
1012
+ Recording completeness across the winning results of a report: `complete` (every expected recording was published),
1013
+ `incomplete` (at least one is skipped or unresolved), `none-expected` (every layer declared its expectations, and none
1014
+ required a recording) or `unknown` (a layer has no receipt, so nothing is claimed). Independent of the checks' outcomes.
1015
+
1016
+ #### `RecordingCompleteness`
1017
+
1018
+ ```ts
1019
+ export type RecordingCompleteness = z.output<typeof RecordingCompletenessSchema>;
1020
+ ```
1021
+
1022
+ A parsed `RecordingCompletenessSchema` value.
1023
+
965
1024
  #### `REPORT_STATUS_SCHEMA_VERSION`
966
1025
 
967
1026
  ```ts
@@ -224,3 +224,32 @@ or the command line, an attachment may name a `path` instead; `atlas report publ
224
224
  ([attach evidence](extending.md#attach-evidence)). A CTRF report already carries most of this, and
225
225
  `atlas report publish --ctrf` keeps it ([native runner reporters](runners.md) cover CodeceptJS, Mocha, Jest and Node's
226
226
  test runner).
227
+
228
+ ## Recording completeness
229
+
230
+ A green run does not say whether the videos you expected were kept and published. Atlas answers that separately from
231
+ the checks' outcomes. Mark a check with `recordingExpectation`: `"required"` (expect a video of it) or
232
+ `"not-applicable"` (an API-only or intentionally unrecorded check). A check with neither is not part of the answer.
233
+
234
+ ```json
235
+ { "id": "checkout#pays", "title": "Pays", "status": "passed", "recordingExpectation": "required",
236
+ "attachments": [{ "name": "pays.webm", "role": "video", "path": "test-results/pays.webm" }] }
237
+ ```
238
+
239
+ When any check carries an expectation, `publishChecks` and `atlas report publish` write a receipt into the layer
240
+ (`recordings`): counts of expected, uploaded, referenced (only a `uri`, which Atlas cannot vouch for), skipped and
241
+ unresolved recordings, and for each expected check its state, a reason when it is not uploaded, and the size and SHA-256
242
+ of every stored video. A video over the size limit, or a file that is missing or not allowed, is kept as an attachment
243
+ without bytes whose `omitted` says why (`too-large`, `not-found`, `not-allowed`, `over-budget`) instead of failing the
244
+ publish; it never contains a path or a token.
245
+
246
+ - `atlas report publish --format json` prints the receipt under `layer.recordings` and a summary under `recordings`.
247
+ Add `--require-recordings` to exit 1 when an expected recording is skipped or unresolved. The layer and its test
248
+ results are still written and are not changed; only the command fails, so a CI step can report the evidence gap and
249
+ retry (publishing again reuses the stored files).
250
+ - `atlas report status --format json` has `recordings`: `state` is `complete`, `incomplete`, `none-expected` or
251
+ `unknown`, with counts and each gap. It never changes `ok`. A layer without a receipt is `unknown`, never `complete`.
252
+ - The viewer shows `Recordings 2 of 3: incomplete` beside the run's origin, apart from its green or red outcomes.
253
+
254
+ This is a statement about publication. Atlas does not check that a stored video plays in a browser, and does not yet
255
+ re-check later that a stored file is still readable.
package/llms-full.txt CHANGED
@@ -1211,6 +1211,35 @@ or the command line, an attachment may name a `path` instead; `atlas report publ
1211
1211
  ([attach evidence](extending.md#attach-evidence)). A CTRF report already carries most of this, and
1212
1212
  `atlas report publish --ctrf` keeps it ([native runner reporters](runners.md) cover CodeceptJS, Mocha, Jest and Node's
1213
1213
  test runner).
1214
+
1215
+ ## Recording completeness
1216
+
1217
+ A green run does not say whether the videos you expected were kept and published. Atlas answers that separately from
1218
+ the checks' outcomes. Mark a check with `recordingExpectation`: `"required"` (expect a video of it) or
1219
+ `"not-applicable"` (an API-only or intentionally unrecorded check). A check with neither is not part of the answer.
1220
+
1221
+ ```json
1222
+ { "id": "checkout#pays", "title": "Pays", "status": "passed", "recordingExpectation": "required",
1223
+ "attachments": [{ "name": "pays.webm", "role": "video", "path": "test-results/pays.webm" }] }
1224
+ ```
1225
+
1226
+ When any check carries an expectation, `publishChecks` and `atlas report publish` write a receipt into the layer
1227
+ (`recordings`): counts of expected, uploaded, referenced (only a `uri`, which Atlas cannot vouch for), skipped and
1228
+ unresolved recordings, and for each expected check its state, a reason when it is not uploaded, and the size and SHA-256
1229
+ of every stored video. A video over the size limit, or a file that is missing or not allowed, is kept as an attachment
1230
+ without bytes whose `omitted` says why (`too-large`, `not-found`, `not-allowed`, `over-budget`) instead of failing the
1231
+ publish; it never contains a path or a token.
1232
+
1233
+ - `atlas report publish --format json` prints the receipt under `layer.recordings` and a summary under `recordings`.
1234
+ Add `--require-recordings` to exit 1 when an expected recording is skipped or unresolved. The layer and its test
1235
+ results are still written and are not changed; only the command fails, so a CI step can report the evidence gap and
1236
+ retry (publishing again reuses the stored files).
1237
+ - `atlas report status --format json` has `recordings`: `state` is `complete`, `incomplete`, `none-expected` or
1238
+ `unknown`, with counts and each gap. It never changes `ok`. A layer without a receipt is `unknown`, never `complete`.
1239
+ - The viewer shows `Recordings 2 of 3: incomplete` beside the run's origin, apart from its green or red outcomes.
1240
+
1241
+ This is a statement about publication. Atlas does not check that a stored video plays in a browser, and does not yet
1242
+ re-check later that a stored file is still readable.
1214
1243
  </doc>
1215
1244
 
1216
1245
  <doc path="docs/server.md">
@@ -4315,6 +4344,7 @@ atlas report — layered evidence for any kind of spec
4315
4344
  [--param key=value]... [--kind <k>] [--title <t>] [--recorded-at <iso|ms>]
4316
4345
  [--attach [role=]<file>]... [--label key=value]... [--link [name=]<url>]...
4317
4346
  [--attach-root <dir>]... [--max-attachment-mb <n>] [--max-total-attachment-mb <n>]
4347
+ [--require-recordings]
4318
4348
  atlas report stream [--store <dir|s3://…|https://atlas.example.com>] --producer <name> [--environment <name>]
4319
4349
  [--branch <b>] [--sha <s>] [--run-url <u>] [--kind <k>] [--param key=value]...
4320
4350
  [--run-id <id>] [--run-title <t>]
@@ -4351,6 +4381,10 @@ atlas report — layered evidence for any kind of spec
4351
4381
  Files a report names (CTRF attachments, JUnit [[ATTACHMENT|path]] lines) come from the report's own
4352
4382
  folder and each --attach-root, and never from a hidden file or a link out: a report is data from a
4353
4383
  test run, not instructions. One that is missing or not allowed is skipped with a warning.
4384
+ --require-recordings exit 1 when a check that declared recordingExpectation "required" has no
4385
+ uploaded video (absent, left out as too large or not allowed, or refused). The layer is
4386
+ still written and the checks keep their results; only this command fails. The receipt of
4387
+ what was uploaded (counts, sizes, checksums) is in the JSON result under layer.recordings.
4354
4388
  From a checkout with uncommitted changes the layer is marked "modified".
4355
4389
  stream Send checks as they finish: one JSON object per line on standard input (the fields of one
4356
4390
  check: id, title, status, and any evidence). Each second's worth becomes one layer, so a server
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crvouga/atlas",
3
- "version": "0.16.0",
3
+ "version": "0.17.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",
@@ -73,6 +73,10 @@
73
73
  "type": "number",
74
74
  "minimum": 0
75
75
  },
76
+ "recordingExpectation": {
77
+ "description": "`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",
78
+ "type": "string"
79
+ },
76
80
  "tags": {
77
81
  "description": "Free labels to filter and group by: smoke, slow, flaky…",
78
82
  "type": "array",
@@ -169,6 +173,10 @@
169
173
  "description": {
170
174
  "type": "string"
171
175
  },
176
+ "omitted": {
177
+ "description": "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\"",
178
+ "type": "string"
179
+ },
172
180
  "tags": {
173
181
  "description": "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",
174
182
  "type": "array",
@@ -404,6 +412,10 @@
404
412
  "description": {
405
413
  "type": "string"
406
414
  },
415
+ "omitted": {
416
+ "description": "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\"",
417
+ "type": "string"
418
+ },
407
419
  "tags": {
408
420
  "description": "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",
409
421
  "type": "array",
@@ -676,6 +688,10 @@
676
688
  "description": {
677
689
  "type": "string"
678
690
  },
691
+ "omitted": {
692
+ "description": "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\"",
693
+ "type": "string"
694
+ },
679
695
  "tags": {
680
696
  "description": "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",
681
697
  "type": "array",
@@ -883,6 +899,10 @@
883
899
  "description": {
884
900
  "type": "string"
885
901
  },
902
+ "omitted": {
903
+ "description": "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\"",
904
+ "type": "string"
905
+ },
886
906
  "tags": {
887
907
  "description": "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",
888
908
  "type": "array",
@@ -207,6 +207,22 @@
207
207
  "roles"
208
208
  ],
209
209
  "additionalProperties": {}
210
+ },
211
+ "recording": {
212
+ "description": "What became of the check's expected recording: uploaded, referenced, skipped, unresolved or not-applicable. Independent of `status`",
213
+ "type": "object",
214
+ "properties": {
215
+ "state": {
216
+ "type": "string"
217
+ },
218
+ "reason": {
219
+ "type": "string"
220
+ }
221
+ },
222
+ "required": [
223
+ "state"
224
+ ],
225
+ "additionalProperties": {}
210
226
  }
211
227
  },
212
228
  "required": [
@@ -481,6 +497,51 @@
481
497
  "roles"
482
498
  ],
483
499
  "additionalProperties": {}
500
+ },
501
+ "recordings": {
502
+ "description": "How many of the recordings the layer expected were published. Absent: the layer declared no expectations, so its completeness is unknown, not complete",
503
+ "type": "object",
504
+ "properties": {
505
+ "expected": {
506
+ "type": "integer",
507
+ "minimum": 0,
508
+ "maximum": 9007199254740991
509
+ },
510
+ "uploaded": {
511
+ "type": "integer",
512
+ "minimum": 0,
513
+ "maximum": 9007199254740991
514
+ },
515
+ "referenced": {
516
+ "type": "integer",
517
+ "minimum": 0,
518
+ "maximum": 9007199254740991
519
+ },
520
+ "skipped": {
521
+ "type": "integer",
522
+ "minimum": 0,
523
+ "maximum": 9007199254740991
524
+ },
525
+ "unresolved": {
526
+ "type": "integer",
527
+ "minimum": 0,
528
+ "maximum": 9007199254740991
529
+ },
530
+ "notApplicable": {
531
+ "type": "integer",
532
+ "minimum": 0,
533
+ "maximum": 9007199254740991
534
+ }
535
+ },
536
+ "required": [
537
+ "expected",
538
+ "uploaded",
539
+ "referenced",
540
+ "skipped",
541
+ "unresolved",
542
+ "notApplicable"
543
+ ],
544
+ "additionalProperties": {}
484
545
  }
485
546
  },
486
547
  "required": [
@@ -207,6 +207,22 @@
207
207
  "roles"
208
208
  ],
209
209
  "additionalProperties": {}
210
+ },
211
+ "recording": {
212
+ "description": "What became of the check's expected recording: uploaded, referenced, skipped, unresolved or not-applicable. Independent of `status`",
213
+ "type": "object",
214
+ "properties": {
215
+ "state": {
216
+ "type": "string"
217
+ },
218
+ "reason": {
219
+ "type": "string"
220
+ }
221
+ },
222
+ "required": [
223
+ "state"
224
+ ],
225
+ "additionalProperties": {}
210
226
  }
211
227
  },
212
228
  "required": [
@@ -481,6 +497,51 @@
481
497
  "roles"
482
498
  ],
483
499
  "additionalProperties": {}
500
+ },
501
+ "recordings": {
502
+ "description": "How many of the recordings the layer expected were published. Absent: the layer declared no expectations, so its completeness is unknown, not complete",
503
+ "type": "object",
504
+ "properties": {
505
+ "expected": {
506
+ "type": "integer",
507
+ "minimum": 0,
508
+ "maximum": 9007199254740991
509
+ },
510
+ "uploaded": {
511
+ "type": "integer",
512
+ "minimum": 0,
513
+ "maximum": 9007199254740991
514
+ },
515
+ "referenced": {
516
+ "type": "integer",
517
+ "minimum": 0,
518
+ "maximum": 9007199254740991
519
+ },
520
+ "skipped": {
521
+ "type": "integer",
522
+ "minimum": 0,
523
+ "maximum": 9007199254740991
524
+ },
525
+ "unresolved": {
526
+ "type": "integer",
527
+ "minimum": 0,
528
+ "maximum": 9007199254740991
529
+ },
530
+ "notApplicable": {
531
+ "type": "integer",
532
+ "minimum": 0,
533
+ "maximum": 9007199254740991
534
+ }
535
+ },
536
+ "required": [
537
+ "expected",
538
+ "uploaded",
539
+ "referenced",
540
+ "skipped",
541
+ "unresolved",
542
+ "notApplicable"
543
+ ],
544
+ "additionalProperties": {}
484
545
  }
485
546
  },
486
547
  "required": [
@@ -252,6 +252,51 @@
252
252
  "roles"
253
253
  ],
254
254
  "additionalProperties": {}
255
+ },
256
+ "recordings": {
257
+ "description": "How many of the recordings the layer expected were published. Absent: the layer declared no expectations, so its completeness is unknown, not complete",
258
+ "type": "object",
259
+ "properties": {
260
+ "expected": {
261
+ "type": "integer",
262
+ "minimum": 0,
263
+ "maximum": 9007199254740991
264
+ },
265
+ "uploaded": {
266
+ "type": "integer",
267
+ "minimum": 0,
268
+ "maximum": 9007199254740991
269
+ },
270
+ "referenced": {
271
+ "type": "integer",
272
+ "minimum": 0,
273
+ "maximum": 9007199254740991
274
+ },
275
+ "skipped": {
276
+ "type": "integer",
277
+ "minimum": 0,
278
+ "maximum": 9007199254740991
279
+ },
280
+ "unresolved": {
281
+ "type": "integer",
282
+ "minimum": 0,
283
+ "maximum": 9007199254740991
284
+ },
285
+ "notApplicable": {
286
+ "type": "integer",
287
+ "minimum": 0,
288
+ "maximum": 9007199254740991
289
+ }
290
+ },
291
+ "required": [
292
+ "expected",
293
+ "uploaded",
294
+ "referenced",
295
+ "skipped",
296
+ "unresolved",
297
+ "notApplicable"
298
+ ],
299
+ "additionalProperties": {}
255
300
  }
256
301
  },
257
302
  "required": [
@@ -198,6 +198,22 @@
198
198
  "roles"
199
199
  ],
200
200
  "additionalProperties": {}
201
+ },
202
+ "recording": {
203
+ "description": "What became of the check's expected recording: uploaded, referenced, skipped, unresolved or not-applicable. Independent of `status`",
204
+ "type": "object",
205
+ "properties": {
206
+ "state": {
207
+ "type": "string"
208
+ },
209
+ "reason": {
210
+ "type": "string"
211
+ }
212
+ },
213
+ "required": [
214
+ "state"
215
+ ],
216
+ "additionalProperties": {}
201
217
  }
202
218
  },
203
219
  "required": [