@alwaysmeticulous/debug-workspace 2.275.1 → 2.276.2

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 (36) hide show
  1. package/README.md +8 -1
  2. package/dist/__tests__/extract-screenshot-dom-files.spec.d.ts +1 -0
  3. package/dist/__tests__/extract-screenshot-dom-files.spec.js +59 -0
  4. package/dist/__tests__/extract-screenshot-dom-files.spec.js.map +1 -0
  5. package/dist/__tests__/fetch-dom-diffs.spec.d.ts +1 -0
  6. package/dist/__tests__/fetch-dom-diffs.spec.js +316 -0
  7. package/dist/__tests__/fetch-dom-diffs.spec.js.map +1 -0
  8. package/dist/download-debug-data.js +25 -11
  9. package/dist/download-debug-data.js.map +1 -1
  10. package/dist/extract-screenshot-dom-files.d.ts +6 -0
  11. package/dist/extract-screenshot-dom-files.js +104 -0
  12. package/dist/extract-screenshot-dom-files.js.map +1 -0
  13. package/dist/fetch-dom-diffs.d.ts +36 -0
  14. package/dist/fetch-dom-diffs.js +338 -0
  15. package/dist/fetch-dom-diffs.js.map +1 -0
  16. package/dist/generate-debug-derived-files.js +57 -91
  17. package/dist/generate-debug-derived-files.js.map +1 -1
  18. package/dist/generate-debug-workspace.d.ts +10 -2
  19. package/dist/generate-debug-workspace.js +81 -84
  20. package/dist/generate-debug-workspace.js.map +1 -1
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +7 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/pipeline.d.ts +2 -1
  25. package/dist/pipeline.js +6 -5
  26. package/dist/pipeline.js.map +1 -1
  27. package/dist/replay-walk.d.ts +40 -0
  28. package/dist/replay-walk.js +57 -0
  29. package/dist/replay-walk.js.map +1 -0
  30. package/dist/resolve-debug-context.js +12 -15
  31. package/dist/resolve-debug-context.js.map +1 -1
  32. package/dist/screenshot-identifier.d.ts +19 -0
  33. package/dist/screenshot-identifier.js +51 -0
  34. package/dist/screenshot-identifier.js.map +1 -0
  35. package/dist/templates/CLAUDE.md +115 -78
  36. package/package.json +6 -6
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e13ec865-b015-5912-8934-fc90cab78689")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3c3e6a18-3b50-54ba-a2e4-296e73c18524")}catch(e){}}();
3
3
 
4
4
  var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -13,11 +13,13 @@ const path_1 = require("path");
13
13
  const common_1 = require("@alwaysmeticulous/common");
14
14
  const chalk_1 = __importDefault(require("chalk"));
15
15
  const debug_constants_1 = require("./debug-constants");
16
+ const extract_screenshot_dom_files_1 = require("./extract-screenshot-dom-files");
17
+ const fetch_dom_diffs_1 = require("./fetch-dom-diffs");
16
18
  const generate_debug_derived_files_1 = require("./generate-debug-derived-files");
19
+ const screenshot_identifier_1 = require("./screenshot-identifier");
17
20
  const TEMPLATES_DIR = (0, path_1.join)(__dirname, "templates");
18
- const generateDebugWorkspace = (options) => {
19
- var _a;
20
- const { debugContext, workspaceDir } = options;
21
+ const generateDebugWorkspace = async (options) => {
22
+ const { client, debugContext, workspaceDir } = options;
21
23
  const claudeDir = (0, path_1.join)(workspaceDir, ".claude");
22
24
  (0, fs_1.mkdirSync)(claudeDir, { recursive: true });
23
25
  copyClaudeMd(workspaceDir, options.additionalTemplatesDir);
@@ -30,13 +32,20 @@ const generateDebugWorkspace = (options) => {
30
32
  generateTimelineSummaries(workspaceDir);
31
33
  generateSessionSummaries(debugContext, workspaceDir);
32
34
  prettifySnapshotAssets(workspaceDir);
35
+ (0, extract_screenshot_dom_files_1.extractScreenshotDomFiles)(workspaceDir);
36
+ const domDiffMap = await (0, fetch_dom_diffs_1.fetchDomDiffs)({
37
+ client,
38
+ debugContext,
39
+ workspaceDir,
40
+ maxConcurrency: options.maxConcurrency,
41
+ });
33
42
  (0, generate_debug_derived_files_1.generateDebugDerivedFiles)(workspaceDir);
34
43
  const screenshotMap = buildScreenshotMap(debugContext, workspaceDir);
35
44
  generateScreenshotContext(debugContext, workspaceDir, screenshotMap);
36
45
  const replayComparison = buildReplayComparison(debugContext, workspaceDir);
37
46
  const fileMetadata = collectFileMetadata(debugContext, workspaceDir);
38
- const writeCtx = (_a = options.writeContextJson) !== null && _a !== void 0 ? _a : defaultWriteContextJson;
39
- writeCtx(debugContext, workspaceDir, fileMetadata, options.projectRepoDir, screenshotMap, replayComparison);
47
+ const writeCtx = options.writeContextJson ?? defaultWriteContextJson;
48
+ writeCtx(debugContext, workspaceDir, fileMetadata, options.projectRepoDir, screenshotMap, replayComparison, domDiffMap);
40
49
  copyClaudeSubdir(workspaceDir, "rules", options.additionalTemplatesDir);
41
50
  copyClaudeSubdir(workspaceDir, "hooks", options.additionalTemplatesDir, {
42
51
  makeExecutable: true,
@@ -234,7 +243,6 @@ const generateLogDiffs = (debugContext, workspaceDir) => {
234
243
  }
235
244
  };
236
245
  const generateLogDiffPair = (basePath, headPath, workspaceDir, baseName) => {
237
- var _a;
238
246
  const diffDir = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "log-diffs");
239
247
  (0, fs_1.mkdirSync)(diffDir, { recursive: true });
240
248
  let rawDiff;
@@ -245,7 +253,7 @@ const generateLogDiffPair = (basePath, headPath, workspaceDir, baseName) => {
245
253
  });
246
254
  }
247
255
  catch (error) {
248
- rawDiff = (_a = error === null || error === void 0 ? void 0 : error.stdout) !== null && _a !== void 0 ? _a : "";
256
+ rawDiff = error?.stdout ?? "";
249
257
  }
250
258
  if (!rawDiff.trim()) {
251
259
  return;
@@ -278,12 +286,11 @@ const filterLogDiff = (rawDiff) => {
278
286
  return removeIdenticalHunks(filteredLines.join("\n"));
279
287
  };
280
288
  const removeIdenticalHunks = (diff) => {
281
- var _a;
282
289
  const parts = diff.split(/^(@@[^@]*@@.*$)/m);
283
290
  const result = [parts[0]];
284
291
  for (let i = 1; i < parts.length; i += 2) {
285
292
  const hunkHeader = parts[i];
286
- const hunkBody = (_a = parts[i + 1]) !== null && _a !== void 0 ? _a : "";
293
+ const hunkBody = parts[i + 1] ?? "";
287
294
  const addedLines = [];
288
295
  const removedLines = [];
289
296
  for (const line of hunkBody.split("\n")) {
@@ -330,7 +337,7 @@ const summarizeLogDiff = (rawDiff) => {
330
337
  `================`,
331
338
  ``,
332
339
  `Total changed lines: ${addedCount + removedCount} (+${addedCount} in head, -${removedCount} in base)`,
333
- `First divergence at base log line: ${firstDivergenceLine !== null && firstDivergenceLine !== void 0 ? firstDivergenceLine : "unknown"}`,
340
+ `First divergence at base log line: ${firstDivergenceLine ?? "unknown"}`,
334
341
  ``,
335
342
  `Change categories (+ = extra in head, - = extra in base):`,
336
343
  ];
@@ -348,10 +355,9 @@ const summarizeLogDiff = (rawDiff) => {
348
355
  return parts.join("\n");
349
356
  };
350
357
  const categorizeLogLine = (line, categories, direction) => {
351
- var _a;
352
358
  const content = line.slice(1);
353
359
  const category = classifyLogContent(content);
354
- const entry = (_a = categories[category]) !== null && _a !== void 0 ? _a : { added: 0, removed: 0 };
360
+ const entry = categories[category] ?? { added: 0, removed: 0 };
355
361
  entry[direction]++;
356
362
  categories[category] = entry;
357
363
  };
@@ -380,7 +386,6 @@ const classifyLogContent = (content) => {
380
386
  return "other";
381
387
  };
382
388
  const generateDiffSummaries = (workspaceDir) => {
383
- var _a, _b;
384
389
  const diffsDir = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "diffs");
385
390
  if (!(0, fs_1.existsSync)(diffsDir)) {
386
391
  return;
@@ -389,7 +394,7 @@ const generateDiffSummaries = (workspaceDir) => {
389
394
  const jsonFiles = (0, fs_1.readdirSync)(diffsDir).filter((f) => f.endsWith(".json") && !f.endsWith(".summary.json"));
390
395
  for (const file of jsonFiles) {
391
396
  const raw = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(diffsDir, file), "utf8"));
392
- const results = (_b = (_a = raw === null || raw === void 0 ? void 0 : raw.data) === null || _a === void 0 ? void 0 : _a.screenshotDiffResults) !== null && _b !== void 0 ? _b : [];
397
+ const results = raw?.data?.screenshotDiffResults ?? [];
393
398
  if (results.length === 0) {
394
399
  continue;
395
400
  }
@@ -425,7 +430,6 @@ const generateDiffSummaries = (workspaceDir) => {
425
430
  // PR diff from project repo
426
431
  // ---------------------------------------------------------------------------
427
432
  const generatePrDiff = (debugContext, workspaceDir) => {
428
- var _a;
429
433
  const projectRepoDir = (0, path_1.join)(workspaceDir, "project-repo");
430
434
  if (!(0, fs_1.existsSync)(projectRepoDir)) {
431
435
  return;
@@ -435,7 +439,7 @@ const generatePrDiff = (debugContext, workspaceDir) => {
435
439
  if (!headSha) {
436
440
  return;
437
441
  }
438
- const effectiveBaseSha = baseSha !== null && baseSha !== void 0 ? baseSha : resolveBaseShaFromGit(projectRepoDir, headSha);
442
+ const effectiveBaseSha = baseSha ?? resolveBaseShaFromGit(projectRepoDir, headSha);
439
443
  if (!effectiveBaseSha) {
440
444
  return;
441
445
  }
@@ -444,7 +448,7 @@ const generatePrDiff = (debugContext, workspaceDir) => {
444
448
  diffOutput = (0, child_process_1.execFileSync)("git", ["diff", `${effectiveBaseSha}..${headSha}`], { cwd: projectRepoDir, encoding: "utf8", maxBuffer: 50 * 1024 * 1024 });
445
449
  }
446
450
  catch (error) {
447
- diffOutput = (_a = error === null || error === void 0 ? void 0 : error.stdout) !== null && _a !== void 0 ? _a : "";
451
+ diffOutput = error?.stdout ?? "";
448
452
  }
449
453
  if (diffOutput.trim()) {
450
454
  (0, fs_1.writeFileSync)((0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "pr-diff.txt"), diffOutput);
@@ -469,7 +473,6 @@ const resolveBaseShaFromGit = (repoDir, headSha) => {
469
473
  // Params diffs
470
474
  // ---------------------------------------------------------------------------
471
475
  const generateParamsDiffs = (debugContext, workspaceDir) => {
472
- var _a;
473
476
  const paramsFile = "launchBrowserAndReplayParams.json";
474
477
  const pairs = [];
475
478
  for (const diff of debugContext.replayDiffs) {
@@ -510,7 +513,7 @@ const generateParamsDiffs = (debugContext, workspaceDir) => {
510
513
  });
511
514
  }
512
515
  catch (diffError) {
513
- diffOutput = (_a = diffError === null || diffError === void 0 ? void 0 : diffError.stdout) !== null && _a !== void 0 ? _a : "";
516
+ diffOutput = diffError?.stdout ?? "";
514
517
  }
515
518
  finally {
516
519
  safeUnlink(tmpA);
@@ -578,7 +581,6 @@ const generateAssetsDiff = (debugContext, workspaceDir) => {
578
581
  }
579
582
  };
580
583
  const compareAssetDirs = (baseDir, headDir) => {
581
- var _a;
582
584
  const baseFiles = listAssetFiles(baseDir);
583
585
  const headFiles = listAssetFiles(headDir);
584
586
  if (baseFiles.size === 0 && headFiles.size === 0) {
@@ -593,7 +595,7 @@ const compareAssetDirs = (baseDir, headDir) => {
593
595
  const baseInfo = baseFiles.get(name);
594
596
  const headInfo = headFiles.get(name);
595
597
  if (!baseInfo) {
596
- added.push(` + ${name} (${(_a = headInfo === null || headInfo === void 0 ? void 0 : headInfo.size) !== null && _a !== void 0 ? _a : 0} bytes)`);
598
+ added.push(` + ${name} (${headInfo?.size ?? 0} bytes)`);
597
599
  }
598
600
  else if (!headInfo) {
599
601
  removed.push(` - ${name} (${baseInfo.size} bytes)`);
@@ -681,7 +683,6 @@ const generateTimelineSummaries = (workspaceDir) => {
681
683
  }
682
684
  };
683
685
  const summarizeTimeline = (timeline, replayId, role) => {
684
- var _a, _b, _c, _d, _e, _f, _g;
685
686
  const eventKindCounts = {};
686
687
  const screenshotEntries = [];
687
688
  let navigationCount = 0;
@@ -693,7 +694,7 @@ const summarizeTimeline = (timeline, replayId, role) => {
693
694
  const flakinessWarnings = [];
694
695
  for (const entry of timeline) {
695
696
  const kind = entry.kind;
696
- eventKindCounts[kind] = ((_a = eventKindCounts[kind]) !== null && _a !== void 0 ? _a : 0) + 1;
697
+ eventKindCounts[kind] = (eventKindCounts[kind] ?? 0) + 1;
697
698
  const vt = entry.virtualTimeStart;
698
699
  if (vt != null) {
699
700
  if (firstVirtualTime == null || vt < firstVirtualTime) {
@@ -706,17 +707,19 @@ const summarizeTimeline = (timeline, replayId, role) => {
706
707
  if (kind.startsWith("potentialFlakinessWarning")) {
707
708
  flakinessWarnings.push({
708
709
  kind,
709
- message: (_e = (_c = (_b = entry.data) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : (_d = entry.data) === null || _d === void 0 ? void 0 : _d.warning) !== null && _e !== void 0 ? _e : JSON.stringify((_f = entry.data) !== null && _f !== void 0 ? _f : {}),
710
+ message: entry.data?.message ??
711
+ entry.data?.warning ??
712
+ JSON.stringify(entry.data ?? {}),
710
713
  virtualTime: vt,
711
714
  });
712
715
  }
713
716
  switch (kind) {
714
717
  case "screenshot": {
715
- const filename = ((_g = entry.data) === null || _g === void 0 ? void 0 : _g.identifier)
716
- ? screenshotIdentifierToFilename(entry.data.identifier)
718
+ const filename = entry.data?.identifier
719
+ ? (0, screenshot_identifier_1.screenshotIdentifierToFilename)(entry.data.identifier)
717
720
  : undefined;
718
721
  screenshotEntries.push({
719
- filename: filename !== null && filename !== void 0 ? filename : "unknown",
722
+ filename: filename ?? "unknown",
720
723
  virtualTime: vt,
721
724
  });
722
725
  break;
@@ -748,7 +751,7 @@ const summarizeTimeline = (timeline, replayId, role) => {
748
751
  "",
749
752
  `Total timeline entries: ${timeline.length}`,
750
753
  `Total virtual time: ${totalVirtualTimeMs != null ? `${totalVirtualTimeMs}ms` : "unknown"}`,
751
- `Virtual time range: ${firstVirtualTime !== null && firstVirtualTime !== void 0 ? firstVirtualTime : "?"} - ${lastVirtualTime !== null && lastVirtualTime !== void 0 ? lastVirtualTime : "?"}`,
754
+ `Virtual time range: ${firstVirtualTime ?? "?"} - ${lastVirtualTime ?? "?"}`,
752
755
  "",
753
756
  "Key counts:",
754
757
  ` Screenshots: ${screenshotEntries.length}`,
@@ -878,7 +881,6 @@ const findAssetFilesRecursive = (baseDir, relativeTo) => {
878
881
  // ---------------------------------------------------------------------------
879
882
  const SCREENSHOT_LOG_CONTEXT_LINES = 30;
880
883
  const buildScreenshotMap = (debugContext, workspaceDir) => {
881
- var _a, _b, _c, _d;
882
884
  const map = {};
883
885
  for (const subDir of ["head", "base", "other"]) {
884
886
  const subDirPath = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "replays", subDir);
@@ -894,22 +896,32 @@ const buildScreenshotMap = (debugContext, workspaceDir) => {
894
896
  if (!Array.isArray(timeline)) {
895
897
  continue;
896
898
  }
899
+ const screenshotsDir = (0, path_1.join)(subDirPath, replayId, "screenshots");
897
900
  for (const entry of timeline) {
898
901
  const e = entry;
899
- if (e.kind !== "screenshot" || !((_a = e.data) === null || _a === void 0 ? void 0 : _a.identifier)) {
902
+ if (e.kind !== "screenshot" || !e.data?.identifier) {
900
903
  continue;
901
904
  }
902
- const filename = screenshotIdentifierToFilename(e.data.identifier);
905
+ const filename = (0, screenshot_identifier_1.screenshotIdentifierToFilename)(e.data.identifier);
903
906
  if (!filename) {
904
907
  continue;
905
908
  }
909
+ const baseName = filename.endsWith(".png")
910
+ ? filename.slice(0, -".png".length)
911
+ : filename;
912
+ const htmlFilename = `${baseName}.html`;
913
+ const afterHtmlFilename = `${baseName}.after.html`;
914
+ const htmlExists = (0, fs_1.existsSync)((0, path_1.join)(screenshotsDir, htmlFilename));
915
+ const afterHtmlExists = (0, fs_1.existsSync)((0, path_1.join)(screenshotsDir, afterHtmlFilename));
906
916
  map[`${subDir}/${replayId}/${filename}`] = {
907
917
  replayId,
908
918
  replayRole: subDir,
909
919
  filename,
910
- virtualTimeStart: (_b = e.virtualTimeStart) !== null && _b !== void 0 ? _b : null,
911
- virtualTimeEnd: (_c = e.virtualTimeEnd) !== null && _c !== void 0 ? _c : null,
912
- eventNumber: (_d = e.data.identifier.eventNumber) !== null && _d !== void 0 ? _d : null,
920
+ virtualTimeStart: e.virtualTimeStart ?? null,
921
+ virtualTimeEnd: e.virtualTimeEnd ?? null,
922
+ eventNumber: e.data.identifier.eventNumber ?? null,
923
+ htmlFilename: htmlExists ? htmlFilename : null,
924
+ afterHtmlFilename: afterHtmlExists ? afterHtmlFilename : null,
913
925
  };
914
926
  }
915
927
  }
@@ -919,23 +931,7 @@ const buildScreenshotMap = (debugContext, workspaceDir) => {
919
931
  }
920
932
  return map;
921
933
  };
922
- const screenshotIdentifierToFilename = (identifier) => {
923
- const variantPortion = identifier.variant === "redacted" ? ".redacted" : "";
924
- if (identifier.type === "end-state") {
925
- return identifier.logicVersion == null
926
- ? `final-state${variantPortion}.png`
927
- : `final-state-v${identifier.logicVersion}${variantPortion}.png`;
928
- }
929
- if (identifier.type === "after-event" && identifier.eventNumber != null) {
930
- const eventIndexStr = identifier.eventNumber.toString().padStart(5, "0");
931
- return identifier.logicVersion == null
932
- ? `screenshot-after-event-${eventIndexStr}${variantPortion}.png`
933
- : `screenshot-after-event-${eventIndexStr}-v${identifier.logicVersion}${variantPortion}.png`;
934
- }
935
- return undefined;
936
- };
937
934
  const generateScreenshotContext = (debugContext, workspaceDir, screenshotMap) => {
938
- var _a, _b, _c, _d;
939
935
  if (!debugContext.screenshot) {
940
936
  return;
941
937
  }
@@ -952,14 +948,14 @@ const generateScreenshotContext = (debugContext, workspaceDir, screenshotMap) =>
952
948
  "",
953
949
  ];
954
950
  if (headEntry) {
955
- parts.push(`HEAD (${diff.headReplayId}) @ virtualTime ${(_a = headEntry.virtualTimeStart) !== null && _a !== void 0 ? _a : "?"}ms, event ${(_b = headEntry.eventNumber) !== null && _b !== void 0 ? _b : "?"}:`, "");
951
+ parts.push(`HEAD (${diff.headReplayId}) @ virtualTime ${headEntry.virtualTimeStart ?? "?"}ms, event ${headEntry.eventNumber ?? "?"}:`, "");
956
952
  const headContext = extractLogContext(headLogPath, headEntry);
957
- parts.push(headContext !== null && headContext !== void 0 ? headContext : " (could not extract log context)", "");
953
+ parts.push(headContext ?? " (could not extract log context)", "");
958
954
  }
959
955
  if (baseEntry) {
960
- parts.push(`BASE (${diff.baseReplayId}) @ virtualTime ${(_c = baseEntry.virtualTimeStart) !== null && _c !== void 0 ? _c : "?"}ms, event ${(_d = baseEntry.eventNumber) !== null && _d !== void 0 ? _d : "?"}:`, "");
956
+ parts.push(`BASE (${diff.baseReplayId}) @ virtualTime ${baseEntry.virtualTimeStart ?? "?"}ms, event ${baseEntry.eventNumber ?? "?"}:`, "");
961
957
  const baseContext = extractLogContext(baseLogPath, baseEntry);
962
- parts.push(baseContext !== null && baseContext !== void 0 ? baseContext : " (could not extract log context)", "");
958
+ parts.push(baseContext ?? " (could not extract log context)", "");
963
959
  }
964
960
  if (headEntry || baseEntry) {
965
961
  const contextDir = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "screenshot-context");
@@ -1026,7 +1022,6 @@ const buildReplayComparison = (debugContext, workspaceDir) => {
1026
1022
  return entries;
1027
1023
  };
1028
1024
  const extractReplayStats = (replayDir) => {
1029
- var _a, _b, _c;
1030
1025
  const stats = {
1031
1026
  totalEvents: null,
1032
1027
  totalNetworkRequests: null,
@@ -1037,10 +1032,10 @@ const extractReplayStats = (replayDir) => {
1037
1032
  const timelineStatsPath = (0, path_1.join)(replayDir, "timeline-stats.json");
1038
1033
  if ((0, fs_1.existsSync)(timelineStatsPath)) {
1039
1034
  const timelineStats = JSON.parse((0, fs_1.readFileSync)(timelineStatsPath, "utf8"));
1040
- const counts = (_a = timelineStats.countByType) !== null && _a !== void 0 ? _a : {};
1035
+ const counts = timelineStats.countByType ?? {};
1041
1036
  stats.totalEvents = Object.values(counts).reduce((sum, n) => sum + n, 0);
1042
- stats.totalNetworkRequests = (_b = counts["pollyReplay"]) !== null && _b !== void 0 ? _b : null;
1043
- stats.totalAnimationFrames = (_c = counts["jsReplay"]) !== null && _c !== void 0 ? _c : null;
1037
+ stats.totalNetworkRequests = counts["pollyReplay"] ?? null;
1038
+ stats.totalAnimationFrames = counts["jsReplay"] ?? null;
1044
1039
  }
1045
1040
  const timelinePath = (0, path_1.join)(replayDir, "timeline.json");
1046
1041
  if ((0, fs_1.existsSync)(timelinePath)) {
@@ -1155,22 +1150,21 @@ const generateSessionSummaries = (debugContext, workspaceDir) => {
1155
1150
  }
1156
1151
  };
1157
1152
  const summarizeSession = (data, sessionId) => {
1158
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
1159
1153
  const parts = [
1160
1154
  `Session Summary: ${sessionId}`,
1161
1155
  "=".repeat(20 + sessionId.length),
1162
1156
  "",
1163
1157
  ];
1164
- const win = (_a = data.userEvents) === null || _a === void 0 ? void 0 : _a.window;
1165
- parts.push(`Window: ${(_b = win === null || win === void 0 ? void 0 : win.startUrl) !== null && _b !== void 0 ? _b : "unknown"}`);
1166
- if ((win === null || win === void 0 ? void 0 : win.width) != null && (win === null || win === void 0 ? void 0 : win.height) != null) {
1158
+ const win = data.userEvents?.window;
1159
+ parts.push(`Window: ${win?.startUrl ?? "unknown"}`);
1160
+ if (win?.width != null && win?.height != null) {
1167
1161
  parts.push(`Viewport: ${win.width} x ${win.height}`);
1168
1162
  }
1169
- parts.push(`Hostname: ${(_c = data.hostname) !== null && _c !== void 0 ? _c : "unknown"}`);
1170
- parts.push(`Recorded: ${(_d = data.datetime_first_payload) !== null && _d !== void 0 ? _d : "unknown"}`);
1163
+ parts.push(`Hostname: ${data.hostname ?? "unknown"}`);
1164
+ parts.push(`Recorded: ${data.datetime_first_payload ?? "unknown"}`);
1171
1165
  parts.push(`Abandoned: ${data.abandoned ? "yes" : "no"}`);
1172
1166
  parts.push("");
1173
- const history = (_e = data.urlHistory) !== null && _e !== void 0 ? _e : [];
1167
+ const history = data.urlHistory ?? [];
1174
1168
  if (history.length > 0) {
1175
1169
  parts.push(`URL History (${history.length} pages):`);
1176
1170
  for (const entry of history) {
@@ -1178,16 +1172,16 @@ const summarizeSession = (data, sessionId) => {
1178
1172
  const pattern = entry.urlPattern
1179
1173
  ? ` [pattern: ${entry.urlPattern}]`
1180
1174
  : "";
1181
- parts.push(` ${ts} ${(_f = entry.url) !== null && _f !== void 0 ? _f : "unknown"}${pattern}`);
1175
+ parts.push(` ${ts} ${entry.url ?? "unknown"}${pattern}`);
1182
1176
  }
1183
1177
  parts.push("");
1184
1178
  }
1185
- const events = (_h = (_g = data.userEvents) === null || _g === void 0 ? void 0 : _g.event_log) !== null && _h !== void 0 ? _h : [];
1179
+ const events = data.userEvents?.event_log ?? [];
1186
1180
  if (events.length > 0) {
1187
1181
  const typeCounts = {};
1188
1182
  for (const event of events) {
1189
- typeCounts[(_j = event.type) !== null && _j !== void 0 ? _j : "unknown"] =
1190
- ((_l = typeCounts[(_k = event.type) !== null && _k !== void 0 ? _k : "unknown"]) !== null && _l !== void 0 ? _l : 0) + 1;
1183
+ typeCounts[event.type ?? "unknown"] =
1184
+ (typeCounts[event.type ?? "unknown"] ?? 0) + 1;
1191
1185
  }
1192
1186
  parts.push(`User Events: ${events.length} events`);
1193
1187
  for (const [type, count] of Object.entries(typeCounts).sort(([, a], [, b]) => b - a)) {
@@ -1195,15 +1189,15 @@ const summarizeSession = (data, sessionId) => {
1195
1189
  }
1196
1190
  parts.push("");
1197
1191
  }
1198
- const harContainer = (_m = data.pollyHAR) === null || _m === void 0 ? void 0 : _m.pollyHAR;
1192
+ const harContainer = data.pollyHAR?.pollyHAR;
1199
1193
  if (harContainer) {
1200
- const allEntries = Object.values(harContainer).flatMap((r) => { var _a, _b; return (_b = (_a = r === null || r === void 0 ? void 0 : r.log) === null || _a === void 0 ? void 0 : _a.entries) !== null && _b !== void 0 ? _b : []; });
1194
+ const allEntries = Object.values(harContainer).flatMap((r) => r?.log?.entries ?? []);
1201
1195
  if (allEntries.length > 0) {
1202
1196
  parts.push(`Network Requests: ${allEntries.length} total`);
1203
1197
  const methodCounts = {};
1204
1198
  for (const entry of allEntries) {
1205
- const method = (_p = (_o = entry.request) === null || _o === void 0 ? void 0 : _o.method) !== null && _p !== void 0 ? _p : "UNKNOWN";
1206
- methodCounts[method] = ((_q = methodCounts[method]) !== null && _q !== void 0 ? _q : 0) + 1;
1199
+ const method = entry.request?.method ?? "UNKNOWN";
1200
+ methodCounts[method] = (methodCounts[method] ?? 0) + 1;
1207
1201
  }
1208
1202
  parts.push(` Methods: ${Object.entries(methodCounts)
1209
1203
  .sort(([, a], [, b]) => b - a)
@@ -1212,19 +1206,19 @@ const summarizeSession = (data, sessionId) => {
1212
1206
  parts.push("");
1213
1207
  }
1214
1208
  }
1215
- const localStorage = (_u = (_t = (_s = (_r = data.randomEvents) === null || _r === void 0 ? void 0 : _r.localStorage) === null || _s === void 0 ? void 0 : _s.state) === null || _t === void 0 ? void 0 : _t.length) !== null && _u !== void 0 ? _u : 0;
1216
- const sessionStorage = (_y = (_x = (_w = (_v = data.randomEvents) === null || _v === void 0 ? void 0 : _v.sessionStorage) === null || _w === void 0 ? void 0 : _w.state) === null || _x === void 0 ? void 0 : _x.length) !== null && _y !== void 0 ? _y : 0;
1217
- const cookies = (_0 = (_z = data.cookies) === null || _z === void 0 ? void 0 : _z.length) !== null && _0 !== void 0 ? _0 : 0;
1209
+ const localStorage = data.randomEvents?.localStorage?.state?.length ?? 0;
1210
+ const sessionStorage = data.randomEvents?.sessionStorage?.state?.length ?? 0;
1211
+ const cookies = data.cookies?.length ?? 0;
1218
1212
  parts.push("Storage:");
1219
1213
  parts.push(` localStorage: ${localStorage} entries`);
1220
1214
  parts.push(` sessionStorage: ${sessionStorage} entries`);
1221
1215
  parts.push(` Cookies: ${cookies}`);
1222
1216
  parts.push("");
1223
- const connections = (_1 = data.webSocketData) !== null && _1 !== void 0 ? _1 : [];
1217
+ const connections = data.webSocketData ?? [];
1224
1218
  if (connections.length > 0) {
1225
1219
  parts.push(`WebSocket Connections: ${connections.length}`);
1226
1220
  for (const conn of connections) {
1227
- parts.push(` ${(_2 = conn.url) !== null && _2 !== void 0 ? _2 : "unknown"} (${(_4 = (_3 = conn.events) === null || _3 === void 0 ? void 0 : _3.length) !== null && _4 !== void 0 ? _4 : 0} events)`);
1221
+ parts.push(` ${conn.url ?? "unknown"} (${conn.events?.length ?? 0} events)`);
1228
1222
  }
1229
1223
  parts.push("");
1230
1224
  }
@@ -1234,21 +1228,21 @@ const summarizeSession = (data, sessionId) => {
1234
1228
  if (ctx.userId || ctx.userEmail) {
1235
1229
  parts.push(` User: ${[ctx.userId, ctx.userEmail].filter(Boolean).join(" / ")}`);
1236
1230
  }
1237
- const flags = Object.entries((_5 = ctx.featureFlags) !== null && _5 !== void 0 ? _5 : {});
1231
+ const flags = Object.entries(ctx.featureFlags ?? {});
1238
1232
  if (flags.length > 0) {
1239
1233
  parts.push(` Feature flags: ${flags.map(([k, v]) => `${k}=${v}`).join(", ")}`);
1240
1234
  }
1241
1235
  parts.push("");
1242
1236
  }
1243
1237
  const appData = data.applicationSpecificData;
1244
- if (appData === null || appData === void 0 ? void 0 : appData.nextJs) {
1238
+ if (appData?.nextJs) {
1245
1239
  parts.push("Framework: Next.js");
1246
1240
  if (appData.nextJs.page) {
1247
1241
  parts.push(` Page: ${appData.nextJs.page}`);
1248
1242
  }
1249
1243
  parts.push("");
1250
1244
  }
1251
- else if (appData === null || appData === void 0 ? void 0 : appData.reactRouter) {
1245
+ else if (appData?.reactRouter) {
1252
1246
  parts.push("Framework: React Router");
1253
1247
  parts.push("");
1254
1248
  }
@@ -1257,7 +1251,7 @@ const summarizeSession = (data, sessionId) => {
1257
1251
  // ---------------------------------------------------------------------------
1258
1252
  // Context JSON generation (default implementation)
1259
1253
  // ---------------------------------------------------------------------------
1260
- const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, projectRepoDir, screenshotMap, replayComparison) => {
1254
+ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, projectRepoDir, screenshotMap, replayComparison, domDiffMap) => {
1261
1255
  const headIds = new Set(debugContext.replayDiffs.map((d) => d.headReplayId));
1262
1256
  const baseIds = new Set(debugContext.replayDiffs.map((d) => d.baseReplayId));
1263
1257
  const headReplays = [];
@@ -1293,6 +1287,7 @@ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, proje
1293
1287
  sessions: debugContext.sessionIds,
1294
1288
  screenshotMap,
1295
1289
  replayComparison,
1290
+ domDiffMap,
1296
1291
  paths: {
1297
1292
  replays: "replays/",
1298
1293
  sessions: "sessions/",
@@ -1304,6 +1299,8 @@ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, proje
1304
1299
  assetsDiffs: "assets-diffs/",
1305
1300
  timelineSummaries: "timeline-summaries/",
1306
1301
  screenshotContext: "screenshot-context/",
1302
+ domDiffs: "dom-diffs/",
1303
+ domDiffsSummary: "dom-diffs/*.summary.txt",
1307
1304
  prDiff: "pr-diff.txt",
1308
1305
  formattedAssets: "formatted-assets/",
1309
1306
  testRun: "test-run/",
@@ -1314,4 +1311,4 @@ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, proje
1314
1311
  (0, fs_1.writeFileSync)((0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "context.json"), JSON.stringify(context, null, 2));
1315
1312
  };
1316
1313
  //# sourceMappingURL=generate-debug-workspace.js.map
1317
- //# debugId=e13ec865-b015-5912-8934-fc90cab78689
1314
+ //# debugId=3c3e6a18-3b50-54ba-a2e4-296e73c18524