@monoes/monobrowse 1.0.12 → 1.0.13

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 (175) hide show
  1. package/dist/src/__tests__/profiler-heap.test.d.ts +2 -0
  2. package/dist/src/__tests__/profiler-heap.test.d.ts.map +1 -0
  3. package/dist/src/__tests__/profiler-heap.test.js +154 -0
  4. package/dist/src/__tests__/profiler-heap.test.js.map +1 -0
  5. package/dist/src/__tests__/report-a11y.test.d.ts +2 -0
  6. package/dist/src/__tests__/report-a11y.test.d.ts.map +1 -0
  7. package/dist/src/__tests__/report-a11y.test.js +147 -0
  8. package/dist/src/__tests__/report-a11y.test.js.map +1 -0
  9. package/dist/src/__tests__/report-analyze.test.d.ts +2 -0
  10. package/dist/src/__tests__/report-analyze.test.d.ts.map +1 -0
  11. package/dist/src/__tests__/report-analyze.test.js +157 -0
  12. package/dist/src/__tests__/report-analyze.test.js.map +1 -0
  13. package/dist/src/__tests__/report-budget.test.d.ts +2 -0
  14. package/dist/src/__tests__/report-budget.test.d.ts.map +1 -0
  15. package/dist/src/__tests__/report-budget.test.js +80 -0
  16. package/dist/src/__tests__/report-budget.test.js.map +1 -0
  17. package/dist/src/__tests__/report-diff.test.d.ts +2 -0
  18. package/dist/src/__tests__/report-diff.test.d.ts.map +1 -0
  19. package/dist/src/__tests__/report-diff.test.js +231 -0
  20. package/dist/src/__tests__/report-diff.test.js.map +1 -0
  21. package/dist/src/__tests__/report-evidence.test.d.ts +2 -0
  22. package/dist/src/__tests__/report-evidence.test.d.ts.map +1 -0
  23. package/dist/src/__tests__/report-evidence.test.js +214 -0
  24. package/dist/src/__tests__/report-evidence.test.js.map +1 -0
  25. package/dist/src/__tests__/report-flake.test.d.ts +2 -0
  26. package/dist/src/__tests__/report-flake.test.d.ts.map +1 -0
  27. package/dist/src/__tests__/report-flake.test.js +182 -0
  28. package/dist/src/__tests__/report-flake.test.js.map +1 -0
  29. package/dist/src/__tests__/report-history.test.d.ts +2 -0
  30. package/dist/src/__tests__/report-history.test.d.ts.map +1 -0
  31. package/dist/src/__tests__/report-history.test.js +229 -0
  32. package/dist/src/__tests__/report-history.test.js.map +1 -0
  33. package/dist/src/__tests__/report-output.test.d.ts +2 -0
  34. package/dist/src/__tests__/report-output.test.d.ts.map +1 -0
  35. package/dist/src/__tests__/report-output.test.js +169 -0
  36. package/dist/src/__tests__/report-output.test.js.map +1 -0
  37. package/dist/src/__tests__/report-png.test.d.ts +2 -0
  38. package/dist/src/__tests__/report-png.test.d.ts.map +1 -0
  39. package/dist/src/__tests__/report-png.test.js +84 -0
  40. package/dist/src/__tests__/report-png.test.js.map +1 -0
  41. package/dist/src/__tests__/report-render-extras.test.d.ts +2 -0
  42. package/dist/src/__tests__/report-render-extras.test.d.ts.map +1 -0
  43. package/dist/src/__tests__/report-render-extras.test.js +285 -0
  44. package/dist/src/__tests__/report-render-extras.test.js.map +1 -0
  45. package/dist/src/__tests__/report-render.test.d.ts +2 -0
  46. package/dist/src/__tests__/report-render.test.d.ts.map +1 -0
  47. package/dist/src/__tests__/report-render.test.js +143 -0
  48. package/dist/src/__tests__/report-render.test.js.map +1 -0
  49. package/dist/src/__tests__/report-run.test.d.ts +2 -0
  50. package/dist/src/__tests__/report-run.test.d.ts.map +1 -0
  51. package/dist/src/__tests__/report-run.test.js +234 -0
  52. package/dist/src/__tests__/report-run.test.js.map +1 -0
  53. package/dist/src/browser/index.d.ts +1 -0
  54. package/dist/src/browser/index.d.ts.map +1 -1
  55. package/dist/src/browser/index.js +1 -0
  56. package/dist/src/browser/index.js.map +1 -1
  57. package/dist/src/browser/profiler.d.ts.map +1 -1
  58. package/dist/src/browser/profiler.js +19 -22
  59. package/dist/src/browser/profiler.js.map +1 -1
  60. package/dist/src/cli/commands.d.ts.map +1 -1
  61. package/dist/src/cli/commands.js +254 -0
  62. package/dist/src/cli/commands.js.map +1 -1
  63. package/dist/src/report/a11y.d.ts +52 -0
  64. package/dist/src/report/a11y.d.ts.map +1 -0
  65. package/dist/src/report/a11y.js +231 -0
  66. package/dist/src/report/a11y.js.map +1 -0
  67. package/dist/src/report/analyze.d.ts +20 -0
  68. package/dist/src/report/analyze.d.ts.map +1 -0
  69. package/dist/src/report/analyze.js +136 -0
  70. package/dist/src/report/analyze.js.map +1 -0
  71. package/dist/src/report/budget.d.ts +27 -0
  72. package/dist/src/report/budget.d.ts.map +1 -0
  73. package/dist/src/report/budget.js +143 -0
  74. package/dist/src/report/budget.js.map +1 -0
  75. package/dist/src/report/collect-a11y.d.ts +25 -0
  76. package/dist/src/report/collect-a11y.d.ts.map +1 -0
  77. package/dist/src/report/collect-a11y.js +154 -0
  78. package/dist/src/report/collect-a11y.js.map +1 -0
  79. package/dist/src/report/collect.d.ts +45 -0
  80. package/dist/src/report/collect.d.ts.map +1 -0
  81. package/dist/src/report/collect.js +275 -0
  82. package/dist/src/report/collect.js.map +1 -0
  83. package/dist/src/report/evidence.d.ts +80 -0
  84. package/dist/src/report/evidence.d.ts.map +1 -0
  85. package/dist/src/report/evidence.js +279 -0
  86. package/dist/src/report/evidence.js.map +1 -0
  87. package/dist/src/report/flake.d.ts +88 -0
  88. package/dist/src/report/flake.d.ts.map +1 -0
  89. package/dist/src/report/flake.js +232 -0
  90. package/dist/src/report/flake.js.map +1 -0
  91. package/dist/src/report/history.d.ts +85 -0
  92. package/dist/src/report/history.d.ts.map +1 -0
  93. package/dist/src/report/history.js +176 -0
  94. package/dist/src/report/history.js.map +1 -0
  95. package/dist/src/report/index.d.ts +102 -0
  96. package/dist/src/report/index.d.ts.map +1 -0
  97. package/dist/src/report/index.js +216 -0
  98. package/dist/src/report/index.js.map +1 -0
  99. package/dist/src/report/pixel-diff.d.ts +30 -0
  100. package/dist/src/report/pixel-diff.d.ts.map +1 -0
  101. package/dist/src/report/pixel-diff.js +175 -0
  102. package/dist/src/report/pixel-diff.js.map +1 -0
  103. package/dist/src/report/png.d.ts +28 -0
  104. package/dist/src/report/png.d.ts.map +1 -0
  105. package/dist/src/report/png.js +259 -0
  106. package/dist/src/report/png.js.map +1 -0
  107. package/dist/src/report/render-evidence.d.ts +16 -0
  108. package/dist/src/report/render-evidence.d.ts.map +1 -0
  109. package/dist/src/report/render-evidence.js +174 -0
  110. package/dist/src/report/render-evidence.js.map +1 -0
  111. package/dist/src/report/render-trend.d.ts +16 -0
  112. package/dist/src/report/render-trend.d.ts.map +1 -0
  113. package/dist/src/report/render-trend.js +194 -0
  114. package/dist/src/report/render-trend.js.map +1 -0
  115. package/dist/src/report/render.d.ts +21 -0
  116. package/dist/src/report/render.d.ts.map +1 -0
  117. package/dist/src/report/render.js +286 -0
  118. package/dist/src/report/render.js.map +1 -0
  119. package/dist/src/report/run-diff.d.ts +18 -0
  120. package/dist/src/report/run-diff.d.ts.map +1 -0
  121. package/dist/src/report/run-diff.js +51 -0
  122. package/dist/src/report/run-diff.js.map +1 -0
  123. package/dist/src/report/structure.d.ts +41 -0
  124. package/dist/src/report/structure.d.ts.map +1 -0
  125. package/dist/src/report/structure.js +210 -0
  126. package/dist/src/report/structure.js.map +1 -0
  127. package/dist/src/report/trend.d.ts +26 -0
  128. package/dist/src/report/trend.d.ts.map +1 -0
  129. package/dist/src/report/trend.js +164 -0
  130. package/dist/src/report/trend.js.map +1 -0
  131. package/dist/src/report/types.d.ts +320 -0
  132. package/dist/src/report/types.d.ts.map +1 -0
  133. package/dist/src/report/types.js +11 -0
  134. package/dist/src/report/types.js.map +1 -0
  135. package/dist/src/report/util.d.ts +17 -0
  136. package/dist/src/report/util.d.ts.map +1 -0
  137. package/dist/src/report/util.js +45 -0
  138. package/dist/src/report/util.js.map +1 -0
  139. package/dist/tsconfig.tsbuildinfo +1 -1
  140. package/package.json +1 -1
  141. package/src/__tests__/profiler-heap.test.ts +191 -0
  142. package/src/__tests__/report-a11y.test.ts +180 -0
  143. package/src/__tests__/report-analyze.test.ts +202 -0
  144. package/src/__tests__/report-budget.test.ts +92 -0
  145. package/src/__tests__/report-diff.test.ts +272 -0
  146. package/src/__tests__/report-evidence.test.ts +276 -0
  147. package/src/__tests__/report-flake.test.ts +214 -0
  148. package/src/__tests__/report-history.test.ts +293 -0
  149. package/src/__tests__/report-output.test.ts +210 -0
  150. package/src/__tests__/report-png.test.ts +95 -0
  151. package/src/__tests__/report-render-extras.test.ts +315 -0
  152. package/src/__tests__/report-render.test.ts +175 -0
  153. package/src/__tests__/report-run.test.ts +264 -0
  154. package/src/browser/index.ts +1 -0
  155. package/src/browser/profiler.ts +28 -21
  156. package/src/cli/commands.ts +272 -0
  157. package/src/report/a11y.ts +242 -0
  158. package/src/report/analyze.ts +181 -0
  159. package/src/report/budget.ts +155 -0
  160. package/src/report/collect-a11y.ts +200 -0
  161. package/src/report/collect.ts +408 -0
  162. package/src/report/evidence.ts +379 -0
  163. package/src/report/flake.ts +303 -0
  164. package/src/report/history.ts +219 -0
  165. package/src/report/index.ts +307 -0
  166. package/src/report/pixel-diff.ts +197 -0
  167. package/src/report/png.ts +290 -0
  168. package/src/report/render-evidence.ts +194 -0
  169. package/src/report/render-trend.ts +225 -0
  170. package/src/report/render.ts +314 -0
  171. package/src/report/run-diff.ts +63 -0
  172. package/src/report/structure.ts +212 -0
  173. package/src/report/trend.ts +189 -0
  174. package/src/report/types.ts +356 -0
  175. package/src/report/util.ts +48 -0
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Recorded evidence for a bug report (RIG-11).
3
+ *
4
+ * When a run breaches its budget, "LCP was 4.1s" is a number; the frames
5
+ * either side of the moment it went wrong, lined up against the console and
6
+ * network entries from the same instant, is a bug report. This module records
7
+ * the frames and assembles that timeline.
8
+ *
9
+ * Size is the hard constraint. A screencast is tens of megabytes and a report
10
+ * is a single self-contained HTML file, so there are three separate bounds:
11
+ * the recorder's ring buffer (what we hold in memory), the frame selection
12
+ * (what we attach), and a byte budget applied over the selection. Nothing
13
+ * here can produce a 200MB report.
14
+ *
15
+ * `startEvidenceRecorder` talks to Chrome; everything below it is pure and
16
+ * unit-tested against fixture frames.
17
+ */
18
+ const DEFAULT_MAX_BUFFER_FRAMES = 160;
19
+ const DEFAULT_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
20
+ /**
21
+ * Halve the temporal resolution of the buffer instead of dropping its head.
22
+ *
23
+ * A plain ring buffer keeps the end of the run, which is the wrong half: a
24
+ * page that throws during load has its evidence at the start. Decimating
25
+ * keeps coverage of the whole run and merely coarsens it, which degrades the
26
+ * timeline gracefully however long the run turns out to be.
27
+ */
28
+ function decimate(frames) {
29
+ const kept = frames.filter((_, i) => i % 2 === 0);
30
+ return { kept, dropped: frames.length - kept.length };
31
+ }
32
+ export async function startEvidenceRecorder(client, sessionId, startedAtMs, options = {}) {
33
+ const maxFrames = options.maxFrames ?? DEFAULT_MAX_BUFFER_FRAMES;
34
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BUFFER_BYTES;
35
+ const recorder = {
36
+ frames: [],
37
+ droppedFrames: 0,
38
+ stop: async () => { },
39
+ };
40
+ let bytes = 0;
41
+ const off = client.on('Page.screencastFrame', (params, sid) => {
42
+ if (sid !== sessionId)
43
+ return;
44
+ const p = params;
45
+ // Ack first and unconditionally: Chrome stops sending frames until the
46
+ // previous one is acknowledged, so a failure to ack silently ends the
47
+ // recording.
48
+ if (p.sessionId !== undefined) {
49
+ void client
50
+ .send('Page.screencastFrameAck', { sessionId: p.sessionId }, sessionId)
51
+ .catch(() => { });
52
+ }
53
+ if (!p.data)
54
+ return;
55
+ recorder.frames.push({
56
+ offsetMs: Math.max(0, Date.now() - startedAtMs),
57
+ data: p.data,
58
+ bytes: p.data.length,
59
+ });
60
+ bytes += p.data.length;
61
+ if (recorder.frames.length > maxFrames || bytes > maxBytes) {
62
+ const { kept, dropped } = decimate(recorder.frames);
63
+ recorder.frames = kept;
64
+ recorder.droppedFrames += dropped;
65
+ bytes = kept.reduce((sum, f) => sum + f.bytes, 0);
66
+ }
67
+ });
68
+ // Idempotent: collect() stops the recorder once the interesting part of the
69
+ // run is over and again in its `finally`, and Chrome errors on stopping a
70
+ // screencast that is already stopped.
71
+ let stopped = false;
72
+ recorder.stop = async () => {
73
+ if (stopped)
74
+ return;
75
+ stopped = true;
76
+ off();
77
+ await client.send('Page.stopScreencast', {}, sessionId).catch(() => { });
78
+ };
79
+ try {
80
+ await client.send('Page.startScreencast', {
81
+ format: 'jpeg',
82
+ quality: options.quality ?? 60,
83
+ everyNthFrame: options.everyNthFrame ?? 2,
84
+ maxWidth: options.maxWidth ?? 900,
85
+ maxHeight: options.maxHeight ?? 1600,
86
+ }, sessionId);
87
+ }
88
+ catch (err) {
89
+ off();
90
+ throw err;
91
+ }
92
+ return recorder;
93
+ }
94
+ const DEFAULT_ATTACH_FRAMES = 12;
95
+ const DEFAULT_ATTACH_BYTES = 6 * 1024 * 1024;
96
+ const DEFAULT_WINDOW_MS = 4000;
97
+ /**
98
+ * Pick the frames to attach.
99
+ *
100
+ * With a focus offset, frames nearest it win — that is the moment being
101
+ * explained. Without one (a vitals-only breach has no instant), the run is
102
+ * sampled evenly so the reader still sees it load. The byte budget is applied
103
+ * last, evicting the least relevant frame first, so the cap is never reached
104
+ * by truncating the interesting end.
105
+ */
106
+ export function selectFrames(frames, focusOffsetMs, options = {}) {
107
+ const maxFrames = Math.max(1, options.maxFrames ?? DEFAULT_ATTACH_FRAMES);
108
+ const maxBytes = options.maxBytes ?? DEFAULT_ATTACH_BYTES;
109
+ const windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;
110
+ if (!frames.length)
111
+ return { frames: [], dropped: 0 };
112
+ let ranked;
113
+ if (focusOffsetMs === null) {
114
+ if (frames.length <= maxFrames) {
115
+ ranked = [...frames];
116
+ }
117
+ else {
118
+ const step = (frames.length - 1) / (maxFrames - 1 || 1);
119
+ const picked = new Set();
120
+ for (let i = 0; i < maxFrames; i++)
121
+ picked.add(Math.round(i * step));
122
+ ranked = [...picked].sort((a, b) => a - b).map((i) => frames[i]);
123
+ }
124
+ }
125
+ else {
126
+ const distance = (f) => Math.abs(f.offsetMs - focusOffsetMs);
127
+ const inWindow = frames.filter((f) => distance(f) <= windowMs);
128
+ // Fall back to the nearest frames overall rather than attaching none: a
129
+ // failure whose frames all fell outside the window still deserves context.
130
+ const pool = inWindow.length ? inWindow : [...frames];
131
+ ranked = [...pool].sort((a, b) => distance(a) - distance(b)).slice(0, maxFrames);
132
+ }
133
+ let dropped = frames.length - ranked.length;
134
+ let total = ranked.reduce((sum, f) => sum + f.bytes, 0);
135
+ if (total > maxBytes) {
136
+ const order = focusOffsetMs === null
137
+ ? [...ranked]
138
+ : [...ranked].sort((a, b) => Math.abs(a.offsetMs - focusOffsetMs) - Math.abs(b.offsetMs - focusOffsetMs));
139
+ const keep = new Set();
140
+ let used = 0;
141
+ for (const frame of order) {
142
+ if (used + frame.bytes > maxBytes)
143
+ continue;
144
+ keep.add(frame);
145
+ used += frame.bytes;
146
+ }
147
+ dropped += ranked.length - keep.size;
148
+ ranked = ranked.filter((f) => keep.has(f));
149
+ total = used;
150
+ }
151
+ return { frames: ranked.sort((a, b) => a.offsetMs - b.offsetMs), dropped };
152
+ }
153
+ const DEFAULT_MAX_EVENTS = 60;
154
+ function truncate(text, max = 200) {
155
+ const flat = String(text ?? '')
156
+ .replace(/\s+/g, ' ')
157
+ .trim();
158
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
159
+ }
160
+ /**
161
+ * The instant the run went wrong: the earliest hard error we have a clock
162
+ * reading for. Returns null when the breach has no moment attached — a slow
163
+ * LCP is a property of the whole load, not an event.
164
+ */
165
+ export function findFocusOffset(input) {
166
+ const candidates = [];
167
+ for (const e of input.console) {
168
+ if (e.type === 'error' && Number.isFinite(e.timestamp)) {
169
+ candidates.push(e.timestamp - input.startedAtMs);
170
+ }
171
+ }
172
+ for (const e of input.pageErrors) {
173
+ if (Number.isFinite(e.timestamp))
174
+ candidates.push(e.timestamp - input.startedAtMs);
175
+ }
176
+ for (const r of input.requests) {
177
+ if (r.failed && r.startedAtMs !== undefined)
178
+ candidates.push(r.startedAtMs - input.startedAtMs);
179
+ }
180
+ const usable = candidates.filter((v) => Number.isFinite(v) && v >= 0);
181
+ return usable.length ? Math.min(...usable) : null;
182
+ }
183
+ export function buildEvidence(input) {
184
+ const notes = [];
185
+ const focusOffsetMs = findFocusOffset(input);
186
+ const picked = selectFrames(input.frames, focusOffsetMs, input.select);
187
+ const frames = picked.frames.map((f) => ({
188
+ offsetMs: f.offsetMs,
189
+ dataUrl: `data:image/jpeg;base64,${f.data}`,
190
+ bytes: f.bytes,
191
+ }));
192
+ const events = [];
193
+ for (const [i, frame] of picked.frames.entries()) {
194
+ events.push({
195
+ offsetMs: frame.offsetMs,
196
+ kind: 'frame',
197
+ label: 'frame',
198
+ severity: 'info',
199
+ frameIndex: i,
200
+ });
201
+ }
202
+ for (const e of input.console) {
203
+ if (e.type !== 'error' && e.type !== 'warn' && e.type !== 'warning')
204
+ continue;
205
+ events.push({
206
+ offsetMs: e.timestamp - input.startedAtMs,
207
+ kind: 'console',
208
+ label: `console.${e.type}`,
209
+ detail: truncate(e.text),
210
+ severity: e.type === 'error' ? 'error' : 'warning',
211
+ });
212
+ }
213
+ for (const e of input.pageErrors) {
214
+ events.push({
215
+ offsetMs: e.timestamp - input.startedAtMs,
216
+ kind: 'pageerror',
217
+ label: 'uncaught exception',
218
+ detail: truncate(e.text),
219
+ severity: 'error',
220
+ });
221
+ }
222
+ for (const r of input.requests) {
223
+ if (!r.failed)
224
+ continue;
225
+ if (r.startedAtMs === undefined)
226
+ continue;
227
+ events.push({
228
+ offsetMs: r.startedAtMs - input.startedAtMs,
229
+ kind: 'request',
230
+ label: `${r.status ?? r.errorText ?? 'no response'} ${r.method}`,
231
+ detail: truncate(r.url),
232
+ severity: 'error',
233
+ });
234
+ }
235
+ if (focusOffsetMs !== null) {
236
+ events.push({
237
+ offsetMs: focusOffsetMs,
238
+ kind: 'marker',
239
+ label: 'first failure',
240
+ detail: input.failures.map((f) => `${f.budget} ${f.actual}`).join(', ') || undefined,
241
+ severity: 'error',
242
+ });
243
+ }
244
+ // Trim the non-frame rows worst-first, so a page with 400 console warnings
245
+ // still shows its one uncaught exception.
246
+ const frameRows = events.filter((e) => e.kind === 'frame');
247
+ let otherRows = events.filter((e) => e.kind !== 'frame');
248
+ const maxEvents = input.maxEvents ?? DEFAULT_MAX_EVENTS;
249
+ if (otherRows.length > maxEvents) {
250
+ const weight = { error: 0, warning: 1, info: 2 };
251
+ const kept = [...otherRows]
252
+ .sort((a, b) => weight[a.severity] - weight[b.severity] ||
253
+ Math.abs(a.offsetMs - (focusOffsetMs ?? 0)) - Math.abs(b.offsetMs - (focusOffsetMs ?? 0)))
254
+ .slice(0, maxEvents);
255
+ notes.push(`Timeline trimmed to the ${maxEvents} most relevant of ${otherRows.length} events.`);
256
+ otherRows = kept;
257
+ }
258
+ const timeline = [...frameRows, ...otherRows].sort((a, b) => a.offsetMs - b.offsetMs || a.kind.localeCompare(b.kind));
259
+ const droppedFrames = (input.bufferDropped ?? 0) + picked.dropped;
260
+ if (droppedFrames > 0) {
261
+ notes.push(`${droppedFrames} recorded frame(s) not attached — the report keeps the ${frames.length} nearest the failure to stay inside its size budget.`);
262
+ }
263
+ if (!frames.length && input.frames.length === 0) {
264
+ notes.push('No screencast frames were captured for this run.');
265
+ }
266
+ if (focusOffsetMs === null && input.failures.length) {
267
+ notes.push('No single moment of failure could be located — the breach is a load-wide metric, so the frames sample the whole run instead.');
268
+ }
269
+ return {
270
+ reason: input.reason,
271
+ focusOffsetMs,
272
+ frames,
273
+ timeline,
274
+ droppedFrames,
275
+ totalBytes: frames.reduce((sum, f) => sum + f.bytes, 0),
276
+ notes,
277
+ };
278
+ }
279
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/report/evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Flake detection across repeated runs of the same URL (RIG-14).
3
+ *
4
+ * The failure mode this exists to stop: a check that fails two runs in five
5
+ * gets re-run until it is green and shipped as "passing". So the aggregate
6
+ * verdict has a third value — `flaky` — and a check that both passed and
7
+ * failed within the window can only produce that verdict. It is never
8
+ * rounded down to `pass`.
9
+ *
10
+ * The other half is honesty about what N runs can prove. `confidenceNote`
11
+ * states the failure rate the window actually rules out, because "5 runs
12
+ * passed" and "this is reliable" are very different claims.
13
+ *
14
+ * Pure: the tests feed arrays of Reports.
15
+ */
16
+ import type { Budget, Report } from './types.js';
17
+ export type FlakeVerdict = 'pass' | 'fail' | 'flaky';
18
+ export interface FlakeCheck {
19
+ key: keyof Budget;
20
+ label: string;
21
+ runs: number;
22
+ passed: number;
23
+ failed: number;
24
+ /** Fraction of runs that failed, 0..1. */
25
+ flakeRate: number;
26
+ /** True when the check did the same thing every run. */
27
+ stable: boolean;
28
+ /** The measured value for each run, in run order. */
29
+ actuals: string[];
30
+ }
31
+ export interface FlakeSignal {
32
+ kind: 'console' | 'pageError' | 'request' | 'a11y';
33
+ signature: string;
34
+ /** Runs this signal appeared in. */
35
+ runs: number;
36
+ total: number;
37
+ }
38
+ export interface FlakeMetric {
39
+ key: string;
40
+ label: string;
41
+ unit: 'ms' | 'score';
42
+ /** Runs that reported the metric at all. */
43
+ measured: number;
44
+ total: number;
45
+ min: number;
46
+ max: number;
47
+ median: number;
48
+ spread: number;
49
+ /** Spread as a fraction of the median. */
50
+ spreadRatio: number;
51
+ unstable: boolean;
52
+ }
53
+ export interface FlakeReport {
54
+ runs: number;
55
+ verdict: FlakeVerdict;
56
+ checks: FlakeCheck[];
57
+ /** Errors and failed requests that did not appear in every run. */
58
+ signals: FlakeSignal[];
59
+ metrics: FlakeMetric[];
60
+ confidence: 'low' | 'moderate' | 'high';
61
+ confidenceNote: string;
62
+ headline: string;
63
+ }
64
+ /**
65
+ * Normalise a message so the same error reported with a different id, line or
66
+ * timestamp still counts as the same signal. Without this, a flaky error
67
+ * carrying a request id looks like N distinct one-off errors.
68
+ */
69
+ export declare function signalSignature(text: string): string;
70
+ /**
71
+ * What a window of all-passing runs actually rules out.
72
+ *
73
+ * If a check truly fails with probability p, N independent passing runs have
74
+ * probability (1-p)^N. Solving (1-p)^N = 0.05 gives the largest failure rate
75
+ * consistent with what we saw at 95% confidence — which is a far less
76
+ * flattering number than "N runs passed" sounds.
77
+ */
78
+ export declare function ruledOutFailureRate(runs: number): number;
79
+ /**
80
+ * Aggregate N runs of the same URL.
81
+ *
82
+ * `budget` comes from the runs themselves (they all share one), and only
83
+ * enforced keys become checks: an unenforced budget cannot be flaky.
84
+ */
85
+ export declare function analyzeFlake(reports: Report[]): FlakeReport;
86
+ /** One line for a CI log / agent transcript. */
87
+ export declare function summarizeFlake(flake: FlakeReport): string;
88
+ //# sourceMappingURL=flake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flake.d.ts","sourceRoot":"","sources":["../../../src/report/flake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,mEAAmE;IACnE,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,EAAE,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAwCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUpD;AA0ED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAwBD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,CA0D3D;AAED,gDAAgD;AAChD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Flake detection across repeated runs of the same URL (RIG-14).
3
+ *
4
+ * The failure mode this exists to stop: a check that fails two runs in five
5
+ * gets re-run until it is green and shipped as "passing". So the aggregate
6
+ * verdict has a third value — `flaky` — and a check that both passed and
7
+ * failed within the window can only produce that verdict. It is never
8
+ * rounded down to `pass`.
9
+ *
10
+ * The other half is honesty about what N runs can prove. `confidenceNote`
11
+ * states the failure rate the window actually rules out, because "5 runs
12
+ * passed" and "this is reliable" are very different claims.
13
+ *
14
+ * Pure: the tests feed arrays of Reports.
15
+ */
16
+ import { budgetLabel } from './budget.js';
17
+ /** Spread beyond this fraction of the median is worth flagging as unstable. */
18
+ const UNSTABLE_SPREAD_RATIO = 0.3;
19
+ const COUNT_READERS = {
20
+ maxConsoleErrors: (r) => r.counts.consoleErrors,
21
+ maxPageErrors: (r) => r.counts.pageErrors,
22
+ maxFailedRequests: (r) => r.counts.failedRequests,
23
+ maxA11yErrors: (r) => r.counts.a11yErrors,
24
+ };
25
+ const METRIC_READERS = {
26
+ lcpMs: (r) => r.vitals.lcp,
27
+ clsScore: (r) => r.vitals.cls,
28
+ inpMs: (r) => r.vitals.inp,
29
+ fcpMs: (r) => r.vitals.fcp,
30
+ ttfbMs: (r) => r.vitals.ttfb,
31
+ };
32
+ function actualFor(key, report) {
33
+ const count = COUNT_READERS[key];
34
+ if (count)
35
+ return String(count(report));
36
+ const metric = METRIC_READERS[key];
37
+ const raw = metric?.(report);
38
+ if (raw === undefined || !Number.isFinite(raw))
39
+ return 'not measured';
40
+ return key === 'clsScore' ? raw.toFixed(3) : `${Math.round(raw)}ms`;
41
+ }
42
+ function median(values) {
43
+ const sorted = [...values].sort((a, b) => a - b);
44
+ const mid = Math.floor(sorted.length / 2);
45
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
46
+ }
47
+ function truncate(text, max = 140) {
48
+ const flat = text.replace(/\s+/g, ' ').trim();
49
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
50
+ }
51
+ /**
52
+ * Normalise a message so the same error reported with a different id, line or
53
+ * timestamp still counts as the same signal. Without this, a flaky error
54
+ * carrying a request id looks like N distinct one-off errors.
55
+ */
56
+ export function signalSignature(text) {
57
+ return truncate(text
58
+ .replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi, '<uuid>')
59
+ .replace(/\b0x[0-9a-f]+\b/gi, '<hex>')
60
+ // 5 digits and up, not 3: request ids, timestamps and byte offsets are
61
+ // long, while an HTTP status code is part of what makes two errors
62
+ // different and must survive normalisation.
63
+ .replace(/\b\d{5,}\b/g, '<n>'));
64
+ }
65
+ function collectSignals(reports) {
66
+ const total = reports.length;
67
+ const seen = new Map();
68
+ const add = (kind, signature, runIndex) => {
69
+ const id = `${kind}\n${signature}`;
70
+ let entry = seen.get(id);
71
+ if (!entry) {
72
+ entry = { kind, signature, runs: new Set() };
73
+ seen.set(id, entry);
74
+ }
75
+ entry.runs.add(runIndex);
76
+ };
77
+ reports.forEach((report, i) => {
78
+ for (const e of report.console) {
79
+ if (e.type === 'error')
80
+ add('console', signalSignature(e.text), i);
81
+ }
82
+ for (const e of report.pageErrors)
83
+ add('pageError', signalSignature(e.text), i);
84
+ for (const r of report.requests) {
85
+ if (r.failed)
86
+ add('request', `${r.status ?? r.errorText ?? 'no response'} ${r.url}`, i);
87
+ }
88
+ for (const f of report.a11y) {
89
+ if (f.impact === 'error')
90
+ add('a11y', `${f.rule} at ${f.locator}`, i);
91
+ }
92
+ });
93
+ return [...seen.values()]
94
+ .filter((e) => e.runs.size < total) // present in every run is a bug, not a flake
95
+ .map((e) => ({ kind: e.kind, signature: e.signature, runs: e.runs.size, total }))
96
+ .sort((a, b) => b.runs - a.runs || a.signature.localeCompare(b.signature));
97
+ }
98
+ function collectMetrics(reports) {
99
+ const defs = [
100
+ ['lcp', 'LCP', 'ms', (r) => r.vitals.lcp],
101
+ ['fcp', 'FCP', 'ms', (r) => r.vitals.fcp],
102
+ ['cls', 'CLS', 'score', (r) => r.vitals.cls],
103
+ ['inp', 'INP', 'ms', (r) => r.vitals.inp],
104
+ ['ttfb', 'TTFB', 'ms', (r) => r.vitals.ttfb],
105
+ ];
106
+ const out = [];
107
+ for (const [key, label, unit, read] of defs) {
108
+ const values = reports
109
+ .map(read)
110
+ .filter((v) => typeof v === 'number' && Number.isFinite(v));
111
+ if (!values.length)
112
+ continue;
113
+ const min = Math.min(...values);
114
+ const max = Math.max(...values);
115
+ const mid = median(values);
116
+ const spread = max - min;
117
+ const spreadRatio = mid > 0 ? spread / mid : spread > 0 ? Infinity : 0;
118
+ out.push({
119
+ key,
120
+ label,
121
+ unit,
122
+ measured: values.length,
123
+ total: reports.length,
124
+ min,
125
+ max,
126
+ median: mid,
127
+ spread,
128
+ spreadRatio,
129
+ unstable: values.length > 1 && spreadRatio > UNSTABLE_SPREAD_RATIO,
130
+ });
131
+ }
132
+ return out;
133
+ }
134
+ /**
135
+ * What a window of all-passing runs actually rules out.
136
+ *
137
+ * If a check truly fails with probability p, N independent passing runs have
138
+ * probability (1-p)^N. Solving (1-p)^N = 0.05 gives the largest failure rate
139
+ * consistent with what we saw at 95% confidence — which is a far less
140
+ * flattering number than "N runs passed" sounds.
141
+ */
142
+ export function ruledOutFailureRate(runs) {
143
+ if (runs <= 0)
144
+ return 1;
145
+ return 1 - 0.05 ** (1 / runs);
146
+ }
147
+ function confidenceFor(runs, verdict) {
148
+ if (verdict === 'flaky') {
149
+ return {
150
+ confidence: 'high',
151
+ note: `Flakiness is observed, not inferred: both outcomes occurred within ${runs} runs.`,
152
+ };
153
+ }
154
+ const bound = Math.round(ruledOutFailureRate(runs) * 100);
155
+ const level = runs >= 5 ? 'high' : runs >= 3 ? 'moderate' : 'low';
156
+ const outcome = verdict === 'pass' ? 'passed' : 'failed';
157
+ return {
158
+ confidence: level,
159
+ note: `${runs} run${runs === 1 ? '' : 's'}, all ${outcome} consistently. That only rules out ` +
160
+ `intermittent behaviour more frequent than about 1 run in ${Math.max(2, Math.round(100 / bound))} ` +
161
+ `(${bound}%) at 95% confidence — re-run with a larger --repeat to tighten it.`,
162
+ };
163
+ }
164
+ /**
165
+ * Aggregate N runs of the same URL.
166
+ *
167
+ * `budget` comes from the runs themselves (they all share one), and only
168
+ * enforced keys become checks: an unenforced budget cannot be flaky.
169
+ */
170
+ export function analyzeFlake(reports) {
171
+ if (!reports.length)
172
+ throw new Error('analyzeFlake: needs at least one run');
173
+ const runs = reports.length;
174
+ const budget = reports[0].budget;
175
+ const checks = [];
176
+ for (const key of Object.keys(budget)) {
177
+ if (budget[key] === null)
178
+ continue;
179
+ const failed = reports.filter((r) => r.failures.some((f) => f.budget === key)).length;
180
+ checks.push({
181
+ key,
182
+ label: budgetLabel(key),
183
+ runs,
184
+ passed: runs - failed,
185
+ failed,
186
+ flakeRate: failed / runs,
187
+ stable: failed === 0 || failed === runs,
188
+ actuals: reports.map((r) => actualFor(key, r)),
189
+ });
190
+ }
191
+ const unstableChecks = checks.filter((c) => !c.stable);
192
+ const alwaysFailing = checks.filter((c) => c.failed === runs);
193
+ const verdict = unstableChecks.length
194
+ ? 'flaky'
195
+ : alwaysFailing.length
196
+ ? 'fail'
197
+ : 'pass';
198
+ const signals = collectSignals(reports);
199
+ const metrics = collectMetrics(reports);
200
+ const { confidence, note } = confidenceFor(runs, verdict);
201
+ let headline;
202
+ if (verdict === 'flaky') {
203
+ const worst = [...unstableChecks].sort((a, b) => b.failed - a.failed)[0];
204
+ headline =
205
+ `FLAKY — ${unstableChecks.length} check${unstableChecks.length === 1 ? '' : 's'} ` +
206
+ `changed outcome across ${runs} runs (e.g. ${worst.label} failed ${worst.failed} of ${runs}).`;
207
+ }
208
+ else if (verdict === 'fail') {
209
+ headline = `FAIL — ${alwaysFailing.length} check(s) failed in all ${runs} runs.`;
210
+ }
211
+ else {
212
+ const unstableMetrics = metrics.filter((m) => m.unstable).length;
213
+ headline =
214
+ `PASS — every check held across all ${runs} runs` +
215
+ (unstableMetrics ? `, though ${unstableMetrics} metric(s) varied widely.` : '.');
216
+ }
217
+ return {
218
+ runs,
219
+ verdict,
220
+ checks,
221
+ signals,
222
+ metrics,
223
+ confidence,
224
+ confidenceNote: note,
225
+ headline,
226
+ };
227
+ }
228
+ /** One line for a CI log / agent transcript. */
229
+ export function summarizeFlake(flake) {
230
+ return `${flake.headline} Confidence: ${flake.confidence}.`;
231
+ }
232
+ //# sourceMappingURL=flake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flake.js","sourceRoot":"","sources":["../../../src/report/flake.ts"],"names":[],"mappings":"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"}