@progen-labs/spectra 0.1.3 → 0.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.
@@ -0,0 +1,749 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://unpkg.com/@progen-labs/spectra/schema/result.schema.json",
4
+ "title": "Spectra result",
5
+ "description": "What `spectra … --json` prints and `--out` writes. A small envelope that points at the full reports on disk. Additive changes keep schemaVersion; breaking changes bump it.",
6
+ "type": "object",
7
+ "required": [
8
+ "schemaVersion",
9
+ "kind",
10
+ "spectraVersion",
11
+ "createdAt"
12
+ ],
13
+ "properties": {
14
+ "schemaVersion": {
15
+ "const": 1
16
+ },
17
+ "kind": {
18
+ "enum": [
19
+ "profile",
20
+ "evaluation",
21
+ "compare",
22
+ "reports"
23
+ ]
24
+ },
25
+ "spectraVersion": {
26
+ "type": [
27
+ "string",
28
+ "null"
29
+ ]
30
+ },
31
+ "createdAt": {
32
+ "type": "string",
33
+ "format": "date-time"
34
+ }
35
+ },
36
+ "allOf": [
37
+ {
38
+ "if": {
39
+ "properties": {
40
+ "kind": {
41
+ "const": "profile"
42
+ }
43
+ }
44
+ },
45
+ "then": {
46
+ "$ref": "#/$defs/profile"
47
+ }
48
+ },
49
+ {
50
+ "if": {
51
+ "properties": {
52
+ "kind": {
53
+ "const": "evaluation"
54
+ }
55
+ }
56
+ },
57
+ "then": {
58
+ "$ref": "#/$defs/evaluation"
59
+ }
60
+ },
61
+ {
62
+ "if": {
63
+ "properties": {
64
+ "kind": {
65
+ "const": "compare"
66
+ }
67
+ }
68
+ },
69
+ "then": {
70
+ "$ref": "#/$defs/compare"
71
+ }
72
+ },
73
+ {
74
+ "if": {
75
+ "properties": {
76
+ "kind": {
77
+ "const": "reports"
78
+ }
79
+ }
80
+ },
81
+ "then": {
82
+ "$ref": "#/$defs/reports"
83
+ }
84
+ }
85
+ ],
86
+ "$defs": {
87
+ "summary": {
88
+ "type": "object",
89
+ "description": "Headline numbers; every one is lower-is-better. null when the recording did not measure it.",
90
+ "required": [
91
+ "tbtMs",
92
+ "lcpMs",
93
+ "fcpMs",
94
+ "cls",
95
+ "inpMs",
96
+ "ttfbMs",
97
+ "longTaskCount",
98
+ "maxLongTaskMs",
99
+ "scriptingMs",
100
+ "forcedLayoutCount",
101
+ "domNodes",
102
+ "heapUsedMb",
103
+ "transferKb",
104
+ "criticalFindings",
105
+ "findingCount"
106
+ ],
107
+ "properties": {
108
+ "tbtMs": {
109
+ "type": [
110
+ "number",
111
+ "null"
112
+ ],
113
+ "description": "Total blocking time (ms)"
114
+ },
115
+ "lcpMs": {
116
+ "type": [
117
+ "number",
118
+ "null"
119
+ ],
120
+ "description": "Largest contentful paint (ms)"
121
+ },
122
+ "fcpMs": {
123
+ "type": [
124
+ "number",
125
+ "null"
126
+ ],
127
+ "description": "First contentful paint (ms)"
128
+ },
129
+ "cls": {
130
+ "type": [
131
+ "number",
132
+ "null"
133
+ ],
134
+ "description": "Cumulative layout shift (score)"
135
+ },
136
+ "inpMs": {
137
+ "type": [
138
+ "number",
139
+ "null"
140
+ ],
141
+ "description": "Interaction to next paint (ms)"
142
+ },
143
+ "ttfbMs": {
144
+ "type": [
145
+ "number",
146
+ "null"
147
+ ],
148
+ "description": "Time to first byte (ms)"
149
+ },
150
+ "longTaskCount": {
151
+ "type": [
152
+ "number",
153
+ "null"
154
+ ],
155
+ "description": "Number of long tasks (> 50 ms)"
156
+ },
157
+ "maxLongTaskMs": {
158
+ "type": [
159
+ "number",
160
+ "null"
161
+ ],
162
+ "description": "Longest task (ms)"
163
+ },
164
+ "scriptingMs": {
165
+ "type": [
166
+ "number",
167
+ "null"
168
+ ],
169
+ "description": "JavaScript scripting time (ms)"
170
+ },
171
+ "forcedLayoutCount": {
172
+ "type": [
173
+ "number",
174
+ "null"
175
+ ],
176
+ "description": "Forced synchronous layouts"
177
+ },
178
+ "domNodes": {
179
+ "type": [
180
+ "number",
181
+ "null"
182
+ ],
183
+ "description": "DOM nodes"
184
+ },
185
+ "heapUsedMb": {
186
+ "type": [
187
+ "number",
188
+ "null"
189
+ ],
190
+ "description": "JS heap used (MB)"
191
+ },
192
+ "transferKb": {
193
+ "type": [
194
+ "number",
195
+ "null"
196
+ ],
197
+ "description": "Bytes transferred (KB)"
198
+ },
199
+ "criticalFindings": {
200
+ "type": [
201
+ "number",
202
+ "null"
203
+ ],
204
+ "description": "Critical findings"
205
+ },
206
+ "findingCount": {
207
+ "type": [
208
+ "number",
209
+ "null"
210
+ ],
211
+ "description": "All findings"
212
+ }
213
+ }
214
+ },
215
+ "summaryWithRuns": {
216
+ "allOf": [
217
+ {
218
+ "$ref": "#/$defs/summary"
219
+ }
220
+ ],
221
+ "properties": {
222
+ "runs": {
223
+ "type": "integer",
224
+ "minimum": 1,
225
+ "description": "How many runs the medians are taken over."
226
+ }
227
+ },
228
+ "required": [
229
+ "runs"
230
+ ]
231
+ },
232
+ "culprit": {
233
+ "type": "object",
234
+ "required": [
235
+ "fn",
236
+ "file",
237
+ "line"
238
+ ],
239
+ "properties": {
240
+ "fn": {
241
+ "type": "string"
242
+ },
243
+ "file": {
244
+ "type": [
245
+ "string",
246
+ "null"
247
+ ],
248
+ "description": "Path relative to the project root."
249
+ },
250
+ "line": {
251
+ "type": [
252
+ "integer",
253
+ "null"
254
+ ]
255
+ },
256
+ "lineKind": {
257
+ "type": [
258
+ "string",
259
+ "null"
260
+ ],
261
+ "description": "exact, or located (≈, found by searching the source)."
262
+ },
263
+ "abs": {
264
+ "type": [
265
+ "string",
266
+ "null"
267
+ ],
268
+ "description": "Absolute path on the machine that recorded it."
269
+ },
270
+ "ms": {
271
+ "type": [
272
+ "number",
273
+ "null"
274
+ ]
275
+ },
276
+ "note": {
277
+ "type": "string"
278
+ }
279
+ }
280
+ },
281
+ "finding": {
282
+ "type": "object",
283
+ "required": [
284
+ "id",
285
+ "severity",
286
+ "category",
287
+ "title",
288
+ "impactMs",
289
+ "fix",
290
+ "culprits"
291
+ ],
292
+ "properties": {
293
+ "id": {
294
+ "type": "string"
295
+ },
296
+ "severity": {
297
+ "enum": [
298
+ "critical",
299
+ "warning",
300
+ "info"
301
+ ]
302
+ },
303
+ "category": {
304
+ "type": "string"
305
+ },
306
+ "title": {
307
+ "type": "string"
308
+ },
309
+ "detail": {
310
+ "type": "string"
311
+ },
312
+ "impactMs": {
313
+ "type": "number"
314
+ },
315
+ "file": {
316
+ "type": [
317
+ "string",
318
+ "null"
319
+ ]
320
+ },
321
+ "line": {
322
+ "type": [
323
+ "integer",
324
+ "null"
325
+ ]
326
+ },
327
+ "fix": {
328
+ "type": "string"
329
+ },
330
+ "culprits": {
331
+ "type": "array",
332
+ "items": {
333
+ "$ref": "#/$defs/culprit"
334
+ }
335
+ },
336
+ "seenIn": {
337
+ "type": "integer",
338
+ "description": "Profiles with several runs: how many runs reported this finding."
339
+ }
340
+ }
341
+ },
342
+ "budgets": {
343
+ "description": "Budget checks; null when no budgets are configured.",
344
+ "oneOf": [
345
+ {
346
+ "type": "null"
347
+ },
348
+ {
349
+ "type": "object",
350
+ "required": [
351
+ "ok",
352
+ "failed",
353
+ "checks"
354
+ ],
355
+ "properties": {
356
+ "ok": {
357
+ "type": "boolean"
358
+ },
359
+ "failed": {
360
+ "type": "integer"
361
+ },
362
+ "checks": {
363
+ "type": "array",
364
+ "items": {
365
+ "type": "object",
366
+ "required": [
367
+ "key",
368
+ "limit",
369
+ "value",
370
+ "where",
371
+ "status"
372
+ ],
373
+ "properties": {
374
+ "key": {
375
+ "enum": [
376
+ "tbtMs",
377
+ "lcpMs",
378
+ "fcpMs",
379
+ "cls",
380
+ "inpMs",
381
+ "ttfbMs",
382
+ "longTaskCount",
383
+ "maxLongTaskMs",
384
+ "scriptingMs",
385
+ "forcedLayoutCount",
386
+ "domNodes",
387
+ "heapUsedMb",
388
+ "transferKb",
389
+ "criticalFindings",
390
+ "findingCount"
391
+ ]
392
+ },
393
+ "label": {
394
+ "type": "string"
395
+ },
396
+ "unit": {
397
+ "type": "string"
398
+ },
399
+ "limit": {
400
+ "type": "number"
401
+ },
402
+ "value": {
403
+ "type": [
404
+ "number",
405
+ "null"
406
+ ]
407
+ },
408
+ "where": {
409
+ "type": "string",
410
+ "description": "median, or the journey title."
411
+ },
412
+ "status": {
413
+ "enum": [
414
+ "pass",
415
+ "fail",
416
+ "skipped"
417
+ ]
418
+ }
419
+ }
420
+ }
421
+ }
422
+ }
423
+ }
424
+ ]
425
+ },
426
+ "profile": {
427
+ "type": "object",
428
+ "required": [
429
+ "target",
430
+ "url",
431
+ "mode",
432
+ "runs",
433
+ "representativeRunId",
434
+ "summary",
435
+ "spread",
436
+ "findings",
437
+ "budgets"
438
+ ],
439
+ "properties": {
440
+ "target": {
441
+ "type": [
442
+ "string",
443
+ "null"
444
+ ]
445
+ },
446
+ "url": {
447
+ "type": [
448
+ "string",
449
+ "null"
450
+ ]
451
+ },
452
+ "mode": {
453
+ "enum": [
454
+ "load",
455
+ "live",
456
+ null
457
+ ]
458
+ },
459
+ "cpuThrottle": {
460
+ "type": "number"
461
+ },
462
+ "git": {
463
+ "type": [
464
+ "object",
465
+ "null"
466
+ ]
467
+ },
468
+ "runs": {
469
+ "type": "array",
470
+ "minItems": 1,
471
+ "items": {
472
+ "type": "object",
473
+ "required": [
474
+ "id",
475
+ "file",
476
+ "summary"
477
+ ],
478
+ "properties": {
479
+ "id": {
480
+ "type": "string"
481
+ },
482
+ "file": {
483
+ "type": [
484
+ "string",
485
+ "null"
486
+ ],
487
+ "description": "The full report on disk."
488
+ },
489
+ "summary": {
490
+ "$ref": "#/$defs/summary"
491
+ }
492
+ }
493
+ }
494
+ },
495
+ "representativeRunId": {
496
+ "type": [
497
+ "string",
498
+ "null"
499
+ ],
500
+ "description": "The run closest to the medians; the findings come from it."
501
+ },
502
+ "summary": {
503
+ "$ref": "#/$defs/summaryWithRuns"
504
+ },
505
+ "spread": {
506
+ "type": "object",
507
+ "description": "min / max per metric across runs (several runs only).",
508
+ "additionalProperties": {
509
+ "type": "object",
510
+ "properties": {
511
+ "min": {
512
+ "type": "number"
513
+ },
514
+ "max": {
515
+ "type": "number"
516
+ }
517
+ }
518
+ }
519
+ },
520
+ "findings": {
521
+ "type": "array",
522
+ "items": {
523
+ "$ref": "#/$defs/finding"
524
+ }
525
+ },
526
+ "budgets": {
527
+ "$ref": "#/$defs/budgets"
528
+ }
529
+ }
530
+ },
531
+ "journey": {
532
+ "type": "object",
533
+ "required": [
534
+ "title",
535
+ "kind",
536
+ "ok",
537
+ "reportId",
538
+ "summary",
539
+ "findings"
540
+ ],
541
+ "properties": {
542
+ "title": {
543
+ "type": "string"
544
+ },
545
+ "kind": {
546
+ "type": "string"
547
+ },
548
+ "ok": {
549
+ "type": "boolean"
550
+ },
551
+ "error": {
552
+ "type": [
553
+ "string",
554
+ "null"
555
+ ]
556
+ },
557
+ "reportId": {
558
+ "type": [
559
+ "string",
560
+ "null"
561
+ ]
562
+ },
563
+ "reportFile": {
564
+ "type": [
565
+ "string",
566
+ "null"
567
+ ]
568
+ },
569
+ "summary": {
570
+ "oneOf": [
571
+ {
572
+ "type": "null"
573
+ },
574
+ {
575
+ "$ref": "#/$defs/summary"
576
+ }
577
+ ]
578
+ },
579
+ "findings": {
580
+ "type": "array",
581
+ "items": {
582
+ "$ref": "#/$defs/finding"
583
+ },
584
+ "description": "Top five findings of the journey."
585
+ }
586
+ }
587
+ },
588
+ "evaluation": {
589
+ "type": "object",
590
+ "required": [
591
+ "url",
592
+ "journeys",
593
+ "passed",
594
+ "total",
595
+ "budgets"
596
+ ],
597
+ "properties": {
598
+ "target": {
599
+ "type": [
600
+ "string",
601
+ "null"
602
+ ]
603
+ },
604
+ "url": {
605
+ "type": "string"
606
+ },
607
+ "file": {
608
+ "type": [
609
+ "string",
610
+ "null"
611
+ ]
612
+ },
613
+ "discovered": {
614
+ "type": "integer"
615
+ },
616
+ "skippedDestructive": {
617
+ "type": "array"
618
+ },
619
+ "passed": {
620
+ "type": "integer"
621
+ },
622
+ "total": {
623
+ "type": "integer"
624
+ },
625
+ "journeys": {
626
+ "type": "array",
627
+ "description": "The baseline page load first, then each golden path.",
628
+ "items": {
629
+ "$ref": "#/$defs/journey"
630
+ }
631
+ },
632
+ "budgets": {
633
+ "$ref": "#/$defs/budgets"
634
+ }
635
+ }
636
+ },
637
+ "compare": {
638
+ "type": "object",
639
+ "required": [
640
+ "comparison"
641
+ ],
642
+ "properties": {
643
+ "comparison": {
644
+ "type": "object",
645
+ "description": "The comparison from shared/compare.js (its own version field tracks that format).",
646
+ "required": [
647
+ "version",
648
+ "verdict",
649
+ "confidence",
650
+ "counts",
651
+ "headlines",
652
+ "metrics",
653
+ "findings",
654
+ "checks",
655
+ "before",
656
+ "after"
657
+ ],
658
+ "properties": {
659
+ "version": {
660
+ "type": "integer"
661
+ },
662
+ "verdict": {
663
+ "enum": [
664
+ "improved",
665
+ "regressed",
666
+ "mixed",
667
+ "neutral"
668
+ ]
669
+ },
670
+ "confidence": {
671
+ "enum": [
672
+ "high",
673
+ "medium",
674
+ "low"
675
+ ]
676
+ },
677
+ "metrics": {
678
+ "type": "array",
679
+ "items": {
680
+ "type": "object",
681
+ "required": [
682
+ "id",
683
+ "label",
684
+ "unit",
685
+ "key",
686
+ "verdict",
687
+ "before",
688
+ "after",
689
+ "delta",
690
+ "pct"
691
+ ],
692
+ "properties": {
693
+ "verdict": {
694
+ "enum": [
695
+ "improved",
696
+ "degraded",
697
+ "same",
698
+ "n/a"
699
+ ]
700
+ },
701
+ "key": {
702
+ "type": "boolean",
703
+ "description": "Counts toward the overall verdict."
704
+ }
705
+ }
706
+ }
707
+ },
708
+ "findings": {
709
+ "type": "object",
710
+ "required": [
711
+ "added",
712
+ "resolved",
713
+ "persisting"
714
+ ]
715
+ }
716
+ }
717
+ }
718
+ }
719
+ },
720
+ "reports": {
721
+ "type": "object",
722
+ "required": [
723
+ "reports"
724
+ ],
725
+ "properties": {
726
+ "dir": {
727
+ "type": [
728
+ "string",
729
+ "null"
730
+ ]
731
+ },
732
+ "reports": {
733
+ "type": "array",
734
+ "items": {
735
+ "type": "object",
736
+ "required": [
737
+ "id",
738
+ "createdAt",
739
+ "url",
740
+ "mode",
741
+ "findings",
742
+ "critical"
743
+ ]
744
+ }
745
+ }
746
+ }
747
+ }
748
+ }
749
+ }