@crvouga/atlas 1.1.0 → 1.3.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-query.d.ts +123 -0
- package/dist/reports/src/artifact-query.js +234 -0
- package/dist/reports/src/evidence-detail.d.ts +14 -3
- package/dist/reports/src/evidence-detail.js +34 -19
- package/dist/reports/src/evidence-scope.d.ts +83 -0
- package/dist/reports/src/evidence-scope.js +129 -0
- package/dist/reports/src/evidence-types.d.ts +5 -1
- package/dist/reports/src/explorer-types.d.ts +1 -1
- package/dist/reports/src/layer-merge.js +3 -2
- package/dist/reports/src/layer-types.d.ts +1 -1
- package/dist/reports/src/publish-checks.js +1 -0
- package/dist/reports/src/reporter.d.ts +1 -1
- package/dist/reports/src/reports-explorer-route.d.ts +276 -0
- package/dist/reports/src/reports-route.d.ts +276 -0
- package/dist/reports/src/test-catalog.d.ts +108 -6
- package/dist/reports/src/test-catalog.js +155 -8
- package/dist/schema/src/api.d.ts +745 -0
- package/dist/schema/src/api.js +48 -6
- package/dist/schema/src/layer.d.ts +981 -0
- package/dist/schema/src/layer.js +43 -4
- package/dist/server/src/app.js +16 -5
- package/dist/server/src/openapi.js +42 -3
- package/docs/extending.md +1 -0
- package/docs/reference/http-api.md +86 -2
- package/docs/reference/reports.md +550 -14
- package/docs/reference/schema.md +55 -0
- package/docs/rich-evidence.md +78 -0
- package/docs/server.md +4 -1
- package/docs/ui.md +1 -1
- package/llms-full.txt +170 -4
- package/package.json +1 -1
- package/packages/schema/schemas/check-detail.schema.json +673 -1
- package/packages/schema/schemas/effective-delta.schema.json +206 -0
- package/packages/schema/schemas/effective-evidence.schema.json +206 -0
- package/packages/schema/schemas/evidence-page.schema.json +103 -0
- package/packages/schema/schemas/layer-rows.schema.json +103 -0
- package/packages/schema/schemas/layer.schema.json +1598 -62
- package/packages/schema/schemas/publish-checks.schema.json +768 -0
- package/packages/schema/schemas/report-run.schema.json +131 -0
- package/packages/schema/schemas/report-runs.schema.json +221 -0
- package/packages/schema/schemas/test-catalog.schema.json +135 -0
- package/packages/schema/schemas/test-history.schema.json +216 -0
- package/packages/server/openapi.json +4731 -735
- package/packages/visualizer/src/evidence/artifacts.tsx +24 -18
- package/packages/visualizer/src/evidence/evidence-scope.tsx +106 -0
- package/packages/visualizer/src/evidence/format.ts +11 -0
- package/packages/visualizer/src/explorer/ArtifactsView.tsx +162 -0
- package/packages/visualizer/src/explorer/Explorer.tsx +47 -3
- package/packages/visualizer/src/explorer/RunsView.tsx +43 -19
- package/packages/visualizer/src/explorer/catalog.tsx +97 -12
- package/packages/visualizer/src/explorer/filters.tsx +279 -0
- package/packages/visualizer/src/explorer/search.ts +85 -6
- package/packages/visualizer/src/explorer/views.ts +75 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/** The fields of a scope that say something about the evidence and that `verified` may name, in the order they are shown. */
|
|
2
|
+
export const SCOPE_DIMENSIONS = ['surface', 'deviceKind', 'syntheticData', 'dependencies', 'audioCaptured', 'pacing'];
|
|
3
|
+
/** The filter token of a recording that declares no scope at all. */
|
|
4
|
+
export const UNKNOWN_SCOPE = 'unknown';
|
|
5
|
+
/**
|
|
6
|
+
* The declaration that applies to something: the nearest one wins as a whole, never field by field, so a recording
|
|
7
|
+
* never shows a limitation or a device that was declared for another source. Pass the candidates nearest first
|
|
8
|
+
* (attachment, attempt, check, part, layer); absent ones are skipped. Undefined when none declares a scope.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* effectiveScope(attachment.scope, attempt.scope, check.scope, layer.scope);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function effectiveScope(...candidates) {
|
|
16
|
+
return candidates.find((candidate) => candidate !== undefined);
|
|
17
|
+
}
|
|
18
|
+
const word = (value) => value.normalize('NFC').trim().toLowerCase().replace(/\s+/g, '-');
|
|
19
|
+
/** A stable string that is equal for equal declarations (key order never matters), to tell one scope from another. */
|
|
20
|
+
export function scopeKey(scope) {
|
|
21
|
+
if (!scope)
|
|
22
|
+
return UNKNOWN_SCOPE;
|
|
23
|
+
const sort = (value) => Array.isArray(value) ? value.map(sort) : value && typeof value === 'object' ? Object.fromEntries(Object.entries(value).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)).map(([key, item]) => [key, sort(item)])) : value;
|
|
24
|
+
return JSON.stringify(sort(scope));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The filter tokens one declaration states, normalized (letter case and spaces never matter): `surface:<value>`,
|
|
28
|
+
* `device:<value>`, `data:synthetic` or `data:real`, `dependencies:<value>`, `audio:recorded` or `audio:silent`,
|
|
29
|
+
* `pacing:<value>`. A field that is not declared adds no token. No scope at all is the single token
|
|
30
|
+
* {@link UNKNOWN_SCOPE}, so a filter can ask for the unknown on purpose; a scope that declares nothing readable is
|
|
31
|
+
* also unknown.
|
|
32
|
+
*/
|
|
33
|
+
export function scopeTokens(scope) {
|
|
34
|
+
const tokens = [];
|
|
35
|
+
if (scope?.surface)
|
|
36
|
+
tokens.push(`surface:${word(scope.surface)}`);
|
|
37
|
+
if (scope?.deviceKind)
|
|
38
|
+
tokens.push(`device:${word(scope.deviceKind)}`);
|
|
39
|
+
if (scope?.syntheticData !== undefined)
|
|
40
|
+
tokens.push(scope.syntheticData ? 'data:synthetic' : 'data:real');
|
|
41
|
+
if (scope?.dependencies)
|
|
42
|
+
tokens.push(`dependencies:${word(scope.dependencies)}`);
|
|
43
|
+
if (scope?.audioCaptured !== undefined)
|
|
44
|
+
tokens.push(scope.audioCaptured ? 'audio:recorded' : 'audio:silent');
|
|
45
|
+
if (scope?.pacing)
|
|
46
|
+
tokens.push(`pacing:${word(scope.pacing)}`);
|
|
47
|
+
return tokens.length ? tokens : [UNKNOWN_SCOPE];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Whether one recording's tokens satisfy a filter: every wanted token must be among them. Tokens compare normalized.
|
|
51
|
+
* An empty filter matches everything. The token {@link UNKNOWN_SCOPE} matches only a recording with no declared
|
|
52
|
+
* fields, so asking for `device:physical` never includes a recording that did not say what it ran on.
|
|
53
|
+
*/
|
|
54
|
+
export function matchesScope(tokens, wanted) {
|
|
55
|
+
const have = new Set(tokens.map(word));
|
|
56
|
+
return wanted.every(token => have.has(word(token)));
|
|
57
|
+
}
|
|
58
|
+
const title = (value) => { const text = value.replace(/[-_]+/g, ' ').trim(); return text.charAt(0).toUpperCase() + text.slice(1); };
|
|
59
|
+
const LABELS = { surface: 'Surface', deviceKind: 'Device', syntheticData: 'Data', dependencies: 'Dependencies', audioCaptured: 'Audio', pacing: 'Pacing' };
|
|
60
|
+
function valueOf(scope, dimension) {
|
|
61
|
+
switch (dimension) {
|
|
62
|
+
case 'surface': return scope.surface ? title(scope.surface) : undefined;
|
|
63
|
+
case 'deviceKind': return scope.deviceKind ? title(scope.deviceKind) : undefined;
|
|
64
|
+
case 'syntheticData': return scope.syntheticData === undefined ? undefined : scope.syntheticData ? 'Synthetic' : 'Real';
|
|
65
|
+
case 'dependencies': return scope.dependencies ? title(scope.dependencies) : undefined;
|
|
66
|
+
case 'audioCaptured': return scope.audioCaptured === undefined ? undefined : scope.audioCaptured ? 'Recorded' : 'Silent';
|
|
67
|
+
case 'pacing': return scope.pacing ? title(scope.pacing) : undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Every dimension of a scope with its value and how it is known, in a fixed order, including the ones nobody declared
|
|
72
|
+
* (`Not declared`, basis `undeclared`). A dimension is `verified` only when the scope's `verified` names it and it has
|
|
73
|
+
* a value; everything else a producer wrote is `declared`. With no scope every dimension is undeclared.
|
|
74
|
+
*/
|
|
75
|
+
export function scopeFacts(scope) {
|
|
76
|
+
const verified = new Set(scope?.verified ?? []);
|
|
77
|
+
return SCOPE_DIMENSIONS.map(dimension => {
|
|
78
|
+
const value = scope ? valueOf(scope, dimension) : undefined;
|
|
79
|
+
return { dimension, label: LABELS[dimension], value: value ?? 'Not declared', basis: value === undefined ? 'undeclared' : verified.has(dimension) ? 'verified' : 'declared' };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The concise badges for a scope: one per declared dimension, in a fixed order (`Surface: Browser`, `Device: Simulator`, `Synthetic
|
|
84
|
+
* data`, `Scripted dependencies`, `Silent`, `Paced`). With no declared dimension the one badge `Scope unknown`, so
|
|
85
|
+
* a reviewer is told nothing was claimed rather than shown nothing.
|
|
86
|
+
*/
|
|
87
|
+
export function scopeBadges(scope) {
|
|
88
|
+
const badges = [];
|
|
89
|
+
for (const fact of scopeFacts(scope)) {
|
|
90
|
+
if (fact.basis === 'undeclared')
|
|
91
|
+
continue;
|
|
92
|
+
const text = fact.dimension === 'surface' || fact.dimension === 'deviceKind' ? `${fact.label}: ${fact.value}`
|
|
93
|
+
: fact.dimension === 'syntheticData' ? `${fact.value} data`
|
|
94
|
+
: fact.dimension === 'dependencies' ? `${fact.value} dependencies`
|
|
95
|
+
: fact.dimension === 'audioCaptured' ? (fact.value === 'Silent' ? 'Silent' : 'Audio recorded')
|
|
96
|
+
: fact.value;
|
|
97
|
+
badges.push({ dimension: fact.dimension, text, basis: fact.basis });
|
|
98
|
+
}
|
|
99
|
+
return badges.length ? badges : [{ dimension: 'unknown', text: 'Scope unknown', basis: 'undeclared' }];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* What a reviewer must not read into evidence: a sentence per thing that is not shown. It names the assertions the
|
|
103
|
+
* result stands on when there are some (so activity visible beyond them is not verified), and every kind of reality
|
|
104
|
+
* that was not declared. Empty only for a scope that declares and verifies everything and lists no limitation.
|
|
105
|
+
*/
|
|
106
|
+
export function scopeCaveats(scope) {
|
|
107
|
+
const out = [];
|
|
108
|
+
if (!scope || scopeTokens(scope)[0] === UNKNOWN_SCOPE)
|
|
109
|
+
return ['Scope not declared: do not assume this ran live, on a physical device, with real audio or end to end.'];
|
|
110
|
+
if (scope.asserted?.length)
|
|
111
|
+
out.push(`Only these were asserted: ${scope.asserted.join('; ')}. Other activity visible in the recording is not verified.`);
|
|
112
|
+
else
|
|
113
|
+
out.push('No assertion boundary was declared: activity visible in the recording is not verified behavior.');
|
|
114
|
+
if (scope.syntheticData === true)
|
|
115
|
+
out.push('Uses synthetic data: not a statement about production data.');
|
|
116
|
+
if (scope.dependencies === undefined)
|
|
117
|
+
out.push('Whether dependencies were scripted or live is not declared.');
|
|
118
|
+
else if (word(scope.dependencies) !== 'live')
|
|
119
|
+
out.push(`Dependencies were ${word(scope.dependencies)}, not live.`);
|
|
120
|
+
if (scope.audioCaptured === undefined)
|
|
121
|
+
out.push('Whether audio was captured is not declared.');
|
|
122
|
+
else if (!scope.audioCaptured)
|
|
123
|
+
out.push('Silent: nothing audible was recorded.');
|
|
124
|
+
if (scope.deviceKind === undefined)
|
|
125
|
+
out.push('The kind of device is not declared.');
|
|
126
|
+
for (const limit of scope.limitations ?? [])
|
|
127
|
+
out.push(limit);
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @see docs/report-contract.md
|
|
10
10
|
*/
|
|
11
11
|
import type { EvidenceMeasurement, EvidenceStatus } from './explorer-types.js';
|
|
12
|
-
import type { LayerRun } from '../../schema/src/layer.js';
|
|
12
|
+
import type { EvidenceScope, LayerRun } from '../../schema/src/layer.js';
|
|
13
13
|
import type { LayerParameters } from './layer-types.js';
|
|
14
14
|
/** Where a recorded test's timeline and captured files are read from. */
|
|
15
15
|
export type RecordingAddress = {
|
|
@@ -51,10 +51,14 @@ export type VideoRef = {
|
|
|
51
51
|
readonly attempt?: number;
|
|
52
52
|
/** The name of the step that holds it, when `owner` is `step`. */
|
|
53
53
|
readonly step?: string;
|
|
54
|
+
/** The normalized tags of this attachment itself (`demo`), so a query can ask for a tagged video rather than a result that has a video and some tagged file. Absent when it has none (and in documents of older servers). */
|
|
55
|
+
readonly tags?: readonly string[];
|
|
54
56
|
/** What identifies the bytes (digest, bundle key or address); references with the same one are the same recording. Absent when `available` is false. */
|
|
55
57
|
readonly recording?: string;
|
|
56
58
|
/** False when the reference names no bytes at all (no bundle key, address or inline text), so it can never be played. */
|
|
57
59
|
readonly available: boolean;
|
|
60
|
+
/** What this recording shows, as declared for it: its own `scope`, else its attempt's, check's, part's or layer's. Absent when none declared one: its scope is unknown, not live, physical or audible. */
|
|
61
|
+
readonly scope?: EvidenceScope;
|
|
58
62
|
};
|
|
59
63
|
/** Video availability as counts: references, distinct playable recordings (deduplicated), and references that cannot be played. */
|
|
60
64
|
export type VideoCounts = {
|
|
@@ -36,7 +36,7 @@ export type EvidenceMeasurement = {
|
|
|
36
36
|
readonly limit?: number;
|
|
37
37
|
};
|
|
38
38
|
/** What a check may carry beyond its outcome. All optional and open: see docs/extending.md. */
|
|
39
|
-
export type EvidenceExtras = Partial<Pick<import('../../schema/src/layer.js').Check, 'tags' | 'labels' | 'links' | 'steps' | 'attachments' | 'annotations' | 'attempts' | 'extensions'>>;
|
|
39
|
+
export type EvidenceExtras = Partial<Pick<import('../../schema/src/layer.js').Check, 'tags' | 'labels' | 'links' | 'steps' | 'attachments' | 'annotations' | 'attempts' | 'extensions' | 'scope'>>;
|
|
40
40
|
/** One check of a part, as recorded. */
|
|
41
41
|
export type EvidenceCheck = EvidenceExtras & {
|
|
42
42
|
/** Stable across runs; the newer result replaces the older one only if both used the same id. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { summarizeEvidenceIn, summarizeLayerEvidence } from './evidence-detail.js';
|
|
2
|
+
import { effectiveScope } from './evidence-scope.js';
|
|
2
3
|
import { layerPlace } from './layer-axes.js';
|
|
3
4
|
/**
|
|
4
5
|
* A short, deterministic fingerprint of a spec's text, shaped `<length>:<hash>:<hash>` (the length in UTF-16 code
|
|
@@ -79,7 +80,7 @@ export function layerEvidence(summary, backend) {
|
|
|
79
80
|
for (const part of summary.parts) {
|
|
80
81
|
for (const check of part.checks) {
|
|
81
82
|
const test = tests.get(check.id);
|
|
82
|
-
const evidence =
|
|
83
|
+
const evidence = summarizeEvidenceIn(effectiveScope(part.scope, summary.scope), check);
|
|
83
84
|
const item = expectations?.get(check.id);
|
|
84
85
|
rows.push({
|
|
85
86
|
kind: part.kind,
|
|
@@ -15,7 +15,7 @@ import type { SourceRecord } from './protocol.js';
|
|
|
15
15
|
/** String choices (such as `{ device: 'iphone-15' }`) that make a result its own slot. Compared as sorted key/value pairs. */
|
|
16
16
|
export type LayerParameters = Readonly<Record<string, string>>;
|
|
17
17
|
/** What a layer may carry as a whole. All optional and open: see docs/extending.md. */
|
|
18
|
-
export type LayerExtras = Partial<Pick<import('../../schema/src/layer.js').LayerDocument, 'tags' | 'labels' | 'links' | 'attachments' | 'annotations' | 'extensions' | 'recordings'>>;
|
|
18
|
+
export type LayerExtras = Partial<Pick<import('../../schema/src/layer.js').LayerDocument, 'tags' | 'labels' | 'links' | 'attachments' | 'annotations' | 'extensions' | 'recordings' | 'scope'>>;
|
|
19
19
|
/** A layer without its captured files: what composition and the viewer's lists read. */
|
|
20
20
|
export type LayerSummary = LayerExtras & {
|
|
21
21
|
/** `modified`: recorded from a checkout with uncommitted changes. `unknown`: origin not captured. Absent for a clean checkout. Advisory; never changes a status. */
|
|
@@ -123,6 +123,7 @@ export async function publishChecks(store, input, options = {}) {
|
|
|
123
123
|
...(args.links?.length ? { links: args.links } : {}),
|
|
124
124
|
...(layerEvidence.attachments?.length ? { attachments: layerEvidence.attachments } : {}),
|
|
125
125
|
...(args.annotations?.length ? { annotations: args.annotations } : {}),
|
|
126
|
+
...(args.scope ? { scope: args.scope } : {}),
|
|
126
127
|
...(args.extensions && Object.keys(args.extensions).length ? { extensions: args.extensions } : {})
|
|
127
128
|
};
|
|
128
129
|
const bundle = entries.size ? await writeBundle(store, (async function* () { for (const entry of [...entries.values()].sort((a, b) => (a.key < b.key ? -1 : 1)))
|
|
@@ -13,7 +13,7 @@ import { type PublishChecksInput } from '../../schema/src/layer.js';
|
|
|
13
13
|
import type { ObjectStore } from './object-store.js';
|
|
14
14
|
type Check = PublishChecksInput['checks'][number];
|
|
15
15
|
/** What every layer of one stream shares: who is reporting, from where. Whatever `publishChecks` takes, except the checks and the time. */
|
|
16
|
-
export type ReporterIdentity = Pick<PublishChecksInput, 'producer' | 'kind' | 'title' | 'sha' | 'branch' | 'runUrl' | 'run' | 'environment' | 'parameters' | 'freshness' | 'specs' | 'tags' | 'labels' | 'links' | 'attachments' | 'annotations' | 'extensions'>;
|
|
16
|
+
export type ReporterIdentity = Pick<PublishChecksInput, 'producer' | 'kind' | 'title' | 'sha' | 'branch' | 'runUrl' | 'run' | 'environment' | 'parameters' | 'freshness' | 'specs' | 'tags' | 'labels' | 'links' | 'attachments' | 'annotations' | 'scope' | 'extensions'>;
|
|
17
17
|
/** How a reporter sends: the `store` (a folder, S3, or `httpStore` for a server), how often (`flushMs`, `batchSize`), how hard it tries (`attempts`, `backoffMs`), what it tells (`onError`, `onPublished`), and the clock and sleep for tests. */
|
|
18
18
|
export type ReporterOptions = {
|
|
19
19
|
/** Where layers go: a directory, S3, or `httpStore` for an Atlas server. */
|
|
@@ -67,6 +67,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
67
67
|
} | null;
|
|
68
68
|
parts: readonly {
|
|
69
69
|
tags?: string[] | undefined;
|
|
70
|
+
scope?: {
|
|
71
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
72
|
+
surface?: string | undefined;
|
|
73
|
+
deviceKind?: string | undefined;
|
|
74
|
+
syntheticData?: boolean | undefined;
|
|
75
|
+
dependencies?: string | undefined;
|
|
76
|
+
audioCaptured?: boolean | undefined;
|
|
77
|
+
pacing?: string | undefined;
|
|
78
|
+
asserted?: string[] | undefined;
|
|
79
|
+
limitations?: string[] | undefined;
|
|
80
|
+
declaredBy?: string | undefined;
|
|
81
|
+
verified?: string[] | undefined;
|
|
82
|
+
verifiedBy?: string | undefined;
|
|
83
|
+
provenance?: {
|
|
84
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
85
|
+
url: string;
|
|
86
|
+
name?: string | undefined;
|
|
87
|
+
rel?: string | undefined;
|
|
88
|
+
}[] | undefined;
|
|
89
|
+
extensions?: {
|
|
90
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
91
|
+
} | undefined;
|
|
92
|
+
} | undefined;
|
|
70
93
|
attachments?: {
|
|
71
94
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
72
95
|
name: string;
|
|
@@ -83,6 +106,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
83
106
|
durationMs?: number | undefined;
|
|
84
107
|
description?: string | undefined;
|
|
85
108
|
omitted?: string | undefined;
|
|
109
|
+
scope?: {
|
|
110
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
111
|
+
surface?: string | undefined;
|
|
112
|
+
deviceKind?: string | undefined;
|
|
113
|
+
syntheticData?: boolean | undefined;
|
|
114
|
+
dependencies?: string | undefined;
|
|
115
|
+
audioCaptured?: boolean | undefined;
|
|
116
|
+
pacing?: string | undefined;
|
|
117
|
+
asserted?: string[] | undefined;
|
|
118
|
+
limitations?: string[] | undefined;
|
|
119
|
+
declaredBy?: string | undefined;
|
|
120
|
+
verified?: string[] | undefined;
|
|
121
|
+
verifiedBy?: string | undefined;
|
|
122
|
+
provenance?: {
|
|
123
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
124
|
+
url: string;
|
|
125
|
+
name?: string | undefined;
|
|
126
|
+
rel?: string | undefined;
|
|
127
|
+
}[] | undefined;
|
|
128
|
+
extensions?: {
|
|
129
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
130
|
+
} | undefined;
|
|
131
|
+
} | undefined;
|
|
86
132
|
tags?: string[] | undefined;
|
|
87
133
|
at?: {
|
|
88
134
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -102,6 +148,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
102
148
|
durationMs?: number | undefined;
|
|
103
149
|
startedAtMs?: number | undefined;
|
|
104
150
|
detail?: string | undefined;
|
|
151
|
+
scope?: {
|
|
152
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
153
|
+
surface?: string | undefined;
|
|
154
|
+
deviceKind?: string | undefined;
|
|
155
|
+
syntheticData?: boolean | undefined;
|
|
156
|
+
dependencies?: string | undefined;
|
|
157
|
+
audioCaptured?: boolean | undefined;
|
|
158
|
+
pacing?: string | undefined;
|
|
159
|
+
asserted?: string[] | undefined;
|
|
160
|
+
limitations?: string[] | undefined;
|
|
161
|
+
declaredBy?: string | undefined;
|
|
162
|
+
verified?: string[] | undefined;
|
|
163
|
+
verifiedBy?: string | undefined;
|
|
164
|
+
provenance?: {
|
|
165
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
166
|
+
url: string;
|
|
167
|
+
name?: string | undefined;
|
|
168
|
+
rel?: string | undefined;
|
|
169
|
+
}[] | undefined;
|
|
170
|
+
extensions?: {
|
|
171
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
172
|
+
} | undefined;
|
|
173
|
+
} | undefined;
|
|
105
174
|
steps?: {
|
|
106
175
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
107
176
|
name: string;
|
|
@@ -128,6 +197,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
128
197
|
durationMs?: number | undefined;
|
|
129
198
|
description?: string | undefined;
|
|
130
199
|
omitted?: string | undefined;
|
|
200
|
+
scope?: {
|
|
201
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
202
|
+
surface?: string | undefined;
|
|
203
|
+
deviceKind?: string | undefined;
|
|
204
|
+
syntheticData?: boolean | undefined;
|
|
205
|
+
dependencies?: string | undefined;
|
|
206
|
+
audioCaptured?: boolean | undefined;
|
|
207
|
+
pacing?: string | undefined;
|
|
208
|
+
asserted?: string[] | undefined;
|
|
209
|
+
limitations?: string[] | undefined;
|
|
210
|
+
declaredBy?: string | undefined;
|
|
211
|
+
verified?: string[] | undefined;
|
|
212
|
+
verifiedBy?: string | undefined;
|
|
213
|
+
provenance?: {
|
|
214
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
215
|
+
url: string;
|
|
216
|
+
name?: string | undefined;
|
|
217
|
+
rel?: string | undefined;
|
|
218
|
+
}[] | undefined;
|
|
219
|
+
extensions?: {
|
|
220
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
221
|
+
} | undefined;
|
|
222
|
+
} | undefined;
|
|
131
223
|
tags?: string[] | undefined;
|
|
132
224
|
at?: {
|
|
133
225
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -186,6 +278,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
186
278
|
durationMs?: number | undefined;
|
|
187
279
|
description?: string | undefined;
|
|
188
280
|
omitted?: string | undefined;
|
|
281
|
+
scope?: {
|
|
282
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
283
|
+
surface?: string | undefined;
|
|
284
|
+
deviceKind?: string | undefined;
|
|
285
|
+
syntheticData?: boolean | undefined;
|
|
286
|
+
dependencies?: string | undefined;
|
|
287
|
+
audioCaptured?: boolean | undefined;
|
|
288
|
+
pacing?: string | undefined;
|
|
289
|
+
asserted?: string[] | undefined;
|
|
290
|
+
limitations?: string[] | undefined;
|
|
291
|
+
declaredBy?: string | undefined;
|
|
292
|
+
verified?: string[] | undefined;
|
|
293
|
+
verifiedBy?: string | undefined;
|
|
294
|
+
provenance?: {
|
|
295
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
296
|
+
url: string;
|
|
297
|
+
name?: string | undefined;
|
|
298
|
+
rel?: string | undefined;
|
|
299
|
+
}[] | undefined;
|
|
300
|
+
extensions?: {
|
|
301
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
302
|
+
} | undefined;
|
|
303
|
+
} | undefined;
|
|
189
304
|
tags?: string[] | undefined;
|
|
190
305
|
at?: {
|
|
191
306
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -254,6 +369,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
254
369
|
durationMs?: number | undefined;
|
|
255
370
|
description?: string | undefined;
|
|
256
371
|
omitted?: string | undefined;
|
|
372
|
+
scope?: {
|
|
373
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
374
|
+
surface?: string | undefined;
|
|
375
|
+
deviceKind?: string | undefined;
|
|
376
|
+
syntheticData?: boolean | undefined;
|
|
377
|
+
dependencies?: string | undefined;
|
|
378
|
+
audioCaptured?: boolean | undefined;
|
|
379
|
+
pacing?: string | undefined;
|
|
380
|
+
asserted?: string[] | undefined;
|
|
381
|
+
limitations?: string[] | undefined;
|
|
382
|
+
declaredBy?: string | undefined;
|
|
383
|
+
verified?: string[] | undefined;
|
|
384
|
+
verifiedBy?: string | undefined;
|
|
385
|
+
provenance?: {
|
|
386
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
387
|
+
url: string;
|
|
388
|
+
name?: string | undefined;
|
|
389
|
+
rel?: string | undefined;
|
|
390
|
+
}[] | undefined;
|
|
391
|
+
extensions?: {
|
|
392
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
393
|
+
} | undefined;
|
|
394
|
+
} | undefined;
|
|
257
395
|
tags?: string[] | undefined;
|
|
258
396
|
at?: {
|
|
259
397
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -345,6 +483,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
345
483
|
readonly recordedAtMs: number;
|
|
346
484
|
readonly checks: readonly {
|
|
347
485
|
tags?: string[] | undefined;
|
|
486
|
+
scope?: {
|
|
487
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
488
|
+
surface?: string | undefined;
|
|
489
|
+
deviceKind?: string | undefined;
|
|
490
|
+
syntheticData?: boolean | undefined;
|
|
491
|
+
dependencies?: string | undefined;
|
|
492
|
+
audioCaptured?: boolean | undefined;
|
|
493
|
+
pacing?: string | undefined;
|
|
494
|
+
asserted?: string[] | undefined;
|
|
495
|
+
limitations?: string[] | undefined;
|
|
496
|
+
declaredBy?: string | undefined;
|
|
497
|
+
verified?: string[] | undefined;
|
|
498
|
+
verifiedBy?: string | undefined;
|
|
499
|
+
provenance?: {
|
|
500
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
501
|
+
url: string;
|
|
502
|
+
name?: string | undefined;
|
|
503
|
+
rel?: string | undefined;
|
|
504
|
+
}[] | undefined;
|
|
505
|
+
extensions?: {
|
|
506
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
507
|
+
} | undefined;
|
|
508
|
+
} | undefined;
|
|
348
509
|
attachments?: {
|
|
349
510
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
350
511
|
name: string;
|
|
@@ -361,6 +522,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
361
522
|
durationMs?: number | undefined;
|
|
362
523
|
description?: string | undefined;
|
|
363
524
|
omitted?: string | undefined;
|
|
525
|
+
scope?: {
|
|
526
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
527
|
+
surface?: string | undefined;
|
|
528
|
+
deviceKind?: string | undefined;
|
|
529
|
+
syntheticData?: boolean | undefined;
|
|
530
|
+
dependencies?: string | undefined;
|
|
531
|
+
audioCaptured?: boolean | undefined;
|
|
532
|
+
pacing?: string | undefined;
|
|
533
|
+
asserted?: string[] | undefined;
|
|
534
|
+
limitations?: string[] | undefined;
|
|
535
|
+
declaredBy?: string | undefined;
|
|
536
|
+
verified?: string[] | undefined;
|
|
537
|
+
verifiedBy?: string | undefined;
|
|
538
|
+
provenance?: {
|
|
539
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
540
|
+
url: string;
|
|
541
|
+
name?: string | undefined;
|
|
542
|
+
rel?: string | undefined;
|
|
543
|
+
}[] | undefined;
|
|
544
|
+
extensions?: {
|
|
545
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
546
|
+
} | undefined;
|
|
547
|
+
} | undefined;
|
|
364
548
|
tags?: string[] | undefined;
|
|
365
549
|
at?: {
|
|
366
550
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -380,6 +564,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
380
564
|
durationMs?: number | undefined;
|
|
381
565
|
startedAtMs?: number | undefined;
|
|
382
566
|
detail?: string | undefined;
|
|
567
|
+
scope?: {
|
|
568
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
569
|
+
surface?: string | undefined;
|
|
570
|
+
deviceKind?: string | undefined;
|
|
571
|
+
syntheticData?: boolean | undefined;
|
|
572
|
+
dependencies?: string | undefined;
|
|
573
|
+
audioCaptured?: boolean | undefined;
|
|
574
|
+
pacing?: string | undefined;
|
|
575
|
+
asserted?: string[] | undefined;
|
|
576
|
+
limitations?: string[] | undefined;
|
|
577
|
+
declaredBy?: string | undefined;
|
|
578
|
+
verified?: string[] | undefined;
|
|
579
|
+
verifiedBy?: string | undefined;
|
|
580
|
+
provenance?: {
|
|
581
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
582
|
+
url: string;
|
|
583
|
+
name?: string | undefined;
|
|
584
|
+
rel?: string | undefined;
|
|
585
|
+
}[] | undefined;
|
|
586
|
+
extensions?: {
|
|
587
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
588
|
+
} | undefined;
|
|
589
|
+
} | undefined;
|
|
383
590
|
steps?: {
|
|
384
591
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
385
592
|
name: string;
|
|
@@ -406,6 +613,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
406
613
|
durationMs?: number | undefined;
|
|
407
614
|
description?: string | undefined;
|
|
408
615
|
omitted?: string | undefined;
|
|
616
|
+
scope?: {
|
|
617
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
618
|
+
surface?: string | undefined;
|
|
619
|
+
deviceKind?: string | undefined;
|
|
620
|
+
syntheticData?: boolean | undefined;
|
|
621
|
+
dependencies?: string | undefined;
|
|
622
|
+
audioCaptured?: boolean | undefined;
|
|
623
|
+
pacing?: string | undefined;
|
|
624
|
+
asserted?: string[] | undefined;
|
|
625
|
+
limitations?: string[] | undefined;
|
|
626
|
+
declaredBy?: string | undefined;
|
|
627
|
+
verified?: string[] | undefined;
|
|
628
|
+
verifiedBy?: string | undefined;
|
|
629
|
+
provenance?: {
|
|
630
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
631
|
+
url: string;
|
|
632
|
+
name?: string | undefined;
|
|
633
|
+
rel?: string | undefined;
|
|
634
|
+
}[] | undefined;
|
|
635
|
+
extensions?: {
|
|
636
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
637
|
+
} | undefined;
|
|
638
|
+
} | undefined;
|
|
409
639
|
tags?: string[] | undefined;
|
|
410
640
|
at?: {
|
|
411
641
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -464,6 +694,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
464
694
|
durationMs?: number | undefined;
|
|
465
695
|
description?: string | undefined;
|
|
466
696
|
omitted?: string | undefined;
|
|
697
|
+
scope?: {
|
|
698
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
699
|
+
surface?: string | undefined;
|
|
700
|
+
deviceKind?: string | undefined;
|
|
701
|
+
syntheticData?: boolean | undefined;
|
|
702
|
+
dependencies?: string | undefined;
|
|
703
|
+
audioCaptured?: boolean | undefined;
|
|
704
|
+
pacing?: string | undefined;
|
|
705
|
+
asserted?: string[] | undefined;
|
|
706
|
+
limitations?: string[] | undefined;
|
|
707
|
+
declaredBy?: string | undefined;
|
|
708
|
+
verified?: string[] | undefined;
|
|
709
|
+
verifiedBy?: string | undefined;
|
|
710
|
+
provenance?: {
|
|
711
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
712
|
+
url: string;
|
|
713
|
+
name?: string | undefined;
|
|
714
|
+
rel?: string | undefined;
|
|
715
|
+
}[] | undefined;
|
|
716
|
+
extensions?: {
|
|
717
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
718
|
+
} | undefined;
|
|
719
|
+
} | undefined;
|
|
467
720
|
tags?: string[] | undefined;
|
|
468
721
|
at?: {
|
|
469
722
|
[x: string]: import("hono/utils/types").JSONValue;
|
|
@@ -532,6 +785,29 @@ export declare function createReportsExplorerApp(deps: ReportsExplorerDeps): imp
|
|
|
532
785
|
durationMs?: number | undefined;
|
|
533
786
|
description?: string | undefined;
|
|
534
787
|
omitted?: string | undefined;
|
|
788
|
+
scope?: {
|
|
789
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
790
|
+
surface?: string | undefined;
|
|
791
|
+
deviceKind?: string | undefined;
|
|
792
|
+
syntheticData?: boolean | undefined;
|
|
793
|
+
dependencies?: string | undefined;
|
|
794
|
+
audioCaptured?: boolean | undefined;
|
|
795
|
+
pacing?: string | undefined;
|
|
796
|
+
asserted?: string[] | undefined;
|
|
797
|
+
limitations?: string[] | undefined;
|
|
798
|
+
declaredBy?: string | undefined;
|
|
799
|
+
verified?: string[] | undefined;
|
|
800
|
+
verifiedBy?: string | undefined;
|
|
801
|
+
provenance?: {
|
|
802
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
803
|
+
url: string;
|
|
804
|
+
name?: string | undefined;
|
|
805
|
+
rel?: string | undefined;
|
|
806
|
+
}[] | undefined;
|
|
807
|
+
extensions?: {
|
|
808
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
809
|
+
} | undefined;
|
|
810
|
+
} | undefined;
|
|
535
811
|
tags?: string[] | undefined;
|
|
536
812
|
at?: {
|
|
537
813
|
[x: string]: import("hono/utils/types").JSONValue;
|