@crvouga/atlas 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/playwright-reporter/src/index.d.ts +11 -0
  3. package/dist/playwright-reporter/src/index.js +4 -2
  4. package/dist/reports/src/evidence-types.d.ts +3 -0
  5. package/dist/reports/src/layer-merge.d.ts +1 -1
  6. package/dist/reports/src/layer-merge.js +3 -2
  7. package/dist/reports/src/layer-types.d.ts +3 -0
  8. package/dist/reports/src/publish-checks.js +1 -0
  9. package/dist/reports/src/report-cli.d.ts +1 -1
  10. package/dist/reports/src/report-cli.js +30 -2
  11. package/dist/reports/src/reporter.d.ts +1 -1
  12. package/dist/reports/src/test-catalog.d.ts +20 -4
  13. package/dist/reports/src/test-catalog.js +31 -8
  14. package/dist/schema/src/api.d.ts +49 -1
  15. package/dist/schema/src/api.js +7 -3
  16. package/dist/schema/src/layer.d.ts +26 -0
  17. package/dist/schema/src/layer.js +17 -0
  18. package/docs/integrating.md +8 -0
  19. package/docs/reference/cli.md +7 -0
  20. package/docs/reference/playwright-reporter.md +6 -6
  21. package/docs/reference/reports.md +18 -6
  22. package/docs/reference/schema.md +20 -1
  23. package/docs/report-contract.md +1 -0
  24. package/llms-full.txt +16 -0
  25. package/package.json +1 -1
  26. package/packages/schema/schemas/effective-delta.schema.json +30 -0
  27. package/packages/schema/schemas/effective-evidence.schema.json +30 -0
  28. package/packages/schema/schemas/evidence-page.schema.json +30 -0
  29. package/packages/schema/schemas/layer.schema.json +30 -0
  30. package/packages/schema/schemas/publish-checks.schema.json +30 -0
  31. package/packages/schema/schemas/report-run.schema.json +17 -1
  32. package/packages/schema/schemas/report-runs.schema.json +17 -1
  33. package/packages/server/openapi.json +154 -2
  34. package/packages/visualizer/src/explorer/RunsView.tsx +23 -4
  35. package/packages/visualizer/src/explorer/parts.tsx +2 -1
@@ -7575,6 +7575,36 @@
7575
7575
  "modified"
7576
7576
  ]
7577
7577
  },
7578
+ "run": {
7579
+ "description": "The execution the producer named for it (one local or manual invocation). Grouping and display only; never part of the slot",
7580
+ "type": "object",
7581
+ "properties": {
7582
+ "id": {
7583
+ "type": "string",
7584
+ "minLength": 1,
7585
+ "maxLength": 256,
7586
+ "description": "The execution's identity within a project, chosen by the producer: a UUID, a timestamped name. Layers with the same id are one run; it never changes after it is recorded"
7587
+ },
7588
+ "title": {
7589
+ "description": "A human name for the run. Presentation only: it is not part of the identity and does not hide the commit or `freshness`",
7590
+ "type": "string"
7591
+ },
7592
+ "startedAtMs": {
7593
+ "description": "When the execution started, epoch milliseconds",
7594
+ "type": "number",
7595
+ "minimum": 0
7596
+ },
7597
+ "endedAtMs": {
7598
+ "description": "When the execution ended, epoch milliseconds",
7599
+ "type": "number",
7600
+ "minimum": 0
7601
+ }
7602
+ },
7603
+ "required": [
7604
+ "id"
7605
+ ],
7606
+ "additionalProperties": {}
7607
+ },
7578
7608
  "recording": {
7579
7609
  "anyOf": [
7580
7610
  {},
@@ -8018,6 +8048,36 @@
8018
8048
  "modified"
8019
8049
  ]
8020
8050
  },
8051
+ "run": {
8052
+ "description": "The execution the producer named for it (one local or manual invocation). Grouping and display only; never part of the slot",
8053
+ "type": "object",
8054
+ "properties": {
8055
+ "id": {
8056
+ "type": "string",
8057
+ "minLength": 1,
8058
+ "maxLength": 256,
8059
+ "description": "The execution's identity within a project, chosen by the producer: a UUID, a timestamped name. Layers with the same id are one run; it never changes after it is recorded"
8060
+ },
8061
+ "title": {
8062
+ "description": "A human name for the run. Presentation only: it is not part of the identity and does not hide the commit or `freshness`",
8063
+ "type": "string"
8064
+ },
8065
+ "startedAtMs": {
8066
+ "description": "When the execution started, epoch milliseconds",
8067
+ "type": "number",
8068
+ "minimum": 0
8069
+ },
8070
+ "endedAtMs": {
8071
+ "description": "When the execution ended, epoch milliseconds",
8072
+ "type": "number",
8073
+ "minimum": 0
8074
+ }
8075
+ },
8076
+ "required": [
8077
+ "id"
8078
+ ],
8079
+ "additionalProperties": {}
8080
+ },
8021
8081
  "recording": {
8022
8082
  "anyOf": [
8023
8083
  {},
@@ -9683,6 +9743,36 @@
9683
9743
  "modified"
9684
9744
  ]
9685
9745
  },
9746
+ "run": {
9747
+ "description": "Name the execution these checks belong to, so repeated local runs at one commit stay separate runs and shards of one execution stay together",
9748
+ "type": "object",
9749
+ "properties": {
9750
+ "id": {
9751
+ "type": "string",
9752
+ "minLength": 1,
9753
+ "maxLength": 256,
9754
+ "description": "The execution's identity within a project, chosen by the producer: a UUID, a timestamped name. Layers with the same id are one run; it never changes after it is recorded"
9755
+ },
9756
+ "title": {
9757
+ "description": "A human name for the run. Presentation only: it is not part of the identity and does not hide the commit or `freshness`",
9758
+ "type": "string"
9759
+ },
9760
+ "startedAtMs": {
9761
+ "description": "When the execution started, epoch milliseconds",
9762
+ "type": "number",
9763
+ "minimum": 0
9764
+ },
9765
+ "endedAtMs": {
9766
+ "description": "When the execution ended, epoch milliseconds",
9767
+ "type": "number",
9768
+ "minimum": 0
9769
+ }
9770
+ },
9771
+ "required": [
9772
+ "id"
9773
+ ],
9774
+ "additionalProperties": {}
9775
+ },
9686
9776
  "specs": {
9687
9777
  "default": [],
9688
9778
  "type": "array",
@@ -10171,6 +10261,36 @@
10171
10261
  "modified"
10172
10262
  ]
10173
10263
  },
10264
+ "run": {
10265
+ "description": "The execution the producer named for it (one local or manual invocation). Grouping and display only; never part of the slot",
10266
+ "type": "object",
10267
+ "properties": {
10268
+ "id": {
10269
+ "type": "string",
10270
+ "minLength": 1,
10271
+ "maxLength": 256,
10272
+ "description": "The execution's identity within a project, chosen by the producer: a UUID, a timestamped name. Layers with the same id are one run; it never changes after it is recorded"
10273
+ },
10274
+ "title": {
10275
+ "description": "A human name for the run. Presentation only: it is not part of the identity and does not hide the commit or `freshness`",
10276
+ "type": "string"
10277
+ },
10278
+ "startedAtMs": {
10279
+ "description": "When the execution started, epoch milliseconds",
10280
+ "type": "number",
10281
+ "minimum": 0
10282
+ },
10283
+ "endedAtMs": {
10284
+ "description": "When the execution ended, epoch milliseconds",
10285
+ "type": "number",
10286
+ "minimum": 0
10287
+ }
10288
+ },
10289
+ "required": [
10290
+ "id"
10291
+ ],
10292
+ "additionalProperties": {}
10293
+ },
10174
10294
  "recording": {
10175
10295
  "anyOf": [
10176
10296
  {},
@@ -13747,7 +13867,23 @@
13747
13867
  "properties": {
13748
13868
  "key": {
13749
13869
  "type": "string",
13750
- "description": "The run URL, or `branch@sha`. Pass it to `/api/reports/runs/detail?key=` or `/api/reports/tests?run=`"
13870
+ "description": "`run:<id>` for an execution a producer named, else the run URL, else `branch@sha`. Pass it to `/api/reports/runs/detail?key=` or `/api/reports/tests?run=`"
13871
+ },
13872
+ "runId": {
13873
+ "description": "The execution id the producer named, when it did. Layers that share it are one run however many uploads they took",
13874
+ "type": "string"
13875
+ },
13876
+ "title": {
13877
+ "description": "The human title of the execution (the newest layer's). Presentation only: the key, commit and `freshness` are unaffected",
13878
+ "type": "string"
13879
+ },
13880
+ "freshness": {
13881
+ "description": "`modified` when any layer of the run was recorded from a checkout with uncommitted changes; `unknown` when an origin was not captured; absent when all are clean. Shown beside the commit, never replaced by the title",
13882
+ "type": "string",
13883
+ "enum": [
13884
+ "unknown",
13885
+ "modified"
13886
+ ]
13751
13887
  },
13752
13888
  "runUrl": {
13753
13889
  "type": [
@@ -13901,7 +14037,23 @@
13901
14037
  "properties": {
13902
14038
  "key": {
13903
14039
  "type": "string",
13904
- "description": "The run URL, or `branch@sha`. Pass it to `/api/reports/runs/detail?key=` or `/api/reports/tests?run=`"
14040
+ "description": "`run:<id>` for an execution a producer named, else the run URL, else `branch@sha`. Pass it to `/api/reports/runs/detail?key=` or `/api/reports/tests?run=`"
14041
+ },
14042
+ "runId": {
14043
+ "description": "The execution id the producer named, when it did. Layers that share it are one run however many uploads they took",
14044
+ "type": "string"
14045
+ },
14046
+ "title": {
14047
+ "description": "The human title of the execution (the newest layer's). Presentation only: the key, commit and `freshness` are unaffected",
14048
+ "type": "string"
14049
+ },
14050
+ "freshness": {
14051
+ "description": "`modified` when any layer of the run was recorded from a checkout with uncommitted changes; `unknown` when an origin was not captured; absent when all are clean. Shown beside the commit, never replaced by the title",
14052
+ "type": "string",
14053
+ "enum": [
14054
+ "unknown",
14055
+ "modified"
14056
+ ]
13905
14057
  },
13906
14058
  "runUrl": {
13907
14059
  "type": [
@@ -23,6 +23,19 @@ export function RunsView() {
23
23
  const search = useExplorerSearch();
24
24
  return search.openRun ? <RunDetailView runKey={search.openRun} /> : <RunTable />;
25
25
  }
26
+ /** What a run is called: the title its producer gave it, else its CI run number or `branch@sha`. */
27
+ function runLabel(run: RunSummary): string {
28
+ return run.title ?? runName(run.key);
29
+ }
30
+ /** Beside a commit: said whenever the run was not recorded from a clean checkout, whatever the run is titled. */
31
+ function Freshness({ run }: { run: RunSummary }) {
32
+ if (!run.freshness) return null;
33
+ return (
34
+ <Text span inherit c="dimmed">
35
+ {run.freshness === 'modified' ? 'with local changes' : 'origin not captured'}
36
+ </Text>
37
+ );
38
+ }
26
39
  function Counts({ run }: { run: RunSummary }) {
27
40
  return (
28
41
  <Text span inherit>
@@ -98,19 +111,24 @@ function RunTable() {
98
111
  <Table.Tr key={run.key} data-status={run.counts.failed ? 'failed' : 'passed'}>
99
112
  <Table.Td title={exactTime(run.endedAtMs)}>
100
113
  <Anchor
101
- aria-label={`Open run ${runName(run.key)}`}
114
+ aria-label={`Open run ${runLabel(run)}`}
102
115
  renderRoot={(props) => (
103
116
  <Link {...props} to="/" search={patched({ openRun: run.key })} resetScroll={false} activeOptions={{ exact: true }} />
104
117
  )}
105
118
  >
106
119
  {ago(run.endedAtMs, now)}
107
120
  </Anchor>
121
+ {run.title && (
122
+ <Text c="dimmed" fz="xs">
123
+ {run.title}
124
+ </Text>
125
+ )}
108
126
  </Table.Td>
109
127
  <Table.Td title={run.branch ?? ''} c="dimmed">
110
128
  {run.branch ?? '—'}
111
129
  </Table.Td>
112
130
  <Table.Td>
113
- <Code>{shortSha(run.sha) ?? '—'}</Code>
131
+ <Code>{shortSha(run.sha) ?? '—'}</Code> <Freshness run={run} />
114
132
  </Table.Td>
115
133
  <Table.Td>{run.environments.map((env) => environmentLabel(env)).join(', ') || '—'}</Table.Td>
116
134
  <Table.Td>{run.tests}</Table.Td>
@@ -215,10 +233,10 @@ function RunDetailView({ runKey }: { runKey: string }) {
215
233
  );
216
234
  const { run } = detail.data;
217
235
  return (
218
- <Box aria-label={`Run ${runName(run.key)}`} component="section" mb="lg">
236
+ <Box aria-label={`Run ${runLabel(run)}`} component="section" mb="lg">
219
237
  {back}
220
238
  <Title order={2} mb="sm">
221
- Run {runName(run.key)}
239
+ Run {runLabel(run)}
222
240
  </Title>
223
241
  <Text component="div">
224
242
  {run.branch && (
@@ -227,6 +245,7 @@ function RunDetailView({ runKey }: { runKey: string }) {
227
245
  </Text>
228
246
  )}
229
247
  {run.sha && <Code>{shortSha(run.sha)}</Code>}
248
+ <Freshness run={run} />
230
249
  <Text title={exactTime(run.endedAtMs)} span inherit>
231
250
  ended {ago(run.endedAtMs, now)}
232
251
  </Text>
@@ -21,8 +21,9 @@ export function projectTitle(): string {
21
21
  .join(' ') || 'Project reports'
22
22
  );
23
23
  }
24
- /** A run key for a person: its CI run number, or `branch@sha` shortened. */
24
+ /** A run key for a person: the execution id a producer named, its CI run number, or `branch@sha` shortened. */
25
25
  export function runName(key: string): string {
26
+ if (key.startsWith('run:')) return key.slice(4);
26
27
  const actions = /\/actions\/runs\/(\d+)/.exec(key);
27
28
  if (actions) return `#${actions[1]}`;
28
29
  if (/^https?:/.test(key)) return key.replace(/^https?:\/\//, '').slice(0, 40);