@crvouga/atlas 1.6.0 → 1.8.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 +13 -1
- package/dist/reports/src/explorer-types.d.ts +19 -0
- package/dist/reports/src/latency.d.ts +204 -0
- package/dist/reports/src/latency.js +219 -0
- package/dist/reports/src/reports-explorer-route.d.ts +19 -6
- package/dist/reports/src/reports-route.d.ts +19 -6
- package/dist/reports/src/test-catalog.d.ts +3 -1
- package/dist/reports/src/test-catalog.js +4 -2
- package/dist/schema/src/api.d.ts +151 -0
- package/dist/schema/src/api.js +4 -3
- package/dist/schema/src/layer.d.ts +90 -0
- package/dist/schema/src/layer.js +20 -1
- package/docs/extending.md +18 -1
- package/docs/reference/reports.md +347 -0
- package/docs/reference/schema.md +28 -0
- package/docs/rich-evidence.md +43 -0
- package/docs/ui.md +24 -1
- package/llms-full.txt +85 -2
- package/package.json +1 -1
- package/packages/schema/schemas/check-detail.schema.json +56 -1
- package/packages/schema/schemas/effective-delta.schema.json +60 -2
- package/packages/schema/schemas/effective-evidence.schema.json +60 -2
- package/packages/schema/schemas/layer-rows.schema.json +60 -2
- package/packages/schema/schemas/layer.schema.json +112 -2
- package/packages/schema/schemas/publish-checks.schema.json +56 -1
- package/packages/schema/schemas/test-catalog.schema.json +85 -0
- package/packages/schema/schemas/test-history.schema.json +170 -0
- package/packages/server/openapi.json +547 -8
- package/packages/visualizer/src/evidence/behavior-panel.tsx +10 -16
- package/packages/visualizer/src/evidence/check-detail.tsx +59 -15
- package/packages/visualizer/src/evidence/outcome-summary.tsx +208 -0
- package/packages/visualizer/src/evidence/outcome.test.ts +129 -0
- package/packages/visualizer/src/evidence/outcome.ts +309 -0
- package/packages/visualizer/src/explorer/ProductLatency.tsx +214 -0
- package/packages/visualizer/src/explorer/TestDetail.tsx +32 -3
- package/packages/visualizer/src/explorer/search.ts +3 -0
package/dist/schema/src/api.d.ts
CHANGED
|
@@ -252,6 +252,17 @@ export declare const LayerRowSchema: z.ZodObject<{
|
|
|
252
252
|
value: z.ZodNumber;
|
|
253
253
|
unit: z.ZodString;
|
|
254
254
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
255
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
256
|
+
from: z.ZodOptional<z.ZodString>;
|
|
257
|
+
to: z.ZodOptional<z.ZodString>;
|
|
258
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
259
|
+
from: z.ZodOptional<z.ZodString>;
|
|
260
|
+
to: z.ZodOptional<z.ZodString>;
|
|
261
|
+
}, z.core.$loose>>;
|
|
262
|
+
source: z.ZodOptional<z.ZodString>;
|
|
263
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
264
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
265
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
255
266
|
}, z.core.$loose>>;
|
|
256
267
|
testId: z.ZodNullable<z.ZodString>;
|
|
257
268
|
variant: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -320,6 +331,17 @@ export declare const LayerRowsSchema: z.ZodObject<{
|
|
|
320
331
|
value: z.ZodNumber;
|
|
321
332
|
unit: z.ZodString;
|
|
322
333
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
334
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
335
|
+
from: z.ZodOptional<z.ZodString>;
|
|
336
|
+
to: z.ZodOptional<z.ZodString>;
|
|
337
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
338
|
+
from: z.ZodOptional<z.ZodString>;
|
|
339
|
+
to: z.ZodOptional<z.ZodString>;
|
|
340
|
+
}, z.core.$loose>>;
|
|
341
|
+
source: z.ZodOptional<z.ZodString>;
|
|
342
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
343
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
344
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
323
345
|
}, z.core.$loose>>;
|
|
324
346
|
testId: z.ZodNullable<z.ZodString>;
|
|
325
347
|
variant: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -390,6 +412,17 @@ export declare const LayerEvidenceSchema: z.ZodObject<{
|
|
|
390
412
|
value: z.ZodNumber;
|
|
391
413
|
unit: z.ZodString;
|
|
392
414
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
415
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
416
|
+
from: z.ZodOptional<z.ZodString>;
|
|
417
|
+
to: z.ZodOptional<z.ZodString>;
|
|
418
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
419
|
+
from: z.ZodOptional<z.ZodString>;
|
|
420
|
+
to: z.ZodOptional<z.ZodString>;
|
|
421
|
+
}, z.core.$loose>>;
|
|
422
|
+
source: z.ZodOptional<z.ZodString>;
|
|
423
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
424
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
425
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
393
426
|
}, z.core.$loose>>;
|
|
394
427
|
testId: z.ZodNullable<z.ZodString>;
|
|
395
428
|
variant: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -544,6 +577,17 @@ export declare const EffectiveEvidenceSchema: z.ZodObject<{
|
|
|
544
577
|
value: z.ZodNumber;
|
|
545
578
|
unit: z.ZodString;
|
|
546
579
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
580
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
581
|
+
from: z.ZodOptional<z.ZodString>;
|
|
582
|
+
to: z.ZodOptional<z.ZodString>;
|
|
583
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
584
|
+
from: z.ZodOptional<z.ZodString>;
|
|
585
|
+
to: z.ZodOptional<z.ZodString>;
|
|
586
|
+
}, z.core.$loose>>;
|
|
587
|
+
source: z.ZodOptional<z.ZodString>;
|
|
588
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
589
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
590
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
547
591
|
}, z.core.$loose>>;
|
|
548
592
|
testId: z.ZodNullable<z.ZodString>;
|
|
549
593
|
variant: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -719,6 +763,17 @@ export declare const EffectiveDeltaSchema: z.ZodObject<{
|
|
|
719
763
|
value: z.ZodNumber;
|
|
720
764
|
unit: z.ZodString;
|
|
721
765
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
766
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
767
|
+
from: z.ZodOptional<z.ZodString>;
|
|
768
|
+
to: z.ZodOptional<z.ZodString>;
|
|
769
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
770
|
+
from: z.ZodOptional<z.ZodString>;
|
|
771
|
+
to: z.ZodOptional<z.ZodString>;
|
|
772
|
+
}, z.core.$loose>>;
|
|
773
|
+
source: z.ZodOptional<z.ZodString>;
|
|
774
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
775
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
776
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
722
777
|
}, z.core.$loose>>;
|
|
723
778
|
testId: z.ZodNullable<z.ZodString>;
|
|
724
779
|
variant: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
@@ -1312,6 +1367,17 @@ export declare const CheckDetailSchema: z.ZodObject<{
|
|
|
1312
1367
|
value: z.ZodNumber;
|
|
1313
1368
|
unit: z.ZodString;
|
|
1314
1369
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
1370
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
1371
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1372
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1373
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
1374
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1375
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1376
|
+
}, z.core.$loose>>;
|
|
1377
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1378
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
1379
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
1380
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1315
1381
|
}, z.core.$loose>>>;
|
|
1316
1382
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
1317
1383
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
|
@@ -1498,6 +1564,23 @@ export declare const TestResultEntrySchema: z.ZodObject<{
|
|
|
1498
1564
|
}, z.core.$loose>>;
|
|
1499
1565
|
}, z.core.$loose>>>;
|
|
1500
1566
|
}, z.core.$loose>>;
|
|
1567
|
+
latency: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1568
|
+
name: z.ZodString;
|
|
1569
|
+
value: z.ZodNumber;
|
|
1570
|
+
unit: z.ZodString;
|
|
1571
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
1572
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
1573
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1574
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1575
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
1576
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1577
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1578
|
+
}, z.core.$loose>>;
|
|
1579
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1580
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
1581
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
1582
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1583
|
+
}, z.core.$loose>>>;
|
|
1501
1584
|
}, z.core.$loose>;
|
|
1502
1585
|
/** One test of the catalog: what it is, its current result per environment, and how it has gone over its recorded history. */
|
|
1503
1586
|
export declare const TestSummarySchema: z.ZodObject<{
|
|
@@ -1578,6 +1661,23 @@ export declare const TestSummarySchema: z.ZodObject<{
|
|
|
1578
1661
|
}, z.core.$loose>>;
|
|
1579
1662
|
}, z.core.$loose>>>;
|
|
1580
1663
|
}, z.core.$loose>>;
|
|
1664
|
+
latency: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1665
|
+
name: z.ZodString;
|
|
1666
|
+
value: z.ZodNumber;
|
|
1667
|
+
unit: z.ZodString;
|
|
1668
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
1669
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
1670
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1671
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1672
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
1673
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1674
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1675
|
+
}, z.core.$loose>>;
|
|
1676
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1677
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
1678
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
1679
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1680
|
+
}, z.core.$loose>>>;
|
|
1581
1681
|
}, z.core.$loose>>;
|
|
1582
1682
|
stats: z.ZodObject<{
|
|
1583
1683
|
results: z.ZodNumber;
|
|
@@ -1853,6 +1953,23 @@ export declare const TestCatalogSchema: z.ZodObject<{
|
|
|
1853
1953
|
}, z.core.$loose>>;
|
|
1854
1954
|
}, z.core.$loose>>>;
|
|
1855
1955
|
}, z.core.$loose>>;
|
|
1956
|
+
latency: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1957
|
+
name: z.ZodString;
|
|
1958
|
+
value: z.ZodNumber;
|
|
1959
|
+
unit: z.ZodString;
|
|
1960
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
1961
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
1962
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1963
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1964
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
1965
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1966
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1967
|
+
}, z.core.$loose>>;
|
|
1968
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1969
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
1970
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
1971
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1972
|
+
}, z.core.$loose>>>;
|
|
1856
1973
|
}, z.core.$loose>>;
|
|
1857
1974
|
stats: z.ZodObject<{
|
|
1858
1975
|
results: z.ZodNumber;
|
|
@@ -2055,6 +2172,23 @@ export declare const TestHistorySchema: z.ZodObject<{
|
|
|
2055
2172
|
}, z.core.$loose>>;
|
|
2056
2173
|
}, z.core.$loose>>>;
|
|
2057
2174
|
}, z.core.$loose>>;
|
|
2175
|
+
latency: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2176
|
+
name: z.ZodString;
|
|
2177
|
+
value: z.ZodNumber;
|
|
2178
|
+
unit: z.ZodString;
|
|
2179
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
2180
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
2181
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2182
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2183
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
2184
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2185
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2186
|
+
}, z.core.$loose>>;
|
|
2187
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2188
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
2189
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
2190
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2191
|
+
}, z.core.$loose>>>;
|
|
2058
2192
|
}, z.core.$loose>>;
|
|
2059
2193
|
stats: z.ZodObject<{
|
|
2060
2194
|
results: z.ZodNumber;
|
|
@@ -2154,6 +2288,23 @@ export declare const TestHistorySchema: z.ZodObject<{
|
|
|
2154
2288
|
}, z.core.$loose>>;
|
|
2155
2289
|
}, z.core.$loose>>>;
|
|
2156
2290
|
}, z.core.$loose>>;
|
|
2291
|
+
latency: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2292
|
+
name: z.ZodString;
|
|
2293
|
+
value: z.ZodNumber;
|
|
2294
|
+
unit: z.ZodString;
|
|
2295
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
2296
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
2297
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2298
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2299
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
2300
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2301
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2302
|
+
}, z.core.$loose>>;
|
|
2303
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2304
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
2305
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
2306
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2307
|
+
}, z.core.$loose>>>;
|
|
2157
2308
|
}, z.core.$loose>>;
|
|
2158
2309
|
}, z.core.$loose>;
|
|
2159
2310
|
/** A run: the layers that name the same execution (else share a run URL, else a branch and commit), with what they recorded. */
|
package/dist/schema/src/api.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* @see docs/server.md
|
|
15
15
|
*/
|
|
16
16
|
import { z } from 'zod/v4';
|
|
17
|
-
import { CheckSchema, EvidenceScopeSchema, LayerRunSchema } from './layer.js';
|
|
17
|
+
import { CheckSchema, EvidenceScopeSchema, LayerRunSchema, MeasurementSchema } from './layer.js';
|
|
18
18
|
/** One of the statuses a check has in a report: `passed`, `failed`, `running` (not finished) or `not-run`. Closed. */
|
|
19
19
|
export const EvidenceStatusSchema = z.enum(['passed', 'failed', 'running', 'not-run']);
|
|
20
20
|
/**
|
|
@@ -124,7 +124,7 @@ export const LayerRowSchema = z.looseObject({
|
|
|
124
124
|
status: EvidenceStatusSchema,
|
|
125
125
|
specPath: z.string().nullable().describe('The spec the check belongs to, `specs/<path>`, or null'),
|
|
126
126
|
detail: z.string().describe('Why it has this status; empty when there is nothing to add'),
|
|
127
|
-
measurements: z.array(
|
|
127
|
+
measurements: z.array(MeasurementSchema),
|
|
128
128
|
testId: z.string().nullable(),
|
|
129
129
|
variant: z.record(z.string(), z.string()),
|
|
130
130
|
durationMs: z.number().nullable(),
|
|
@@ -270,7 +270,8 @@ export const TestResultEntrySchema = z.looseObject({
|
|
|
270
270
|
layer: z.string().describe('The id of the layer that recorded it'),
|
|
271
271
|
backend: z.string(),
|
|
272
272
|
detail: z.string().describe('Why it has its status, at most 500 characters'),
|
|
273
|
-
evidence: EvidenceSummarySchema.optional()
|
|
273
|
+
evidence: EvidenceSummarySchema.optional(),
|
|
274
|
+
latency: z.array(MeasurementSchema).optional().describe('Its product-latency measurements (`kind: product-latency`), when it recorded any. Separate from `durationMs`, which is how long the test took')
|
|
274
275
|
});
|
|
275
276
|
const DurationStatsSchema = z.looseObject({
|
|
276
277
|
count: z.number().int().nonnegative(), totalMs: z.number(), avgMs: z.number(), p50Ms: z.number(), p95Ms: z.number(), minMs: z.number(), maxMs: z.number(), lastMs: z.number()
|
|
@@ -74,16 +74,40 @@ export declare const LayerRunSchema: z.ZodObject<{
|
|
|
74
74
|
}, z.core.$loose>;
|
|
75
75
|
/** The execution of a layer, parsed from `LayerRunSchema`. */
|
|
76
76
|
export type LayerRun = z.output<typeof LayerRunSchema>;
|
|
77
|
+
/** The `kind` of a measurement that is a named, user-visible product latency (see docs/rich-evidence.md#product-latency). */
|
|
78
|
+
export declare const PRODUCT_LATENCY_KIND = "product-latency";
|
|
79
|
+
/** The two ends of a measured interval, named in the producer's words: `{ from: 'submit pressed', to: 'confirmation visible' }`. */
|
|
80
|
+
export declare const MeasurementBoundarySchema: z.ZodObject<{
|
|
81
|
+
from: z.ZodOptional<z.ZodString>;
|
|
82
|
+
to: z.ZodOptional<z.ZodString>;
|
|
83
|
+
}, z.core.$loose>;
|
|
77
84
|
/**
|
|
78
85
|
* A number a check measured, such as a latency or a size, with its unit and an optional allowance. A measurement over
|
|
79
86
|
* its `limit` is reported and never changes the check's status.
|
|
87
|
+
*
|
|
88
|
+
* A measurement of `kind` `product-latency` is how quickly the product responded to a user, between two named events.
|
|
89
|
+
* It is not the check's duration (which includes setup, waits and pacing) and a number with no `kind` is never read as
|
|
90
|
+
* product latency. All the fields after `limit` are optional and describe the measurement; none decides a status.
|
|
80
91
|
*/
|
|
81
92
|
export declare const MeasurementSchema: z.ZodObject<{
|
|
82
93
|
name: z.ZodString;
|
|
83
94
|
value: z.ZodNumber;
|
|
84
95
|
unit: z.ZodString;
|
|
85
96
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
97
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
98
|
+
from: z.ZodOptional<z.ZodString>;
|
|
99
|
+
to: z.ZodOptional<z.ZodString>;
|
|
100
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
101
|
+
from: z.ZodOptional<z.ZodString>;
|
|
102
|
+
to: z.ZodOptional<z.ZodString>;
|
|
103
|
+
}, z.core.$loose>>;
|
|
104
|
+
source: z.ZodOptional<z.ZodString>;
|
|
105
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
106
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
107
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
86
108
|
}, z.core.$loose>;
|
|
109
|
+
/** A measurement as stored in a layer, parsed from `MeasurementSchema`. */
|
|
110
|
+
export type Measurement = z.output<typeof MeasurementSchema>;
|
|
87
111
|
/**
|
|
88
112
|
* Structured data of a producer's or tool's own, by namespace: `{ "com.example.coverage": { … } }`.
|
|
89
113
|
* Use a name you own (a reverse domain, or your tool's name). Readers preserve it and never fail on it.
|
|
@@ -867,6 +891,17 @@ export declare const CheckSchema: z.ZodObject<{
|
|
|
867
891
|
value: z.ZodNumber;
|
|
868
892
|
unit: z.ZodString;
|
|
869
893
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
894
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
895
|
+
from: z.ZodOptional<z.ZodString>;
|
|
896
|
+
to: z.ZodOptional<z.ZodString>;
|
|
897
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
898
|
+
from: z.ZodOptional<z.ZodString>;
|
|
899
|
+
to: z.ZodOptional<z.ZodString>;
|
|
900
|
+
}, z.core.$loose>>;
|
|
901
|
+
source: z.ZodOptional<z.ZodString>;
|
|
902
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
903
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
904
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
870
905
|
}, z.core.$loose>>>;
|
|
871
906
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
872
907
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
|
@@ -1338,6 +1373,17 @@ export declare const ReportPartSchema: z.ZodObject<{
|
|
|
1338
1373
|
value: z.ZodNumber;
|
|
1339
1374
|
unit: z.ZodString;
|
|
1340
1375
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
1376
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
1377
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1378
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1379
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
1380
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1381
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1382
|
+
}, z.core.$loose>>;
|
|
1383
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1384
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
1385
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
1386
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1341
1387
|
}, z.core.$loose>>>;
|
|
1342
1388
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
1343
1389
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
|
@@ -1708,6 +1754,17 @@ export declare const LayerSourceSchema: z.ZodObject<{
|
|
|
1708
1754
|
value: z.ZodNumber;
|
|
1709
1755
|
unit: z.ZodString;
|
|
1710
1756
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
1757
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
1758
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1759
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1760
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
1761
|
+
from: z.ZodOptional<z.ZodString>;
|
|
1762
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1763
|
+
}, z.core.$loose>>;
|
|
1764
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1765
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
1766
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
1767
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1711
1768
|
}, z.core.$loose>>>;
|
|
1712
1769
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
1713
1770
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
|
@@ -2324,6 +2381,17 @@ export declare const LayerDocumentSchema: z.ZodObject<{
|
|
|
2324
2381
|
value: z.ZodNumber;
|
|
2325
2382
|
unit: z.ZodString;
|
|
2326
2383
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
2384
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
2385
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2386
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2387
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
2388
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2389
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2390
|
+
}, z.core.$loose>>;
|
|
2391
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2392
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
2393
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
2394
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2327
2395
|
}, z.core.$loose>>>;
|
|
2328
2396
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
2329
2397
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
|
@@ -2693,6 +2761,17 @@ export declare const LayerDocumentSchema: z.ZodObject<{
|
|
|
2693
2761
|
value: z.ZodNumber;
|
|
2694
2762
|
unit: z.ZodString;
|
|
2695
2763
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
2764
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
2765
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2766
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2767
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
2768
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2769
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2770
|
+
}, z.core.$loose>>;
|
|
2771
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2772
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
2773
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
2774
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2696
2775
|
}, z.core.$loose>>>;
|
|
2697
2776
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
2698
2777
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
|
@@ -2901,6 +2980,17 @@ export declare const PublishChecksSchema: z.ZodObject<{
|
|
|
2901
2980
|
value: z.ZodNumber;
|
|
2902
2981
|
unit: z.ZodString;
|
|
2903
2982
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
2983
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
2984
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2985
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2986
|
+
intended: z.ZodOptional<z.ZodObject<{
|
|
2987
|
+
from: z.ZodOptional<z.ZodString>;
|
|
2988
|
+
to: z.ZodOptional<z.ZodString>;
|
|
2989
|
+
}, z.core.$loose>>;
|
|
2990
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2991
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
2992
|
+
instrumentation: z.ZodOptional<z.ZodString>;
|
|
2993
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2904
2994
|
}, z.core.$loose>>>;
|
|
2905
2995
|
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
2906
2996
|
recordingExpectation: z.ZodOptional<z.ZodString>;
|
package/dist/schema/src/layer.js
CHANGED
|
@@ -62,15 +62,34 @@ export const LayerRunSchema = z.looseObject({
|
|
|
62
62
|
startedAtMs: z.number().nonnegative().optional().describe('When the execution started, epoch milliseconds'),
|
|
63
63
|
endedAtMs: z.number().nonnegative().optional().describe('When the execution ended, epoch milliseconds')
|
|
64
64
|
});
|
|
65
|
+
/** The `kind` of a measurement that is a named, user-visible product latency (see docs/rich-evidence.md#product-latency). */
|
|
66
|
+
export const PRODUCT_LATENCY_KIND = 'product-latency';
|
|
67
|
+
/** The two ends of a measured interval, named in the producer's words: `{ from: 'submit pressed', to: 'confirmation visible' }`. */
|
|
68
|
+
export const MeasurementBoundarySchema = z.looseObject({
|
|
69
|
+
from: z.string().min(1).optional().describe('The event the interval starts at: `end of speech`, `submit pressed`'),
|
|
70
|
+
to: z.string().min(1).optional().describe('The event the interval ends at: `audible response`, `confirmation visible`')
|
|
71
|
+
});
|
|
65
72
|
/**
|
|
66
73
|
* A number a check measured, such as a latency or a size, with its unit and an optional allowance. A measurement over
|
|
67
74
|
* its `limit` is reported and never changes the check's status.
|
|
75
|
+
*
|
|
76
|
+
* A measurement of `kind` `product-latency` is how quickly the product responded to a user, between two named events.
|
|
77
|
+
* It is not the check's duration (which includes setup, waits and pacing) and a number with no `kind` is never read as
|
|
78
|
+
* product latency. All the fields after `limit` are optional and describe the measurement; none decides a status.
|
|
68
79
|
*/
|
|
69
80
|
export const MeasurementSchema = z.looseObject({
|
|
70
81
|
name: z.string().min(1),
|
|
71
82
|
value: z.number().describe('A finite number'),
|
|
72
83
|
unit: z.string(),
|
|
73
|
-
limit: z.number().optional().describe('The allowance. A measurement over it is reported, and never fails the check by itself')
|
|
84
|
+
limit: z.number().optional().describe('The allowance, or budget. A measurement over it is reported, and never fails the check by itself'),
|
|
85
|
+
kind: z.string().min(1).optional().describe('What the number is, in an open vocabulary. `product-latency`: a user-visible response time between `from` and `to`. Absent: just a number, never read as product latency'),
|
|
86
|
+
from: z.string().min(1).optional().describe('The event the interval starts at. Without both `from` and `to` a latency is shown but no product claim is made from it'),
|
|
87
|
+
to: z.string().min(1).optional().describe('The event the interval ends at'),
|
|
88
|
+
intended: MeasurementBoundarySchema.optional().describe('The interval the name of the measurement claims, when what was measured is only part of it. If `intended.to` differs from `to` (or `intended.from` from `from`) the measurement is shown as partial, never as the complete interval'),
|
|
89
|
+
source: z.string().optional().describe('How it was measured: `app-instrumentation`, `trace`, `recording-analysis`'),
|
|
90
|
+
outcome: z.string().min(1).optional().describe('`observed` (the default), `timeout` or `failed`. For anything but `observed` the value is how long the observation waited: at least that much, so it counts against a budget and is never dropped'),
|
|
91
|
+
instrumentation: z.string().optional().describe('The version or method of the measurement. A change of it between two sets of observations is disclosed when they are compared'),
|
|
92
|
+
labels: z.record(z.string(), z.string()).optional().describe('What the observation is comparable with: `device`, `build`, `network`. `device` and `build` group the observations and, when two groups differ in the others, the comparison says so')
|
|
74
93
|
});
|
|
75
94
|
/**
|
|
76
95
|
* Structured data of a producer's or tool's own, by namespace: `{ "com.example.coverage": { … } }`.
|
package/docs/extending.md
CHANGED
|
@@ -34,7 +34,7 @@ carry any of these. Every one is optional.
|
|
|
34
34
|
| `scope{}` | What the evidence does and does not show: surface, device kind, synthetic data, scripted dependencies, audio, pacing, what was asserted and its limits. Unknown when absent. See [Evidence scope](rich-evidence.md#evidence-scope). |
|
|
35
35
|
| `links[]` | Where to read more: the CI run, the issue, the trace client. |
|
|
36
36
|
| `extensions{}` | Structured data of your own or a tool's, under a name you own. |
|
|
37
|
-
| `measurements[]` | Numbers, with units and an allowance (already part of the contract). |
|
|
37
|
+
| `measurements[]` | Numbers, with units and an allowance (already part of the contract). A measurement of `kind` `product-latency` names a user-visible response time between two events; see [Product latency](rich-evidence.md#product-latency). |
|
|
38
38
|
|
|
39
39
|
An attachment may carry its own `tags[]` (`demo`): shown as `#demo` and searchable; see
|
|
40
40
|
[Tagging artifacts and demos](rich-evidence.md#tagging-artifacts-and-demos).
|
|
@@ -104,6 +104,23 @@ every kind of evidence and values from the future) and `layer-extensibility.test
|
|
|
104
104
|
fields survive at every level, malformed evidence is dropped without losing the result, and a reader of the
|
|
105
105
|
first version of the format still reads it all.
|
|
106
106
|
|
|
107
|
+
### Saying what failed
|
|
108
|
+
|
|
109
|
+
A failed check or step may declare the expectation it broke under the `atlas.failure` extension, so a reviewer sees
|
|
110
|
+
it before the raw log. Every field is optional, and the declaration never changes the result.
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"name": "The list includes tea", "kind": "then", "status": "failed",
|
|
115
|
+
"extensions": { "atlas.failure": { "expected": "tea in the list", "actual": "the list is empty", "attribution": "product" } }
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`expected` and `actual` are shown as written. `attribution` is `product`, `test-harness` or `environment`; leave it out
|
|
120
|
+
when you do not know, and the viewer says the cause is unknown. It is never inferred from the message. Whether setup
|
|
121
|
+
failed before the behavior started comes from the failed step's `kind`: `hook`, `setup`, `fixture`, `before`,
|
|
122
|
+
`beforeAll`, `beforeEach` or `given` mean preparation; `when`, `then`, `assertion` or `expect` mean the behavior.
|
|
123
|
+
|
|
107
124
|
## Attach evidence
|
|
108
125
|
|
|
109
126
|
### From the command line
|