@crvouga/atlas 0.14.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.
- package/CHANGELOG.md +12 -0
- package/dist/reports/src/artifact-tag-store.d.ts +20 -0
- package/dist/reports/src/artifact-tag-store.js +70 -0
- package/dist/reports/src/artifact-tags.d.ts +96 -0
- package/dist/reports/src/artifact-tags.js +96 -0
- package/dist/reports/src/evidence-detail.d.ts +20 -3
- package/dist/reports/src/evidence-detail.js +66 -13
- package/dist/reports/src/evidence-types.d.ts +33 -0
- package/dist/reports/src/layer-merge.js +2 -2
- package/dist/reports/src/reports-explorer-route.d.ts +8 -0
- package/dist/reports/src/reports-route.d.ts +8 -0
- package/dist/reports/src/test-catalog.d.ts +35 -26
- package/dist/reports/src/test-catalog.js +79 -15
- package/dist/schema/src/api.d.ts +246 -0
- package/dist/schema/src/api.js +59 -5
- package/dist/schema/src/layer.d.ts +33 -0
- package/dist/schema/src/layer.js +11 -1
- package/dist/server/src/app.js +35 -3
- package/dist/server/src/llms.js +2 -1
- package/dist/server/src/openapi.d.ts +1 -1
- package/dist/server/src/openapi.js +20 -3
- package/docs/extending.md +3 -0
- package/docs/reference/http-api.md +52 -2
- package/docs/reference/reports.md +327 -5
- package/docs/reference/schema.md +48 -0
- package/docs/rich-evidence.md +28 -0
- package/docs/server.md +25 -1
- package/llms-full.txt +108 -3
- package/package.json +1 -1
- package/packages/schema/schemas/check-detail.schema.json +28 -0
- package/packages/schema/schemas/effective-delta.schema.json +96 -0
- package/packages/schema/schemas/effective-evidence.schema.json +96 -0
- package/packages/schema/schemas/evidence-page.schema.json +48 -0
- package/packages/schema/schemas/layer-rows.schema.json +48 -0
- package/packages/schema/schemas/layer.schema.json +70 -0
- package/packages/schema/schemas/publish-checks.schema.json +35 -0
- package/packages/schema/schemas/report-run.schema.json +71 -0
- package/packages/schema/schemas/report-runs.schema.json +38 -1
- package/packages/schema/schemas/test-catalog.schema.json +83 -0
- package/packages/schema/schemas/test-history.schema.json +110 -0
- package/packages/server/openapi.json +1259 -33
- package/packages/visualizer/src/evidence/artifact-tags.tsx +285 -0
- package/packages/visualizer/src/evidence/artifacts.tsx +18 -12
- package/packages/visualizer/src/explorer/RunsView.tsx +128 -10
- package/packages/visualizer/src/explorer/catalog.tsx +16 -6
- package/packages/visualizer/src/explorer/search.ts +4 -1
package/dist/schema/src/api.d.ts
CHANGED
|
@@ -80,6 +80,21 @@ export declare const BackendInfoSchema: z.ZodObject<{
|
|
|
80
80
|
live: z.ZodBoolean;
|
|
81
81
|
available: z.ZodBoolean;
|
|
82
82
|
}, z.core.$loose>;
|
|
83
|
+
/** One reference to a video held by a layer, check, retry attempt or step, found by the attachment's effective media type. */
|
|
84
|
+
export declare const VideoRefSchema: z.ZodObject<{
|
|
85
|
+
name: z.ZodString;
|
|
86
|
+
owner: z.ZodString;
|
|
87
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
step: z.ZodOptional<z.ZodString>;
|
|
89
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
90
|
+
available: z.ZodBoolean;
|
|
91
|
+
}, z.core.$loose>;
|
|
92
|
+
/** Video references as counts: how many are referenced, how many distinct recordings can be played, how many cannot. */
|
|
93
|
+
export declare const VideoCountsSchema: z.ZodObject<{
|
|
94
|
+
references: z.ZodNumber;
|
|
95
|
+
recordings: z.ZodNumber;
|
|
96
|
+
unavailable: z.ZodNumber;
|
|
97
|
+
}, z.core.$loose>;
|
|
83
98
|
/** What a result carries beyond its outcome, as counts and short facts. Present only when there is something. */
|
|
84
99
|
export declare const EvidenceSummarySchema: z.ZodObject<{
|
|
85
100
|
attachments: z.ZodNumber;
|
|
@@ -88,8 +103,17 @@ export declare const EvidenceSummarySchema: z.ZodObject<{
|
|
|
88
103
|
attempts: z.ZodNumber;
|
|
89
104
|
links: z.ZodNumber;
|
|
90
105
|
tags: z.ZodArray<z.ZodString>;
|
|
106
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
91
107
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
92
108
|
roles: z.ZodArray<z.ZodString>;
|
|
109
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
110
|
+
name: z.ZodString;
|
|
111
|
+
owner: z.ZodString;
|
|
112
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
113
|
+
step: z.ZodOptional<z.ZodString>;
|
|
114
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
115
|
+
available: z.ZodBoolean;
|
|
116
|
+
}, z.core.$loose>>>;
|
|
93
117
|
}, z.core.$loose>;
|
|
94
118
|
/** A layer as the report shows it: its origin and its checks by status. */
|
|
95
119
|
export declare const LayerHeaderSchema: z.ZodObject<{
|
|
@@ -129,8 +153,17 @@ export declare const LayerHeaderSchema: z.ZodObject<{
|
|
|
129
153
|
attempts: z.ZodNumber;
|
|
130
154
|
links: z.ZodNumber;
|
|
131
155
|
tags: z.ZodArray<z.ZodString>;
|
|
156
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
132
157
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
133
158
|
roles: z.ZodArray<z.ZodString>;
|
|
159
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
160
|
+
name: z.ZodString;
|
|
161
|
+
owner: z.ZodString;
|
|
162
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
163
|
+
step: z.ZodOptional<z.ZodString>;
|
|
164
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
165
|
+
available: z.ZodBoolean;
|
|
166
|
+
}, z.core.$loose>>>;
|
|
134
167
|
}, z.core.$loose>>;
|
|
135
168
|
}, z.core.$loose>;
|
|
136
169
|
/** One check of a layer as the report shows it. */
|
|
@@ -162,8 +195,17 @@ export declare const LayerRowSchema: z.ZodObject<{
|
|
|
162
195
|
attempts: z.ZodNumber;
|
|
163
196
|
links: z.ZodNumber;
|
|
164
197
|
tags: z.ZodArray<z.ZodString>;
|
|
198
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
165
199
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
166
200
|
roles: z.ZodArray<z.ZodString>;
|
|
201
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
202
|
+
name: z.ZodString;
|
|
203
|
+
owner: z.ZodString;
|
|
204
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
205
|
+
step: z.ZodOptional<z.ZodString>;
|
|
206
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
207
|
+
available: z.ZodBoolean;
|
|
208
|
+
}, z.core.$loose>>>;
|
|
167
209
|
}, z.core.$loose>>;
|
|
168
210
|
}, z.core.$loose>;
|
|
169
211
|
/** A layer with its checks: the rows of one layer, read apart from its header. */
|
|
@@ -197,8 +239,17 @@ export declare const LayerRowsSchema: z.ZodObject<{
|
|
|
197
239
|
attempts: z.ZodNumber;
|
|
198
240
|
links: z.ZodNumber;
|
|
199
241
|
tags: z.ZodArray<z.ZodString>;
|
|
242
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
200
243
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
201
244
|
roles: z.ZodArray<z.ZodString>;
|
|
245
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
246
|
+
name: z.ZodString;
|
|
247
|
+
owner: z.ZodString;
|
|
248
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
249
|
+
step: z.ZodOptional<z.ZodString>;
|
|
250
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
251
|
+
available: z.ZodBoolean;
|
|
252
|
+
}, z.core.$loose>>>;
|
|
202
253
|
}, z.core.$loose>>;
|
|
203
254
|
}, z.core.$loose>>;
|
|
204
255
|
fingerprints: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -234,8 +285,17 @@ export declare const LayerEvidenceSchema: z.ZodObject<{
|
|
|
234
285
|
attempts: z.ZodNumber;
|
|
235
286
|
links: z.ZodNumber;
|
|
236
287
|
tags: z.ZodArray<z.ZodString>;
|
|
288
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
237
289
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
238
290
|
roles: z.ZodArray<z.ZodString>;
|
|
291
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
292
|
+
name: z.ZodString;
|
|
293
|
+
owner: z.ZodString;
|
|
294
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
295
|
+
step: z.ZodOptional<z.ZodString>;
|
|
296
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
297
|
+
available: z.ZodBoolean;
|
|
298
|
+
}, z.core.$loose>>>;
|
|
239
299
|
}, z.core.$loose>>;
|
|
240
300
|
}, z.core.$loose>>;
|
|
241
301
|
fingerprints: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -276,8 +336,17 @@ export declare const LayerEvidenceSchema: z.ZodObject<{
|
|
|
276
336
|
attempts: z.ZodNumber;
|
|
277
337
|
links: z.ZodNumber;
|
|
278
338
|
tags: z.ZodArray<z.ZodString>;
|
|
339
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
279
340
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
280
341
|
roles: z.ZodArray<z.ZodString>;
|
|
342
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
343
|
+
name: z.ZodString;
|
|
344
|
+
owner: z.ZodString;
|
|
345
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
346
|
+
step: z.ZodOptional<z.ZodString>;
|
|
347
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
348
|
+
available: z.ZodBoolean;
|
|
349
|
+
}, z.core.$loose>>>;
|
|
281
350
|
}, z.core.$loose>>;
|
|
282
351
|
}, z.core.$loose>;
|
|
283
352
|
}, z.core.$loose>;
|
|
@@ -318,8 +387,17 @@ export declare const EffectiveEvidenceSchema: z.ZodObject<{
|
|
|
318
387
|
attempts: z.ZodNumber;
|
|
319
388
|
links: z.ZodNumber;
|
|
320
389
|
tags: z.ZodArray<z.ZodString>;
|
|
390
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
321
391
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
322
392
|
roles: z.ZodArray<z.ZodString>;
|
|
393
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
394
|
+
name: z.ZodString;
|
|
395
|
+
owner: z.ZodString;
|
|
396
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
397
|
+
step: z.ZodOptional<z.ZodString>;
|
|
398
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
399
|
+
available: z.ZodBoolean;
|
|
400
|
+
}, z.core.$loose>>>;
|
|
323
401
|
}, z.core.$loose>>;
|
|
324
402
|
}, z.core.$loose>>;
|
|
325
403
|
fingerprints: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -360,8 +438,17 @@ export declare const EffectiveEvidenceSchema: z.ZodObject<{
|
|
|
360
438
|
attempts: z.ZodNumber;
|
|
361
439
|
links: z.ZodNumber;
|
|
362
440
|
tags: z.ZodArray<z.ZodString>;
|
|
441
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
363
442
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
364
443
|
roles: z.ZodArray<z.ZodString>;
|
|
444
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
445
|
+
name: z.ZodString;
|
|
446
|
+
owner: z.ZodString;
|
|
447
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
448
|
+
step: z.ZodOptional<z.ZodString>;
|
|
449
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
450
|
+
available: z.ZodBoolean;
|
|
451
|
+
}, z.core.$loose>>>;
|
|
365
452
|
}, z.core.$loose>>;
|
|
366
453
|
}, z.core.$loose>;
|
|
367
454
|
}, z.core.$loose>>;
|
|
@@ -423,8 +510,17 @@ export declare const EffectiveDeltaSchema: z.ZodObject<{
|
|
|
423
510
|
attempts: z.ZodNumber;
|
|
424
511
|
links: z.ZodNumber;
|
|
425
512
|
tags: z.ZodArray<z.ZodString>;
|
|
513
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
426
514
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
427
515
|
roles: z.ZodArray<z.ZodString>;
|
|
516
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
517
|
+
name: z.ZodString;
|
|
518
|
+
owner: z.ZodString;
|
|
519
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
520
|
+
step: z.ZodOptional<z.ZodString>;
|
|
521
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
522
|
+
available: z.ZodBoolean;
|
|
523
|
+
}, z.core.$loose>>>;
|
|
428
524
|
}, z.core.$loose>>;
|
|
429
525
|
}, z.core.$loose>>;
|
|
430
526
|
fingerprints: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -465,8 +561,17 @@ export declare const EffectiveDeltaSchema: z.ZodObject<{
|
|
|
465
561
|
attempts: z.ZodNumber;
|
|
466
562
|
links: z.ZodNumber;
|
|
467
563
|
tags: z.ZodArray<z.ZodString>;
|
|
564
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
468
565
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
469
566
|
roles: z.ZodArray<z.ZodString>;
|
|
567
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
568
|
+
name: z.ZodString;
|
|
569
|
+
owner: z.ZodString;
|
|
570
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
571
|
+
step: z.ZodOptional<z.ZodString>;
|
|
572
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
573
|
+
available: z.ZodBoolean;
|
|
574
|
+
}, z.core.$loose>>>;
|
|
470
575
|
}, z.core.$loose>>;
|
|
471
576
|
}, z.core.$loose>;
|
|
472
577
|
}, z.core.$loose>>;
|
|
@@ -531,8 +636,17 @@ export declare const EvidencePageSchema: z.ZodObject<{
|
|
|
531
636
|
attempts: z.ZodNumber;
|
|
532
637
|
links: z.ZodNumber;
|
|
533
638
|
tags: z.ZodArray<z.ZodString>;
|
|
639
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
534
640
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
535
641
|
roles: z.ZodArray<z.ZodString>;
|
|
642
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
643
|
+
name: z.ZodString;
|
|
644
|
+
owner: z.ZodString;
|
|
645
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
646
|
+
step: z.ZodOptional<z.ZodString>;
|
|
647
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
648
|
+
available: z.ZodBoolean;
|
|
649
|
+
}, z.core.$loose>>>;
|
|
536
650
|
}, z.core.$loose>>;
|
|
537
651
|
}, z.core.$loose>>;
|
|
538
652
|
cursor: z.ZodNullable<z.ZodString>;
|
|
@@ -573,6 +687,7 @@ export declare const CheckDetailSchema: z.ZodObject<{
|
|
|
573
687
|
height: z.ZodOptional<z.ZodNumber>;
|
|
574
688
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
575
689
|
description: z.ZodOptional<z.ZodString>;
|
|
690
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
576
691
|
at: z.ZodOptional<z.ZodObject<{
|
|
577
692
|
step: z.ZodOptional<z.ZodString>;
|
|
578
693
|
offsetMs: z.ZodOptional<z.ZodNumber>;
|
|
@@ -637,6 +752,7 @@ export declare const CheckDetailSchema: z.ZodObject<{
|
|
|
637
752
|
height: z.ZodOptional<z.ZodNumber>;
|
|
638
753
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
639
754
|
description: z.ZodOptional<z.ZodString>;
|
|
755
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
640
756
|
at: z.ZodOptional<z.ZodObject<{
|
|
641
757
|
step: z.ZodOptional<z.ZodString>;
|
|
642
758
|
offsetMs: z.ZodOptional<z.ZodNumber>;
|
|
@@ -681,6 +797,7 @@ export declare const CheckDetailSchema: z.ZodObject<{
|
|
|
681
797
|
height: z.ZodOptional<z.ZodNumber>;
|
|
682
798
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
683
799
|
description: z.ZodOptional<z.ZodString>;
|
|
800
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
684
801
|
at: z.ZodOptional<z.ZodObject<{
|
|
685
802
|
step: z.ZodOptional<z.ZodString>;
|
|
686
803
|
offsetMs: z.ZodOptional<z.ZodNumber>;
|
|
@@ -732,6 +849,7 @@ export declare const CheckDetailSchema: z.ZodObject<{
|
|
|
732
849
|
height: z.ZodOptional<z.ZodNumber>;
|
|
733
850
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
734
851
|
description: z.ZodOptional<z.ZodString>;
|
|
852
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
735
853
|
at: z.ZodOptional<z.ZodObject<{
|
|
736
854
|
step: z.ZodOptional<z.ZodString>;
|
|
737
855
|
offsetMs: z.ZodOptional<z.ZodNumber>;
|
|
@@ -799,6 +917,55 @@ export declare const ChecksResultSchema: z.ZodObject<{
|
|
|
799
917
|
id: z.ZodString;
|
|
800
918
|
checks: z.ZodNumber;
|
|
801
919
|
}, z.core.$loose>;
|
|
920
|
+
/** Which attachment a reviewer's tags belong to: one attachment of one check of one archived layer. */
|
|
921
|
+
export declare const ArtifactTargetSchema: z.ZodObject<{
|
|
922
|
+
layer: z.ZodString;
|
|
923
|
+
check: z.ZodString;
|
|
924
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
925
|
+
artifact: z.ZodString;
|
|
926
|
+
}, z.core.$loose>;
|
|
927
|
+
/** The body of `POST /api/reports/artifact-tags`: tags to add to and to remove from one attachment. At least one tag overall. */
|
|
928
|
+
export declare const ArtifactTagEditSchema: z.ZodObject<{
|
|
929
|
+
target: z.ZodObject<{
|
|
930
|
+
layer: z.ZodString;
|
|
931
|
+
check: z.ZodString;
|
|
932
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
933
|
+
artifact: z.ZodString;
|
|
934
|
+
}, z.core.$loose>;
|
|
935
|
+
add: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
936
|
+
remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
937
|
+
}, z.core.$loose>;
|
|
938
|
+
/** One recorded edit of an attachment's reviewer tags. Entries are never changed or removed: they are the audit trail. */
|
|
939
|
+
export declare const ArtifactTagEntrySchema: z.ZodObject<{
|
|
940
|
+
id: z.ZodString;
|
|
941
|
+
target: z.ZodObject<{
|
|
942
|
+
layer: z.ZodString;
|
|
943
|
+
check: z.ZodString;
|
|
944
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
945
|
+
artifact: z.ZodString;
|
|
946
|
+
}, z.core.$loose>;
|
|
947
|
+
add: z.ZodArray<z.ZodString>;
|
|
948
|
+
remove: z.ZodArray<z.ZodString>;
|
|
949
|
+
by: z.ZodString;
|
|
950
|
+
atMs: z.ZodNumber;
|
|
951
|
+
}, z.core.$loose>;
|
|
952
|
+
/** `GET /api/reports/artifact-tags`: every recorded edit, oldest first. Fold them with `foldArtifactTags`. */
|
|
953
|
+
export declare const ArtifactTagsSchema: z.ZodObject<{
|
|
954
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
955
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
956
|
+
id: z.ZodString;
|
|
957
|
+
target: z.ZodObject<{
|
|
958
|
+
layer: z.ZodString;
|
|
959
|
+
check: z.ZodString;
|
|
960
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
961
|
+
artifact: z.ZodString;
|
|
962
|
+
}, z.core.$loose>;
|
|
963
|
+
add: z.ZodArray<z.ZodString>;
|
|
964
|
+
remove: z.ZodArray<z.ZodString>;
|
|
965
|
+
by: z.ZodString;
|
|
966
|
+
atMs: z.ZodNumber;
|
|
967
|
+
}, z.core.$loose>>;
|
|
968
|
+
}, z.core.$loose>;
|
|
802
969
|
/** The data of the `hello` event: sent first on `/api/events`. */
|
|
803
970
|
export declare const HelloEventSchema: z.ZodObject<{
|
|
804
971
|
version: z.ZodString;
|
|
@@ -856,8 +1023,17 @@ export declare const TestResultEntrySchema: z.ZodObject<{
|
|
|
856
1023
|
attempts: z.ZodNumber;
|
|
857
1024
|
links: z.ZodNumber;
|
|
858
1025
|
tags: z.ZodArray<z.ZodString>;
|
|
1026
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
859
1027
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
860
1028
|
roles: z.ZodArray<z.ZodString>;
|
|
1029
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1030
|
+
name: z.ZodString;
|
|
1031
|
+
owner: z.ZodString;
|
|
1032
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
1033
|
+
step: z.ZodOptional<z.ZodString>;
|
|
1034
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
1035
|
+
available: z.ZodBoolean;
|
|
1036
|
+
}, z.core.$loose>>>;
|
|
861
1037
|
}, z.core.$loose>>;
|
|
862
1038
|
}, z.core.$loose>;
|
|
863
1039
|
/** One test of the catalog: what it is, its current result per environment, and how it has gone over its recorded history. */
|
|
@@ -907,8 +1083,17 @@ export declare const TestSummarySchema: z.ZodObject<{
|
|
|
907
1083
|
attempts: z.ZodNumber;
|
|
908
1084
|
links: z.ZodNumber;
|
|
909
1085
|
tags: z.ZodArray<z.ZodString>;
|
|
1086
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
910
1087
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
911
1088
|
roles: z.ZodArray<z.ZodString>;
|
|
1089
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1090
|
+
name: z.ZodString;
|
|
1091
|
+
owner: z.ZodString;
|
|
1092
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
1093
|
+
step: z.ZodOptional<z.ZodString>;
|
|
1094
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
1095
|
+
available: z.ZodBoolean;
|
|
1096
|
+
}, z.core.$loose>>>;
|
|
912
1097
|
}, z.core.$loose>>;
|
|
913
1098
|
}, z.core.$loose>>;
|
|
914
1099
|
stats: z.ZodObject<{
|
|
@@ -937,6 +1122,8 @@ export declare const TestSummarySchema: z.ZodObject<{
|
|
|
937
1122
|
branches: z.ZodArray<z.ZodString>;
|
|
938
1123
|
}, z.core.$loose>;
|
|
939
1124
|
tags: z.ZodArray<z.ZodString>;
|
|
1125
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1126
|
+
inheritedArtifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
940
1127
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
941
1128
|
evidence: z.ZodObject<{
|
|
942
1129
|
attachments: z.ZodNumber;
|
|
@@ -1084,6 +1271,10 @@ export declare const TestCatalogSchema: z.ZodObject<{
|
|
|
1084
1271
|
value: z.ZodString;
|
|
1085
1272
|
count: z.ZodNumber;
|
|
1086
1273
|
}, z.core.$loose>>;
|
|
1274
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1275
|
+
value: z.ZodString;
|
|
1276
|
+
count: z.ZodNumber;
|
|
1277
|
+
}, z.core.$loose>>>;
|
|
1087
1278
|
branches: z.ZodArray<z.ZodObject<{
|
|
1088
1279
|
value: z.ZodString;
|
|
1089
1280
|
count: z.ZodNumber;
|
|
@@ -1142,8 +1333,17 @@ export declare const TestCatalogSchema: z.ZodObject<{
|
|
|
1142
1333
|
attempts: z.ZodNumber;
|
|
1143
1334
|
links: z.ZodNumber;
|
|
1144
1335
|
tags: z.ZodArray<z.ZodString>;
|
|
1336
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1145
1337
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1146
1338
|
roles: z.ZodArray<z.ZodString>;
|
|
1339
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1340
|
+
name: z.ZodString;
|
|
1341
|
+
owner: z.ZodString;
|
|
1342
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
1343
|
+
step: z.ZodOptional<z.ZodString>;
|
|
1344
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
1345
|
+
available: z.ZodBoolean;
|
|
1346
|
+
}, z.core.$loose>>>;
|
|
1147
1347
|
}, z.core.$loose>>;
|
|
1148
1348
|
}, z.core.$loose>>;
|
|
1149
1349
|
stats: z.ZodObject<{
|
|
@@ -1172,6 +1372,8 @@ export declare const TestCatalogSchema: z.ZodObject<{
|
|
|
1172
1372
|
branches: z.ZodArray<z.ZodString>;
|
|
1173
1373
|
}, z.core.$loose>;
|
|
1174
1374
|
tags: z.ZodArray<z.ZodString>;
|
|
1375
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1376
|
+
inheritedArtifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1175
1377
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1176
1378
|
evidence: z.ZodObject<{
|
|
1177
1379
|
attachments: z.ZodNumber;
|
|
@@ -1312,8 +1514,17 @@ export declare const TestHistorySchema: z.ZodObject<{
|
|
|
1312
1514
|
attempts: z.ZodNumber;
|
|
1313
1515
|
links: z.ZodNumber;
|
|
1314
1516
|
tags: z.ZodArray<z.ZodString>;
|
|
1517
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1315
1518
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1316
1519
|
roles: z.ZodArray<z.ZodString>;
|
|
1520
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1521
|
+
name: z.ZodString;
|
|
1522
|
+
owner: z.ZodString;
|
|
1523
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
1524
|
+
step: z.ZodOptional<z.ZodString>;
|
|
1525
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
1526
|
+
available: z.ZodBoolean;
|
|
1527
|
+
}, z.core.$loose>>>;
|
|
1317
1528
|
}, z.core.$loose>>;
|
|
1318
1529
|
}, z.core.$loose>>;
|
|
1319
1530
|
stats: z.ZodObject<{
|
|
@@ -1342,6 +1553,8 @@ export declare const TestHistorySchema: z.ZodObject<{
|
|
|
1342
1553
|
branches: z.ZodArray<z.ZodString>;
|
|
1343
1554
|
}, z.core.$loose>;
|
|
1344
1555
|
tags: z.ZodArray<z.ZodString>;
|
|
1556
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1557
|
+
inheritedArtifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1345
1558
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1346
1559
|
evidence: z.ZodObject<{
|
|
1347
1560
|
attachments: z.ZodNumber;
|
|
@@ -1379,8 +1592,17 @@ export declare const TestHistorySchema: z.ZodObject<{
|
|
|
1379
1592
|
attempts: z.ZodNumber;
|
|
1380
1593
|
links: z.ZodNumber;
|
|
1381
1594
|
tags: z.ZodArray<z.ZodString>;
|
|
1595
|
+
artifactTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1382
1596
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1383
1597
|
roles: z.ZodArray<z.ZodString>;
|
|
1598
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1599
|
+
name: z.ZodString;
|
|
1600
|
+
owner: z.ZodString;
|
|
1601
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
1602
|
+
step: z.ZodOptional<z.ZodString>;
|
|
1603
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
1604
|
+
available: z.ZodBoolean;
|
|
1605
|
+
}, z.core.$loose>>>;
|
|
1384
1606
|
}, z.core.$loose>>;
|
|
1385
1607
|
}, z.core.$loose>>;
|
|
1386
1608
|
}, z.core.$loose>;
|
|
@@ -1416,6 +1638,11 @@ export declare const ReportRunSchema: z.ZodObject<{
|
|
|
1416
1638
|
environment: z.ZodNullable<z.ZodString>;
|
|
1417
1639
|
detail: z.ZodString;
|
|
1418
1640
|
}, z.core.$loose>>;
|
|
1641
|
+
videos: z.ZodOptional<z.ZodObject<{
|
|
1642
|
+
references: z.ZodNumber;
|
|
1643
|
+
recordings: z.ZodNumber;
|
|
1644
|
+
unavailable: z.ZodNumber;
|
|
1645
|
+
}, z.core.$loose>>;
|
|
1419
1646
|
}, z.core.$loose>;
|
|
1420
1647
|
/** `GET /api/reports/runs`: runs, newest first. */
|
|
1421
1648
|
export declare const RunListSchema: z.ZodObject<{
|
|
@@ -1453,7 +1680,13 @@ export declare const RunListSchema: z.ZodObject<{
|
|
|
1453
1680
|
environment: z.ZodNullable<z.ZodString>;
|
|
1454
1681
|
detail: z.ZodString;
|
|
1455
1682
|
}, z.core.$loose>>;
|
|
1683
|
+
videos: z.ZodOptional<z.ZodObject<{
|
|
1684
|
+
references: z.ZodNumber;
|
|
1685
|
+
recordings: z.ZodNumber;
|
|
1686
|
+
unavailable: z.ZodNumber;
|
|
1687
|
+
}, z.core.$loose>>;
|
|
1456
1688
|
}, z.core.$loose>>;
|
|
1689
|
+
withVideo: z.ZodOptional<z.ZodNumber>;
|
|
1457
1690
|
}, z.core.$loose>;
|
|
1458
1691
|
/** `GET /api/reports/runs/detail`: one run and its last result for every test, environment and producer it recorded. */
|
|
1459
1692
|
export declare const RunDetailSchema: z.ZodObject<{
|
|
@@ -1490,6 +1723,11 @@ export declare const RunDetailSchema: z.ZodObject<{
|
|
|
1490
1723
|
environment: z.ZodNullable<z.ZodString>;
|
|
1491
1724
|
detail: z.ZodString;
|
|
1492
1725
|
}, z.core.$loose>>;
|
|
1726
|
+
videos: z.ZodOptional<z.ZodObject<{
|
|
1727
|
+
references: z.ZodNumber;
|
|
1728
|
+
recordings: z.ZodNumber;
|
|
1729
|
+
unavailable: z.ZodNumber;
|
|
1730
|
+
}, z.core.$loose>>;
|
|
1493
1731
|
}, z.core.$loose>;
|
|
1494
1732
|
results: z.ZodArray<z.ZodObject<{
|
|
1495
1733
|
key: z.ZodString;
|
|
@@ -1508,5 +1746,13 @@ export declare const RunDetailSchema: z.ZodObject<{
|
|
|
1508
1746
|
at: z.ZodNumber;
|
|
1509
1747
|
layer: z.ZodString;
|
|
1510
1748
|
detail: z.ZodString;
|
|
1749
|
+
videos: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1750
|
+
name: z.ZodString;
|
|
1751
|
+
owner: z.ZodString;
|
|
1752
|
+
attempt: z.ZodOptional<z.ZodNumber>;
|
|
1753
|
+
step: z.ZodOptional<z.ZodString>;
|
|
1754
|
+
recording: z.ZodOptional<z.ZodString>;
|
|
1755
|
+
available: z.ZodBoolean;
|
|
1756
|
+
}, z.core.$loose>>>;
|
|
1511
1757
|
}, z.core.$loose>>;
|
|
1512
1758
|
}, z.core.$loose>;
|
package/dist/schema/src/api.js
CHANGED
|
@@ -62,6 +62,21 @@ export const BackendInfoSchema = z.looseObject({
|
|
|
62
62
|
live: z.boolean().describe('Always false on a server'),
|
|
63
63
|
available: z.boolean().describe('False when the backend could not be read; its results are then unknown, never passed')
|
|
64
64
|
});
|
|
65
|
+
/** One reference to a video held by a layer, check, retry attempt or step, found by the attachment's effective media type. */
|
|
66
|
+
export const VideoRefSchema = z.looseObject({
|
|
67
|
+
name: z.string().describe('The attachment name'),
|
|
68
|
+
owner: z.string().describe('Who holds it: `layer`, `check`, `attempt` or `step`. An open vocabulary: treat an unknown owner as a check'),
|
|
69
|
+
attempt: z.number().int().nonnegative().optional().describe('The retry attempt that holds it, or that holds the step that does'),
|
|
70
|
+
step: z.string().optional().describe('The name of the step that holds it'),
|
|
71
|
+
recording: z.string().optional().describe('What identifies the bytes; references with the same value are one recording. Absent when it cannot be played'),
|
|
72
|
+
available: z.boolean().describe('False when the reference names no bytes (no bundle key, address or inline text)')
|
|
73
|
+
});
|
|
74
|
+
/** Video references as counts: how many are referenced, how many distinct recordings can be played, how many cannot. */
|
|
75
|
+
export const VideoCountsSchema = z.looseObject({
|
|
76
|
+
references: z.number().int().nonnegative().describe('Every reference to a video; identical bytes referenced twice count twice'),
|
|
77
|
+
recordings: z.number().int().nonnegative().describe('Distinct playable recordings'),
|
|
78
|
+
unavailable: z.number().int().nonnegative().describe('References that name no bytes')
|
|
79
|
+
});
|
|
65
80
|
/** What a result carries beyond its outcome, as counts and short facts. Present only when there is something. */
|
|
66
81
|
export const EvidenceSummarySchema = z.looseObject({
|
|
67
82
|
attachments: z.number().int().nonnegative(),
|
|
@@ -70,8 +85,10 @@ export const EvidenceSummarySchema = z.looseObject({
|
|
|
70
85
|
attempts: z.number().int().nonnegative(),
|
|
71
86
|
links: z.number().int().nonnegative(),
|
|
72
87
|
tags: z.array(z.string()),
|
|
88
|
+
artifactTags: z.array(z.string()).optional().describe('Normalized tags of the attachments themselves, sorted and distinct. Absent when no attachment is tagged; never inherited from a check or run'),
|
|
73
89
|
labels: z.record(z.string(), z.string()),
|
|
74
|
-
roles: z.array(z.string())
|
|
90
|
+
roles: z.array(z.string()),
|
|
91
|
+
videos: z.array(VideoRefSchema).optional().describe('Its references to videos and who holds each. Absent when it has none, and in reports written before this was recorded')
|
|
75
92
|
});
|
|
76
93
|
/** A layer as the report shows it: its origin and its checks by status. */
|
|
77
94
|
export const LayerHeaderSchema = z.looseObject({
|
|
@@ -186,6 +203,33 @@ export const ChecksResultSchema = z.looseObject({
|
|
|
186
203
|
id: z.string().describe('The layer id'),
|
|
187
204
|
checks: z.number().int().nonnegative()
|
|
188
205
|
});
|
|
206
|
+
/** Which attachment a reviewer's tags belong to: one attachment of one check of one archived layer. */
|
|
207
|
+
export const ArtifactTargetSchema = z.looseObject({
|
|
208
|
+
layer: z.string().regex(/^[0-9a-f]{64}$/).describe('The id of the archived layer that holds the check'),
|
|
209
|
+
check: z.string().min(1).describe('The check\'s id'),
|
|
210
|
+
kind: z.string().min(1).optional().describe('The kind of the part holding the check, when the same id exists in several parts'),
|
|
211
|
+
artifact: z.string().min(1).max(1024).describe('The attachment: `id:<id>` when it has an id, else `key:<bundleKey>`, else `name:<name>` (see `artifactRef`)')
|
|
212
|
+
});
|
|
213
|
+
/** The body of `POST /api/reports/artifact-tags`: tags to add to and to remove from one attachment. At least one tag overall. */
|
|
214
|
+
export const ArtifactTagEditSchema = z.looseObject({
|
|
215
|
+
target: ArtifactTargetSchema,
|
|
216
|
+
add: z.array(z.string()).max(20).optional().describe('Tags to add. `demo` and `#demo` are the same tag'),
|
|
217
|
+
remove: z.array(z.string()).max(20).optional().describe('Reviewer tags to remove. Tags the producer wrote are part of the immutable layer and stay')
|
|
218
|
+
});
|
|
219
|
+
/** One recorded edit of an attachment's reviewer tags. Entries are never changed or removed: they are the audit trail. */
|
|
220
|
+
export const ArtifactTagEntrySchema = z.looseObject({
|
|
221
|
+
id: z.string().describe('Unique and time-ordered'),
|
|
222
|
+
target: ArtifactTargetSchema,
|
|
223
|
+
add: z.array(z.string()).describe('Normalized tags added'),
|
|
224
|
+
remove: z.array(z.string()).describe('Normalized tags removed'),
|
|
225
|
+
by: z.string().describe('The name of the token that made the edit (never the token)'),
|
|
226
|
+
atMs: z.number().describe('When the server recorded it, epoch milliseconds')
|
|
227
|
+
});
|
|
228
|
+
/** `GET /api/reports/artifact-tags`: every recorded edit, oldest first. Fold them with `foldArtifactTags`. */
|
|
229
|
+
export const ArtifactTagsSchema = z.looseObject({
|
|
230
|
+
schemaVersion: z.literal(1),
|
|
231
|
+
entries: z.array(ArtifactTagEntrySchema)
|
|
232
|
+
});
|
|
189
233
|
/** The data of the `hello` event: sent first on `/api/events`. */
|
|
190
234
|
export const HelloEventSchema = z.looseObject({ version: z.string(), ready: z.boolean(), time: z.number(), heartbeatMs: z.number().positive().optional() });
|
|
191
235
|
/** The data of the `report` event: layers arrived. Enough to say who sent what, without asking. */
|
|
@@ -243,6 +287,8 @@ export const TestSummarySchema = z.looseObject({
|
|
|
243
287
|
runs: z.number().int().nonnegative(), branches: z.array(z.string())
|
|
244
288
|
}),
|
|
245
289
|
tags: z.array(z.string()),
|
|
290
|
+
artifactTags: z.array(z.string()).optional().describe('Normalized tags of the attachments of its current results, such as `demo` (shown `#demo`). Not inherited from a check or run, unlike `tags`'),
|
|
291
|
+
inheritedArtifactTags: z.array(z.string()).optional().describe('Normalized tags its attachments inherit from their check and run, apart from `artifactTags`: what `?artifactTag=…&inherited=1` also matches'),
|
|
246
292
|
labels: z.record(z.string(), z.string()),
|
|
247
293
|
evidence: z.looseObject({ attachments: z.number().int().nonnegative(), steps: z.number().int().nonnegative(), attempts: z.number().int().nonnegative(), roles: z.array(z.string()) }),
|
|
248
294
|
lastRecordedAtMs: z.number(),
|
|
@@ -269,7 +315,7 @@ export const TestCatalogSchema = z.looseObject({
|
|
|
269
315
|
facets: z.looseObject({
|
|
270
316
|
statuses: z.array(FacetValueSchema), environments: z.array(FacetValueSchema), producers: z.array(FacetValueSchema), domains: z.array(FacetValueSchema),
|
|
271
317
|
specs: z.array(CatalogSpecSchema.extend({ tests: z.number().int().nonnegative(), counts: StatusCountsSchema })),
|
|
272
|
-
tags: z.array(FacetValueSchema), branches: z.array(FacetValueSchema), labels: z.record(z.string(), z.array(FacetValueSchema))
|
|
318
|
+
tags: z.array(FacetValueSchema), artifactTags: z.array(FacetValueSchema).optional(), branches: z.array(FacetValueSchema), labels: z.record(z.string(), z.array(FacetValueSchema))
|
|
273
319
|
}),
|
|
274
320
|
total: z.number().int().nonnegative().describe('Tests the query matched, before offset and limit'),
|
|
275
321
|
offset: z.number().int().nonnegative(),
|
|
@@ -344,10 +390,17 @@ export const ReportRunSchema = z.looseObject({
|
|
|
344
390
|
producers: z.array(z.string()), environments: z.array(z.string()),
|
|
345
391
|
layers: z.number().int().nonnegative(), tests: z.number().int().nonnegative(), counts: StatusCountsSchema,
|
|
346
392
|
totalDurationMs: z.number().nullable(),
|
|
347
|
-
failing: z.array(z.looseObject({ key: z.string(), title: z.string(), environment: z.string().nullable(), detail: z.string() }))
|
|
393
|
+
failing: z.array(z.looseObject({ key: z.string(), title: z.string(), environment: z.string().nullable(), detail: z.string() })),
|
|
394
|
+
videos: VideoCountsSchema.optional().describe('Its videos, from its layers and the last result of each test. Absent when it has none or the report carries no video information')
|
|
348
395
|
});
|
|
349
396
|
/** `GET /api/reports/runs`: runs, newest first. */
|
|
350
|
-
export const RunListSchema = z.looseObject({
|
|
397
|
+
export const RunListSchema = z.looseObject({
|
|
398
|
+
schemaVersion: z.literal(1),
|
|
399
|
+
version: z.string(),
|
|
400
|
+
total: z.number().int().nonnegative().describe('Runs that matched, before `limit`'),
|
|
401
|
+
runs: z.array(ReportRunSchema),
|
|
402
|
+
withVideo: z.number().int().nonnegative().optional().describe('How many of all runs (before `video` and `limit`) have a playable video recording')
|
|
403
|
+
});
|
|
351
404
|
/** `GET /api/reports/runs/detail`: one run and its last result for every test, environment and producer it recorded. */
|
|
352
405
|
export const RunDetailSchema = z.looseObject({
|
|
353
406
|
schemaVersion: z.literal(1),
|
|
@@ -355,6 +408,7 @@ export const RunDetailSchema = z.looseObject({
|
|
|
355
408
|
run: ReportRunSchema,
|
|
356
409
|
results: z.array(z.looseObject({
|
|
357
410
|
key: z.string(), id: z.string(), title: z.string(), specPath: z.string().nullable(), environment: z.string().nullable(), producer: z.string(),
|
|
358
|
-
status: EvidenceStatusSchema, durationMs: z.number().nullable(), at: z.number(), layer: z.string(), detail: z.string()
|
|
411
|
+
status: EvidenceStatusSchema, durationMs: z.number().nullable(), at: z.number(), layer: z.string(), detail: z.string(),
|
|
412
|
+
videos: z.array(VideoRefSchema).optional().describe('Every video its evidence references, with who holds it')
|
|
359
413
|
}))
|
|
360
414
|
});
|