@deeeed/metamask-harness 0.43.0 → 0.44.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.
@@ -1,4 +1,5 @@
1
- import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, open, readFile, rm, stat, writeFile } from "node:fs/promises";
2
3
  import path from "node:path";
3
4
 
4
5
  const MARKER = "[PerpsPerf]";
@@ -7,12 +8,39 @@ const DETAILED_MARKERS = [MARKER, LEGACY_MARKER];
7
8
  const STARTUP_MARKER = "[StartupPerf]";
8
9
  const LOAD_PROOF_MARKER = "[PerpsLoadProof]";
9
10
  const STATE_FILE = ".homepage-performance-capture.json";
11
+ const CAPTURE_BOUNDARY_BYTES = 4096;
12
+ const BOOTSTRAP_LOOKBACK_BYTES = 512 * 1024;
10
13
  const FRESH_SOURCES = new Set([
11
14
  "fresh_socket",
12
15
  "provider_snapshot",
13
16
  "terminal_global_snapshot_v2",
17
+ "terminal_v2",
14
18
  "provider",
15
19
  ]);
20
+ const SURFACE_STAGE_ORDER = [
21
+ "surface_demand",
22
+ "surface_initial_ui_recorded",
23
+ "surface_resolved_recorded",
24
+ "surface_live_recorded",
25
+ ];
26
+ const SURFACE_STAGES = new Set(SURFACE_STAGE_ORDER);
27
+ const PERFORMANCE_IDENTITY_FIELDS = [
28
+ "demand_id",
29
+ "perps_session_id",
30
+ "lifecycle",
31
+ "account_generation",
32
+ "context_generation",
33
+ ];
34
+ const LOAD_PROOF_BASE_IDENTITY_FIELDS = PERFORMANCE_IDENTITY_FIELDS.slice(1);
35
+ const LOAD_PROOF_IDENTITY_FIELDS = [
36
+ ...LOAD_PROOF_BASE_IDENTITY_FIELDS,
37
+ "connection_generation",
38
+ ];
39
+ const GENERATION_IDENTITY_FIELDS = new Set([
40
+ "account_generation",
41
+ "context_generation",
42
+ "connection_generation",
43
+ ]);
16
44
 
17
45
  function resolveWithin(root, relativePath, label) {
18
46
  const absoluteRoot = path.resolve(root);
@@ -24,15 +52,83 @@ function resolveWithin(root, relativePath, label) {
24
52
  return absolutePath;
25
53
  }
26
54
 
27
- async function fileSize(file) {
55
+ async function fileState(file) {
28
56
  try {
29
- return (await stat(file)).size;
57
+ const value = await stat(file);
58
+ return { size: value.size, device: value.dev, inode: value.ino };
30
59
  } catch (error) {
31
- if (error?.code === "ENOENT") return 0;
60
+ if (error?.code === "ENOENT") return null;
32
61
  throw error;
33
62
  }
34
63
  }
35
64
 
65
+ async function readFileRange(file, start, length) {
66
+ if (length === 0) return Buffer.alloc(0);
67
+ const handle = await open(file, "r");
68
+ try {
69
+ const buffer = Buffer.alloc(length);
70
+ const { bytesRead } = await handle.read(buffer, 0, length, start);
71
+ return buffer.subarray(0, bytesRead);
72
+ } finally {
73
+ await handle.close();
74
+ }
75
+ }
76
+
77
+ function captureBoundary(content, offset) {
78
+ const start = Math.max(0, offset - CAPTURE_BOUNDARY_BYTES);
79
+ const bytes = content.subarray(start, offset);
80
+ return {
81
+ start,
82
+ length: bytes.length,
83
+ sha256: createHash("sha256").update(bytes).digest("hex"),
84
+ };
85
+ }
86
+
87
+ function captureBoundaryBytes(start, bytes) {
88
+ return {
89
+ start,
90
+ length: bytes.length,
91
+ sha256: createHash("sha256").update(bytes).digest("hex"),
92
+ };
93
+ }
94
+
95
+ async function readCaptureSource(sourceFile, state) {
96
+ const current = await fileState(sourceFile);
97
+ if (!current) {
98
+ if (state.offset === 0 && state.sourceIdentity === null) {
99
+ return Buffer.alloc(0);
100
+ }
101
+ throw new Error("Perps performance capture source disappeared after phase=start.");
102
+ }
103
+ if (state.sourceIdentity === null) {
104
+ state.sourceIdentity = current;
105
+ }
106
+ if (
107
+ state.sourceIdentity &&
108
+ (current.device !== state.sourceIdentity.device ||
109
+ current.inode !== state.sourceIdentity.inode)
110
+ ) {
111
+ throw new Error("Perps performance capture source was replaced after phase=start.");
112
+ }
113
+ if (current.size < state.offset) {
114
+ throw new Error("Perps performance capture source shrank after phase=start.");
115
+ }
116
+ const content = await readFile(sourceFile);
117
+ const boundary = captureBoundary(content, state.offset);
118
+ if (state.sourceBoundary === null) {
119
+ state.sourceBoundary = boundary;
120
+ } else if (
121
+ boundary.start !== state.sourceBoundary.start ||
122
+ boundary.length !== state.sourceBoundary.length ||
123
+ boundary.sha256 !== state.sourceBoundary.sha256
124
+ ) {
125
+ throw new Error(
126
+ "Perps performance capture source was truncated or rewritten after phase=start.",
127
+ );
128
+ }
129
+ return content;
130
+ }
131
+
36
132
  function parseRecord(line, marker) {
37
133
  const markerIndex = line.indexOf(marker);
38
134
  if (markerIndex < 0) return null;
@@ -56,83 +152,279 @@ function parseDetailedRecord(line) {
56
152
  return marker ? parseRecord(line, marker) : null;
57
153
  }
58
154
 
59
- function latestPerpsBootstrapStartRecord(content) {
60
- return content
61
- .split(/\r?\n/u)
62
- .filter((line) => line.includes(LOAD_PROOF_MARKER))
63
- .map((line) => parseRecord(line, LOAD_PROOF_MARKER))
64
- .filter((record) => record?.stage === "perps_bootstrap_start")
65
- .at(-1) ?? null;
155
+ function identityField(record, field) {
156
+ if (field === "perps_session_id") {
157
+ if (Object.hasOwn(record, "perps_session_id")) {
158
+ return { present: true, value: record.perps_session_id };
159
+ }
160
+ if (Object.hasOwn(record, "session_id")) {
161
+ return { present: true, value: record.session_id };
162
+ }
163
+ return { present: false, value: undefined };
164
+ }
165
+ return Object.hasOwn(record, field)
166
+ ? { present: true, value: record[field] }
167
+ : { present: false, value: undefined };
66
168
  }
67
169
 
68
- function consoleClockMs(line) {
69
- const match = line.match(/\b(\d{2}):(\d{2}):(\d{2})\.(\d{3})\b/u);
70
- if (!match) return null;
170
+ function hasValidIdentityField(record, field) {
171
+ const identity = identityField(record, field);
172
+ if (
173
+ !identity.present ||
174
+ identity.value === null ||
175
+ identity.value === undefined
176
+ ) {
177
+ return false;
178
+ }
179
+ if (GENERATION_IDENTITY_FIELDS.has(field)) {
180
+ return (
181
+ typeof identity.value === "number" &&
182
+ Number.isInteger(identity.value) &&
183
+ identity.value >= 0
184
+ );
185
+ }
186
+ return String(identity.value).trim().length > 0;
187
+ }
188
+
189
+ function hasCompleteIdentity(record, fields = PERFORMANCE_IDENTITY_FIELDS) {
190
+ return fields.every((field) => hasValidIdentityField(record, field));
191
+ }
192
+
193
+ function sameIdentity(left, right, fields = PERFORMANCE_IDENTITY_FIELDS) {
71
194
  return (
72
- Number(match[1]) * 3_600_000 +
73
- Number(match[2]) * 60_000 +
74
- Number(match[3]) * 1_000 +
75
- Number(match[4])
195
+ hasCompleteIdentity(left, fields) &&
196
+ hasCompleteIdentity(right, fields) &&
197
+ fields.every((field) => {
198
+ const leftField = identityField(left, field);
199
+ const rightField = identityField(right, field);
200
+ return String(leftField.value) === String(rightField.value);
201
+ })
202
+ );
203
+ }
204
+
205
+ function identityKey(record, fields = PERFORMANCE_IDENTITY_FIELDS) {
206
+ return JSON.stringify(
207
+ fields.map((field) => {
208
+ const value = identityField(record, field);
209
+ return value.present ? [field, String(value.value)] : [field, "<missing>"];
210
+ }),
211
+ );
212
+ }
213
+
214
+ function performanceRecordTime(record) {
215
+ const value = Number(
216
+ record.frame_checkpoint_monotonic_ms ?? record.monotonic_ms,
76
217
  );
218
+ return Number.isFinite(value) ? value : null;
77
219
  }
78
220
 
79
- function existingLiveStreamRecords(segmentLines, markerRecords) {
80
- let bootstrapLineIndex = -1;
81
- segmentLines.forEach((line, index) => {
221
+ function isAccountContentVariant(value) {
222
+ return ["positions", "orders", "positions_and_orders"].includes(
223
+ String(value ?? ""),
224
+ );
225
+ }
226
+
227
+ function orderedSurfaceSequence(records, demand, requiredStages) {
228
+ const stages = SURFACE_STAGE_ORDER.filter((stage) =>
229
+ requiredStages.includes(stage),
230
+ );
231
+ if (stages.length === 0) return [demand];
232
+ const demandAt = performanceRecordTime(demand);
233
+ if (demandAt === null) return null;
234
+ const sequence = [];
235
+ let previousAt = demandAt;
236
+ for (const stage of stages) {
237
+ if (stage === "surface_demand") {
238
+ sequence.push(demand);
239
+ continue;
240
+ }
241
+ const matches = records
242
+ .filter(
243
+ (record) =>
244
+ record.stage === stage &&
245
+ sameIdentity(record, demand),
246
+ )
247
+ .sort(
248
+ (left, right) =>
249
+ performanceRecordTime(left) - performanceRecordTime(right),
250
+ );
251
+ if (matches.length !== 1) return null;
252
+ const match = matches[0];
253
+ const matchAt = performanceRecordTime(match);
82
254
  if (
83
- line.includes(LOAD_PROOF_MARKER) &&
84
- line.includes('"stage":"perps_bootstrap_start"')
255
+ matchAt === null ||
256
+ matchAt < previousAt ||
257
+ !Number.isFinite(Number(match.duration_ms)) ||
258
+ Number(match.duration_ms) < 0 ||
259
+ (stage === "surface_live_recorded" &&
260
+ (match.fresh_for_lifecycle !== true || !frameIsFresh(match)))
85
261
  ) {
86
- bootstrapLineIndex = index;
262
+ return null;
87
263
  }
88
- });
89
- const bootstrapLine =
90
- bootstrapLineIndex >= 0 ? segmentLines[bootstrapLineIndex] : undefined;
91
- const liveLines =
92
- bootstrapLineIndex >= 0
93
- ? segmentLines.slice(bootstrapLineIndex + 1)
94
- : segmentLines;
95
- const bootstrapClock = bootstrapLine ? consoleClockMs(bootstrapLine) : null;
96
- const bootstrapRecord = markerRecords
97
- .filter((record) => record.stage === "perps_bootstrap_start")
98
- .at(-1);
99
- const patterns = new Map([
100
- ["PerpsWS: First price data received", "prices"],
101
- ["PerpsWS: First position data received", "positions"],
102
- ["PerpsWS: First order data received", "orders"],
103
- ["PerpsWS: First account data received", "account"],
104
- ]);
105
- const records = [];
106
- for (const [message, stream] of patterns) {
107
- const line = liveLines.find((candidate) => candidate.includes(message));
108
- if (!line) continue;
109
- const eventClock = consoleClockMs(line);
110
- let elapsedMs = null;
111
- if (bootstrapClock !== null && eventClock !== null) {
112
- elapsedMs = eventClock - bootstrapClock;
113
- if (elapsedMs < 0) elapsedMs += 24 * 3_600_000;
264
+ sequence.push(match);
265
+ previousAt = matchAt;
266
+ }
267
+ return sequence;
268
+ }
269
+
270
+ function coherentPerformanceProof(
271
+ records,
272
+ loadProofRecords,
273
+ requiredStages,
274
+ requiredLiveStreams,
275
+ expectedLifecycle = null,
276
+ expectedContentVariant = null,
277
+ ) {
278
+ const requiredSurfaceStages = requiredStages.filter((stage) =>
279
+ SURFACE_STAGES.has(stage),
280
+ );
281
+ const required =
282
+ requiredSurfaceStages.length > 0 || requiredLiveStreams.length > 0;
283
+ if (!required) {
284
+ return {
285
+ status: "not_required",
286
+ demand: null,
287
+ identity: null,
288
+ missingLiveStreams: [],
289
+ sequence: [],
290
+ };
291
+ }
292
+ const demands = records.filter((record) => record.stage === "surface_demand");
293
+ let best = null;
294
+ for (const demand of demands) {
295
+ if (!hasCompleteIdentity(demand)) continue;
296
+ if (
297
+ records.filter(
298
+ (record) =>
299
+ record.stage === "surface_demand" && sameIdentity(record, demand),
300
+ ).length !== 1
301
+ ) {
302
+ continue;
114
303
  }
115
- records.push({
116
- stage: "values_ready",
117
- stream,
118
- source: "fresh_socket",
119
- item_count: null,
120
- elapsed_ms: elapsedMs,
121
- monotonic_ms:
122
- elapsedMs !== null &&
123
- Number.isFinite(Number(bootstrapRecord?.monotonic_ms))
124
- ? Number(bootstrapRecord.monotonic_ms) + elapsedMs
125
- : null,
126
- evidence: "existing_sentry_ws_marker",
127
- });
304
+ if (
305
+ expectedLifecycle !== null &&
306
+ String(demand.lifecycle ?? "") !== expectedLifecycle
307
+ ) {
308
+ continue;
309
+ }
310
+ const sequence = orderedSurfaceSequence(
311
+ records,
312
+ demand,
313
+ requiredSurfaceStages,
314
+ );
315
+ if (!sequence) continue;
316
+ if (
317
+ expectedContentVariant !== null &&
318
+ sequence
319
+ .filter((record) => record.stage !== "surface_demand")
320
+ .some(
321
+ (record) =>
322
+ !contentVariantSatisfies(
323
+ String(record.content_variant ?? ""),
324
+ expectedContentVariant,
325
+ ),
326
+ )
327
+ ) {
328
+ continue;
329
+ }
330
+ const liveRecords = loadProofRecords.filter(
331
+ (record) =>
332
+ record.stage === "values_ready" &&
333
+ record.source === "fresh_socket" &&
334
+ hasCompleteIdentity(record, LOAD_PROOF_IDENTITY_FIELDS) &&
335
+ sameIdentity(record, demand, LOAD_PROOF_BASE_IDENTITY_FIELDS),
336
+ );
337
+ const connectionGenerations = new Set(
338
+ liveRecords.map((record) => record.connection_generation),
339
+ );
340
+ const liveRecordConnectionGeneration =
341
+ connectionGenerations.size === 1
342
+ ? [...connectionGenerations][0]
343
+ : null;
344
+ const liveSurface = sequence.find(
345
+ (record) => record.stage === "surface_live_recorded",
346
+ );
347
+ const accountLiveSurface =
348
+ liveSurface && isAccountContentVariant(liveSurface.content_variant)
349
+ ? liveSurface
350
+ : null;
351
+ const surfaceConnectionGeneration =
352
+ accountLiveSurface &&
353
+ hasValidIdentityField(accountLiveSurface, "connection_generation")
354
+ ? accountLiveSurface.connection_generation
355
+ : null;
356
+ const identityCoherent =
357
+ connectionGenerations.size <= 1 &&
358
+ (!accountLiveSurface ||
359
+ (surfaceConnectionGeneration !== null &&
360
+ (liveRecordConnectionGeneration === null ||
361
+ surfaceConnectionGeneration === liveRecordConnectionGeneration)));
362
+ const coherentConnectionGeneration =
363
+ liveRecordConnectionGeneration ?? surfaceConnectionGeneration;
364
+ const liveStreams = new Set(
365
+ liveRecordConnectionGeneration === null
366
+ ? []
367
+ : liveRecords.map((record) => String(record.stream ?? "")),
368
+ );
369
+ const missingLiveStreams = requiredLiveStreams.filter(
370
+ (stream) => !liveStreams.has(stream),
371
+ );
372
+ const candidate = {
373
+ demand,
374
+ sequence,
375
+ missingLiveStreams,
376
+ identityCoherent,
377
+ connectionGeneration: coherentConnectionGeneration,
378
+ };
379
+ if (
380
+ !best ||
381
+ Number(identityCoherent) > Number(best.identityCoherent) ||
382
+ (identityCoherent === best.identityCoherent &&
383
+ missingLiveStreams.length < best.missingLiveStreams.length)
384
+ ) {
385
+ best = candidate;
386
+ }
387
+ if (identityCoherent && missingLiveStreams.length === 0) break;
128
388
  }
129
- return records;
389
+ return {
390
+ status:
391
+ best?.identityCoherent && best.missingLiveStreams.length === 0
392
+ ? "pass"
393
+ : "fail",
394
+ demand: best?.demand ?? null,
395
+ identity: best
396
+ ? {
397
+ ...Object.fromEntries(
398
+ PERFORMANCE_IDENTITY_FIELDS.map((field) => {
399
+ const value = identityField(best.demand, field);
400
+ return [field, value.present ? value.value : null];
401
+ }),
402
+ ),
403
+ connection_generation: best.connectionGeneration,
404
+ }
405
+ : null,
406
+ missingLiveStreams: best?.missingLiveStreams ?? requiredLiveStreams,
407
+ sequence: best?.sequence.map((record) => record.stage) ?? [],
408
+ };
409
+ }
410
+
411
+ function latestPerpsBootstrapStartRecord(content) {
412
+ return content
413
+ .split(/\r?\n/u)
414
+ .filter((line) => line.includes(LOAD_PROOF_MARKER))
415
+ .map((line) => parseRecord(line, LOAD_PROOF_MARKER))
416
+ .filter((record) => record?.stage === "perps_bootstrap_start")
417
+ .at(-1) ?? null;
130
418
  }
131
419
 
132
420
  function mergeLoadProofRecords(records) {
133
421
  const byStageStreamSource = new Map();
134
422
  for (const record of records) {
135
- const key = `${record.stage ?? "unknown"}:${record.stream ?? ""}:${record.source ?? ""}`;
423
+ const identityFields =
424
+ record.stage === "values_ready"
425
+ ? LOAD_PROOF_IDENTITY_FIELDS
426
+ : LOAD_PROOF_BASE_IDENTITY_FIELDS;
427
+ const key = `${record.stage ?? "unknown"}:${record.stream ?? ""}:${record.source ?? ""}:${identityKey(record, identityFields)}`;
136
428
  const current = byStageStreamSource.get(key);
137
429
  if (record.stage === "perps_bootstrap_start") {
138
430
  if (
@@ -143,14 +435,9 @@ function mergeLoadProofRecords(records) {
143
435
  }
144
436
  continue;
145
437
  }
146
- const recordIsFallback =
147
- record.evidence === "existing_sentry_ws_marker";
148
- const currentIsFallback =
149
- current?.evidence === "existing_sentry_ws_marker";
150
438
  const recordElapsedMs = Number(record.elapsed_ms);
151
439
  const currentElapsedMs = Number(current?.elapsed_ms);
152
- const sameEvidenceClassEarlier =
153
- recordIsFallback === currentIsFallback &&
440
+ const earlier =
154
441
  record.elapsed_ms !== null &&
155
442
  record.elapsed_ms !== undefined &&
156
443
  Number.isFinite(recordElapsedMs) &&
@@ -158,18 +445,14 @@ function mergeLoadProofRecords(records) {
158
445
  current?.elapsed_ms !== undefined &&
159
446
  Number.isFinite(currentElapsedMs) &&
160
447
  recordElapsedMs < currentElapsedMs;
161
- if (
162
- !current ||
163
- (currentIsFallback && !recordIsFallback) ||
164
- sameEvidenceClassEarlier
165
- ) {
448
+ if (!current || earlier) {
166
449
  byStageStreamSource.set(key, record);
167
450
  }
168
451
  }
169
452
  return [...byStageStreamSource.values()];
170
453
  }
171
454
 
172
- async function waitForPerformanceRecord({ node, sourceFile, offset }) {
455
+ async function waitForPerformanceRecord({ node, sourceFile, state }) {
173
456
  const stage = node.wait_for_stage;
174
457
  const requiredLiveStreams = Array.isArray(node.required_live_streams)
175
458
  ? node.required_live_streams.map(String)
@@ -187,6 +470,9 @@ async function waitForPerformanceRecord({ node, sourceFile, offset }) {
187
470
  ...(node.wait_for_lifecycle !== undefined
188
471
  ? { lifecycle: String(node.wait_for_lifecycle) }
189
472
  : {}),
473
+ ...(node.wait_for_content_variant !== undefined
474
+ ? { content_variant: String(node.wait_for_content_variant) }
475
+ : {}),
190
476
  };
191
477
  const timeoutMs = Math.max(1, Number(node.wait_timeout_ms ?? 60_000));
192
478
  const pollIntervalMs = Math.max(
@@ -196,8 +482,8 @@ async function waitForPerformanceRecord({ node, sourceFile, offset }) {
196
482
  const deadline = Date.now() + timeoutMs;
197
483
 
198
484
  while (true) {
199
- const content = await readFile(sourceFile);
200
- const start = offset <= content.length ? offset : 0;
485
+ const content = await readCaptureSource(sourceFile, state);
486
+ const start = state.offset;
201
487
  const segmentLines = content
202
488
  .subarray(start)
203
489
  .toString("utf8")
@@ -206,33 +492,42 @@ async function waitForPerformanceRecord({ node, sourceFile, offset }) {
206
492
  .filter(detailedMarker)
207
493
  .map(parseDetailedRecord)
208
494
  .filter(Boolean);
209
- const stageMatched =
210
- expected === null ||
211
- performanceRecords.some((record) =>
212
- Object.entries(expected).every(
213
- ([key, value]) => String(record[key] ?? "") === value,
214
- ),
215
- );
216
495
  const markerLoadProofRecords = segmentLines
217
496
  .filter((line) => line.includes(LOAD_PROOF_MARKER))
218
497
  .map((line) => parseRecord(line, LOAD_PROOF_MARKER))
219
498
  .filter(Boolean);
220
- const liveStreams = new Set(
221
- mergeLoadProofRecords([
222
- ...markerLoadProofRecords,
223
- ...existingLiveStreamRecords(segmentLines, markerLoadProofRecords),
224
- ])
225
- .filter(
226
- (record) =>
227
- record.stage === "values_ready" &&
228
- record.source === "fresh_socket",
229
- )
230
- .map((record) => String(record.stream ?? "")),
231
- );
232
- const liveStreamsMatched = requiredLiveStreams.every((stream) =>
233
- liveStreams.has(stream),
499
+ const loadProofRecords = mergeLoadProofRecords(markerLoadProofRecords);
500
+ const coherentProof = coherentPerformanceProof(
501
+ performanceRecords,
502
+ loadProofRecords,
503
+ expected && SURFACE_STAGES.has(expected.stage) ? [expected.stage] : [],
504
+ requiredLiveStreams,
505
+ node.wait_for_lifecycle === undefined
506
+ ? null
507
+ : String(node.wait_for_lifecycle),
508
+ node.wait_for_content_variant === undefined
509
+ ? null
510
+ : String(node.wait_for_content_variant),
234
511
  );
235
- if (stageMatched && liveStreamsMatched) return;
512
+ const stageMatched =
513
+ expected === null ||
514
+ performanceRecords.some(
515
+ (record) =>
516
+ Object.entries(expected).every(
517
+ ([key, value]) =>
518
+ key === "content_variant"
519
+ ? contentVariantSatisfies(
520
+ String(record.content_variant ?? ""),
521
+ value,
522
+ )
523
+ : String(record[key] ?? "") === value,
524
+ ) &&
525
+ (coherentProof.demand === null ||
526
+ sameIdentity(record, coherentProof.demand)),
527
+ );
528
+ const coherenceMatched =
529
+ coherentProof.status === "not_required" || coherentProof.status === "pass";
530
+ if (stageMatched && coherenceMatched) return;
236
531
  if (Date.now() >= deadline) {
237
532
  throw new Error(
238
533
  `Timed out waiting ${timeoutMs}ms for ${MARKER} stage ${JSON.stringify(expected)} and live streams ${JSON.stringify(requiredLiveStreams)}.`,
@@ -271,13 +566,19 @@ function startupMeasurements(records) {
271
566
  }
272
567
 
273
568
  function perpsBootstrapBoundary(homepageRecords, loadProofRecords) {
274
- const demandTimes = homepageRecords
569
+ const demands = homepageRecords
275
570
  .filter((record) => record.stage === "surface_demand")
276
- .map((record) => Number(record.monotonic_ms))
277
- .filter(Number.isFinite);
278
- const firstDemandAt = demandTimes.length > 0 ? Math.min(...demandTimes) : null;
571
+ .filter((record) => Number.isFinite(Number(record.monotonic_ms)))
572
+ .sort((left, right) => Number(left.monotonic_ms) - Number(right.monotonic_ms));
573
+ const demand = demands[0] ?? null;
574
+ const firstDemandAt = demand === null ? null : Number(demand.monotonic_ms);
279
575
  const bootstrapTimes = loadProofRecords
280
- .filter((record) => record.stage === "perps_bootstrap_start")
576
+ .filter(
577
+ (record) =>
578
+ record.stage === "perps_bootstrap_start" &&
579
+ demand !== null &&
580
+ sameIdentity(record, demand, LOAD_PROOF_BASE_IDENTITY_FIELDS),
581
+ )
281
582
  .map((record) => Number(record.monotonic_ms))
282
583
  .filter(
283
584
  (value) =>
@@ -395,13 +696,8 @@ function frameIsCached(record) {
395
696
  }
396
697
 
397
698
  function visibleFrameGroups(records) {
398
- const demandLifecycles = new Map(
399
- records
400
- .filter((record) => record.stage === "surface_demand")
401
- .map((record) => [
402
- String(record.demand_id ?? ""),
403
- record.lifecycle ?? "unknown",
404
- ]),
699
+ const demands = records.filter(
700
+ (record) => record.stage === "surface_demand",
405
701
  );
406
702
  const groups = new Map();
407
703
  for (const record of records) {
@@ -409,12 +705,13 @@ function visibleFrameGroups(records) {
409
705
  const at = frameTime(record);
410
706
  if (at === null) continue;
411
707
  const demandId = String(record.demand_id ?? "");
412
- const key = `${demandId}:${at}`;
708
+ const key = `${identityKey(record)}:${at}`;
709
+ const demand = demands.find((candidate) => sameIdentity(candidate, record));
413
710
  const group = groups.get(key) ?? {
414
711
  at,
415
712
  demandId,
416
- lifecycle:
417
- record.lifecycle ?? demandLifecycles.get(demandId) ?? "unknown",
713
+ demand,
714
+ lifecycle: record.lifecycle ?? demand?.lifecycle ?? "unknown",
418
715
  records: [],
419
716
  };
420
717
  group.records.push(record);
@@ -451,23 +748,29 @@ function frameGroupSatisfies(group, requiredVariants, predicate) {
451
748
 
452
749
  function cacheTakeoverMeasurement(records, requiredContentVariants = []) {
453
750
  const groups = visibleFrameGroups(records);
454
- const cached = groups.find((group) =>
455
- frameGroupSatisfies(group, requiredContentVariants, frameIsCached),
751
+ const cached = groups.find(
752
+ (group) =>
753
+ group.demand &&
754
+ frameGroupSatisfies(group, requiredContentVariants, frameIsCached),
456
755
  );
457
756
  const fresh = cached
458
757
  ? groups.find(
459
758
  (group) =>
460
759
  group.at > cached.at &&
760
+ group.demand &&
761
+ sameIdentity(group.demand, cached.demand) &&
461
762
  frameGroupSatisfies(group, requiredContentVariants, frameIsFresh),
462
763
  )
463
764
  : null;
464
765
  const cacheHydratedValues = records
465
- .filter((record) => record.stage === "disk_cache_hydrated")
466
- .map((record) => Number(record.monotonic_ms))
467
766
  .filter(
468
- (value) =>
469
- Number.isFinite(value) && (cached === undefined || value <= cached.at),
470
- );
767
+ (record) =>
768
+ record.stage === "disk_cache_hydrated" &&
769
+ cached !== undefined &&
770
+ sameIdentity(record, cached.demand),
771
+ )
772
+ .map((record) => Number(record.monotonic_ms))
773
+ .filter((value) => Number.isFinite(value) && value <= cached.at);
471
774
  const cacheHydratedAt =
472
775
  cacheHydratedValues.length > 0 ? Math.max(...cacheHydratedValues) : null;
473
776
  const failureReason = !cached
@@ -511,29 +814,42 @@ function visibleMeasurements(records, requiredFreshContentVariants = []) {
511
814
  return demands.map((demand) => {
512
815
  const demandId = String(demand.demand_id ?? "");
513
816
  const startedAt = Number(demand.monotonic_ms);
514
- const belongsToDemand = (record) =>
515
- String(record.demand_id ?? "") === demandId &&
516
- ["account_generation", "context_generation"].every(
517
- (key) =>
518
- demand[key] === undefined ||
519
- record[key] === undefined ||
520
- String(record[key]) === String(demand[key]),
521
- );
817
+ const belongsToDemand = (record) => sameIdentity(record, demand);
818
+ const afterDemand = (record) => {
819
+ const at = performanceRecordTime(record);
820
+ return at !== null && Number.isFinite(startedAt) && at >= startedAt;
821
+ };
522
822
  const frames = records.filter(
523
823
  (record) =>
524
- record.stage === "next_frame_checkpoint" && belongsToDemand(record),
824
+ record.stage === "next_frame_checkpoint" &&
825
+ belongsToDemand(record) &&
826
+ afterDemand(record),
525
827
  );
526
828
  const commits = records.filter(
527
- (record) => record.stage === "react_commit" && belongsToDemand(record),
528
- );
529
- const firstVisibleBoundary = records.find(
530
829
  (record) =>
531
- record.stage === "surface_resolved_recorded" && belongsToDemand(record),
532
- );
533
- const freshVisibleBoundary = records.find(
534
- (record) =>
535
- record.stage === "surface_live_recorded" && belongsToDemand(record),
830
+ record.stage === "react_commit" &&
831
+ belongsToDemand(record) &&
832
+ afterDemand(record),
536
833
  );
834
+ const firstVisibleBoundary = records
835
+ .filter(
836
+ (record) =>
837
+ record.stage === "surface_resolved_recorded" &&
838
+ belongsToDemand(record) &&
839
+ afterDemand(record),
840
+ )
841
+ .sort((left, right) => frameTime(left) - frameTime(right))[0];
842
+ const firstVisibleBoundaryAt = frameTime(firstVisibleBoundary ?? {});
843
+ const freshVisibleBoundary = records
844
+ .filter(
845
+ (record) =>
846
+ record.stage === "surface_live_recorded" &&
847
+ belongsToDemand(record) &&
848
+ afterDemand(record) &&
849
+ (firstVisibleBoundaryAt === null ||
850
+ frameTime(record) >= firstVisibleBoundaryAt),
851
+ )
852
+ .sort((left, right) => frameTime(left) - frameTime(right))[0];
537
853
  const frameTimes = frames
538
854
  .map((record) =>
539
855
  Number(record.frame_checkpoint_monotonic_ms ?? record.monotonic_ms),
@@ -601,6 +917,11 @@ function visibleMeasurements(records, requiredFreshContentVariants = []) {
601
917
  const dataAges = frames
602
918
  .map((record) => Number(record.data_age_ms))
603
919
  .filter(Number.isFinite);
920
+ const deliveryRecords = [
921
+ ...frames,
922
+ firstVisibleBoundary,
923
+ freshVisibleBoundary,
924
+ ].filter(Boolean);
604
925
  return {
605
926
  demandId,
606
927
  lifecycle: demand.lifecycle ?? "unknown",
@@ -625,10 +946,15 @@ function visibleMeasurements(records, requiredFreshContentVariants = []) {
625
946
  ? roundMs(freshVisibleAt - startedAt)
626
947
  : null,
627
948
  deliverySources: [
628
- ...new Set(frames.map((record) => String(record.source ?? "unknown"))),
949
+ ...new Set(
950
+ deliveryRecords
951
+ .map((record) => String(record.source ?? ""))
952
+ .filter(Boolean),
953
+ ),
629
954
  ],
630
955
  contentVariant:
631
- frames.find((record) => record.content_variant)?.content_variant ??
956
+ deliveryRecords.find((record) => record.content_variant)
957
+ ?.content_variant ??
632
958
  null,
633
959
  maxDataAgeMs: dataAges.length > 0 ? Math.max(...dataAges) : null,
634
960
  };
@@ -694,18 +1020,31 @@ function socketPipelineMeasurements(records) {
694
1020
  return sockets.flatMap((socket) => {
695
1021
  const deliveryId = String(socket.delivery_id);
696
1022
  const socketAt = Number(socket.monotonic_ms);
697
- const commit = records.find(
698
- (record) =>
699
- record.stage === "react_commit" &&
700
- String(record.delivery_id ?? "") === deliveryId,
701
- );
702
- const frame = records.find(
703
- (record) =>
704
- record.stage === "next_frame_checkpoint" &&
705
- String(record.delivery_id ?? "") === deliveryId,
706
- );
707
- if (!commit || !frame || !Number.isFinite(socketAt)) return [];
1023
+ if (!Number.isFinite(socketAt)) return [];
1024
+ const commit = records
1025
+ .filter(
1026
+ (record) =>
1027
+ record.stage === "react_commit" &&
1028
+ String(record.delivery_id ?? "") === deliveryId &&
1029
+ sameIdentity(record, socket) &&
1030
+ Number(record.monotonic_ms) >= socketAt,
1031
+ )
1032
+ .sort(
1033
+ (left, right) => Number(left.monotonic_ms) - Number(right.monotonic_ms),
1034
+ )[0];
1035
+ if (!commit) return [];
708
1036
  const commitAt = Number(commit.monotonic_ms);
1037
+ const frame = records
1038
+ .filter(
1039
+ (record) =>
1040
+ record.stage === "next_frame_checkpoint" &&
1041
+ String(record.delivery_id ?? "") === deliveryId &&
1042
+ sameIdentity(record, socket) &&
1043
+ frameTime(record) !== null &&
1044
+ frameTime(record) >= commitAt,
1045
+ )
1046
+ .sort((left, right) => frameTime(left) - frameTime(right))[0];
1047
+ if (!frame) return [];
709
1048
  const frameAt = Number(
710
1049
  frame.frame_checkpoint_monotonic_ms ?? frame.monotonic_ms,
711
1050
  );
@@ -714,14 +1053,14 @@ function socketPipelineMeasurements(records) {
714
1053
  (record) =>
715
1054
  record.stage === "subscriber_delivery" &&
716
1055
  String(record.delivery_id ?? "") === deliveryId &&
1056
+ sameIdentity(record, socket) &&
1057
+ Number(record.monotonic_ms) >= socketAt &&
717
1058
  Number(record.monotonic_ms) <= commitAt,
718
1059
  )
719
1060
  .map((record) => Number(record.monotonic_ms))
720
1061
  .filter(Number.isFinite);
721
- const subscriberAt =
722
- subscriberCandidates.length > 0
723
- ? Math.max(...subscriberCandidates)
724
- : socketAt;
1062
+ if (subscriberCandidates.length === 0) return [];
1063
+ const subscriberAt = Math.max(...subscriberCandidates);
725
1064
  return [
726
1065
  {
727
1066
  deliveryId,
@@ -757,14 +1096,20 @@ function firstFreshDeliveryChecks(records, requirements) {
757
1096
  record.delivery_id,
758
1097
  );
759
1098
  const delivery = socket
760
- ? records.find(
761
- (record) =>
762
- record.stage === "subscriber_delivery" &&
763
- record.delivery_id === socket.delivery_id &&
764
- record.stream === stream &&
765
- record.lifecycle === socket.lifecycle &&
766
- Number(record.throttle_ms ?? 0) === subscriberThrottleMs,
767
- )
1099
+ ? records
1100
+ .filter(
1101
+ (record) =>
1102
+ record.stage === "subscriber_delivery" &&
1103
+ record.delivery_id === socket.delivery_id &&
1104
+ record.stream === stream &&
1105
+ sameIdentity(record, socket) &&
1106
+ Number(record.monotonic_ms) >= Number(socket.monotonic_ms) &&
1107
+ Number(record.throttle_ms ?? 0) === subscriberThrottleMs,
1108
+ )
1109
+ .sort(
1110
+ (left, right) =>
1111
+ Number(left.monotonic_ms) - Number(right.monotonic_ms),
1112
+ )[0]
768
1113
  : null;
769
1114
  const socketAt = Number(socket?.monotonic_ms);
770
1115
  const subscriberAt = Number(delivery?.monotonic_ms);
@@ -797,6 +1142,7 @@ function summarize(
797
1142
  bytesScanned,
798
1143
  requiredFreshContentVariants = [],
799
1144
  firstFreshDeliveryRequirements = [],
1145
+ includeCacheTakeover = false,
800
1146
  ) {
801
1147
  const measurements = visibleMeasurements(
802
1148
  records,
@@ -849,10 +1195,9 @@ function summarize(
849
1195
  monotonicValues.length > 0 ? Math.max(...monotonicValues) : null,
850
1196
  visibleMeasurements: measurements,
851
1197
  visibleMeasurementCohorts: visibleMeasurementCohorts(measurements),
852
- cacheTakeoverMeasurement: cacheTakeoverMeasurement(
853
- records,
854
- requiredFreshContentVariants,
855
- ),
1198
+ cacheTakeoverMeasurement: includeCacheTakeover
1199
+ ? cacheTakeoverMeasurement(records, requiredFreshContentVariants)
1200
+ : { status: "not_required" },
856
1201
  socketPipelineMeasurements: socketPipelineMeasurements(records),
857
1202
  firstFreshDeliveryChecks: firstFreshDeliveryChecks(
858
1203
  records,
@@ -885,15 +1230,29 @@ export async function capturePerpsPerformance(input) {
885
1230
  await mkdir(artifactsDir, { recursive: true });
886
1231
 
887
1232
  if (phase === "start") {
888
- const offset = await fileSize(sourceFile);
889
- const existingContent =
890
- offset > 0 ? (await readFile(sourceFile)).toString("utf8") : "";
1233
+ const sourceIdentity = await fileState(sourceFile);
1234
+ const offset = sourceIdentity?.size ?? 0;
1235
+ const lookbackStart = Math.max(0, offset - BOOTSTRAP_LOOKBACK_BYTES);
1236
+ const existingContent = sourceIdentity
1237
+ ? (
1238
+ await readFileRange(sourceFile, lookbackStart, offset - lookbackStart)
1239
+ ).toString("utf8")
1240
+ : "";
1241
+ const boundaryStart = Math.max(0, offset - CAPTURE_BOUNDARY_BYTES);
1242
+ const sourceBoundary = sourceIdentity
1243
+ ? captureBoundaryBytes(
1244
+ boundaryStart,
1245
+ await readFileRange(sourceFile, boundaryStart, offset - boundaryStart),
1246
+ )
1247
+ : null;
891
1248
  await writeFile(
892
1249
  stateFile,
893
1250
  `${JSON.stringify(
894
1251
  {
895
1252
  sourcePath,
896
1253
  offset,
1254
+ sourceIdentity,
1255
+ sourceBoundary,
897
1256
  captureStartedAtEpochMs: Date.now(),
898
1257
  perpsBootstrapStartRecord:
899
1258
  latestPerpsBootstrapStartRecord(existingContent),
@@ -918,6 +1277,19 @@ export async function capturePerpsPerformance(input) {
918
1277
  state.sourcePath !== sourcePath ||
919
1278
  !Number.isInteger(state.offset) ||
920
1279
  state.offset < 0 ||
1280
+ !(
1281
+ state.sourceIdentity === null ||
1282
+ (state.sourceIdentity &&
1283
+ Number.isInteger(state.sourceIdentity.device) &&
1284
+ Number.isInteger(state.sourceIdentity.inode))
1285
+ ) ||
1286
+ !(
1287
+ state.sourceBoundary === null ||
1288
+ (state.sourceBoundary &&
1289
+ Number.isInteger(state.sourceBoundary.start) &&
1290
+ Number.isInteger(state.sourceBoundary.length) &&
1291
+ typeof state.sourceBoundary.sha256 === "string")
1292
+ ) ||
921
1293
  !Number.isFinite(state.captureStartedAtEpochMs)
922
1294
  ) {
923
1295
  throw new Error(
@@ -928,11 +1300,11 @@ export async function capturePerpsPerformance(input) {
928
1300
  await waitForPerformanceRecord({
929
1301
  node,
930
1302
  sourceFile,
931
- offset: state.offset,
1303
+ state,
932
1304
  });
933
1305
 
934
- const content = await readFile(sourceFile);
935
- const offset = state.offset <= content.length ? state.offset : 0;
1306
+ const content = await readCaptureSource(sourceFile, state);
1307
+ const offset = state.offset;
936
1308
  const segment = content.subarray(offset).toString("utf8");
937
1309
  const segmentLines = segment.split(/\r?\n/u);
938
1310
  const lines = segmentLines
@@ -959,10 +1331,7 @@ export async function capturePerpsPerformance(input) {
959
1331
  .map((line) => parseRecord(line, LOAD_PROOF_MARKER))
960
1332
  .filter(Boolean),
961
1333
  ];
962
- const loadProofRecords = mergeLoadProofRecords([
963
- ...markerLoadProofRecords,
964
- ...existingLiveStreamRecords(segmentLines, markerLoadProofRecords),
965
- ]);
1334
+ const loadProofRecords = mergeLoadProofRecords(markerLoadProofRecords);
966
1335
  const requireRecords = node.require_records !== false;
967
1336
  const requiredStages = Array.isArray(node.required_stages)
968
1337
  ? node.required_stages.map(String)
@@ -1048,17 +1417,19 @@ export async function capturePerpsPerformance(input) {
1048
1417
  const requiredLiveStreams = Array.isArray(node.required_live_streams)
1049
1418
  ? node.required_live_streams.map(String)
1050
1419
  : [];
1051
- const presentLiveStreams = new Set(
1052
- loadProofRecords
1053
- .filter(
1054
- (record) =>
1055
- record.stage === "values_ready" && record.source === "fresh_socket",
1056
- )
1057
- .map((record) => String(record.stream ?? "")),
1058
- );
1059
- const missingLiveStreams = requiredLiveStreams.filter(
1060
- (stream) => !presentLiveStreams.has(stream),
1420
+ const coherentProof = coherentPerformanceProof(
1421
+ records,
1422
+ loadProofRecords,
1423
+ requiredStages,
1424
+ requiredLiveStreams,
1425
+ node.wait_for_lifecycle === undefined
1426
+ ? null
1427
+ : String(node.wait_for_lifecycle),
1428
+ node.wait_for_content_variant === undefined
1429
+ ? null
1430
+ : String(node.wait_for_content_variant),
1061
1431
  );
1432
+ const missingLiveStreams = coherentProof.missingLiveStreams;
1062
1433
  const measuredPerpsBootstrapBoundary = perpsBootstrapBoundary(
1063
1434
  records,
1064
1435
  loadProofRecords,
@@ -1088,6 +1459,7 @@ export async function capturePerpsPerformance(input) {
1088
1459
  missingFreshContentVariants.length === 0 &&
1089
1460
  failedFirstFreshDeliveries.length === 0 &&
1090
1461
  missingLiveStreams.length === 0 &&
1462
+ coherentProof.status !== "fail" &&
1091
1463
  (!requirePerpsBootstrapStartBeforeDemand ||
1092
1464
  measuredPerpsBootstrapBoundary.status === "pass") &&
1093
1465
  (!requireCacheBeforeFresh || cacheTakeover.status === "pass")
@@ -1102,6 +1474,9 @@ export async function capturePerpsPerformance(input) {
1102
1474
  missingFreshContentVariants,
1103
1475
  failedFirstFreshDeliveries,
1104
1476
  missingLiveStreams,
1477
+ coherentSurfaceAndLive: coherentProof.status,
1478
+ coherentIdentity: coherentProof.identity,
1479
+ coherentSurfaceSequence: coherentProof.sequence,
1105
1480
  perpsBootstrapStartBeforeDemand: requirePerpsBootstrapStartBeforeDemand
1106
1481
  ? measuredPerpsBootstrapBoundary.status
1107
1482
  : "not_required",
@@ -1120,6 +1495,7 @@ export async function capturePerpsPerformance(input) {
1120
1495
  content.length - offset,
1121
1496
  requiredFreshContentVariants,
1122
1497
  firstFreshDeliveryRequirements,
1498
+ requireCacheBeforeFresh,
1123
1499
  ),
1124
1500
  captureWindow: {
1125
1501
  startedAtEpochMs: state.captureStartedAtEpochMs,
@@ -1149,6 +1525,11 @@ export async function capturePerpsPerformance(input) {
1149
1525
  `Missing required ${STARTUP_MARKER} stages: ${missingStartupStages.join(", ")}.`,
1150
1526
  );
1151
1527
  }
1528
+ if (coherentProof.status === "fail") {
1529
+ throw new Error(
1530
+ `Required ${MARKER} surface stages and live streams did not form one ordered identity-coherent demand tuple.`,
1531
+ );
1532
+ }
1152
1533
  if (
1153
1534
  requirePerpsBootstrapStartBeforeDemand &&
1154
1535
  measuredPerpsBootstrapBoundary.status !== "pass"