ccqa 1.57.1 → 1.57.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.
package/dist/bin/ccqa.mjs CHANGED
@@ -13877,6 +13877,7 @@ function parseTraceEvents(jsonl) {
13877
13877
  const frames = [];
13878
13878
  const steps = [];
13879
13879
  const pendingByCallId = /* @__PURE__ */ new Map();
13880
+ const wallOffsets = /* @__PURE__ */ new Map();
13880
13881
  let maxTimestamp = -Infinity;
13881
13882
  for (const line of jsonl.split("\n")) {
13882
13883
  if (line.trim() === "") continue;
@@ -13900,8 +13901,13 @@ function parseTraceEvents(jsonl) {
13900
13901
  if (type === "screencast-frame") {
13901
13902
  if (typeof event.sha1 === "string" && typeof event.timestamp === "number") frames.push({
13902
13903
  sha1: event.sha1,
13903
- timestamp: event.timestamp
13904
+ timestamp: event.timestamp,
13905
+ ...typeof event.frameSwapWallTime === "number" ? { swapWallTime: event.frameSwapWallTime } : {}
13904
13906
  });
13907
+ } else if (type === "context-options") {
13908
+ if (typeof event.wallTime === "number" && typeof event.monotonicTime === "number") {
13909
+ if (!wallOffsets.has(event.origin)) wallOffsets.set(event.origin, event.wallTime - event.monotonicTime);
13910
+ }
13905
13911
  } else if (type === "action") {
13906
13912
  if (typeof event.callId === "string" && typeof event.startTime === "number" && typeof event.endTime === "number") steps.push({
13907
13913
  title: titleOf$1(event),
@@ -13932,10 +13938,16 @@ function parseTraceEvents(jsonl) {
13932
13938
  ...pending,
13933
13939
  endTime: maxTimestamp
13934
13940
  });
13935
- frames.sort((a, b) => a.timestamp - b.timestamp);
13941
+ const offset = wallOffsets.get("testRunner") ?? wallOffsets.values().next().value;
13942
+ const painted = offset !== void 0 && frames.every((f) => f.swapWallTime !== void 0);
13943
+ const placed = frames.map(({ sha1, timestamp, swapWallTime }) => ({
13944
+ sha1,
13945
+ timestamp: painted ? swapWallTime - offset : timestamp
13946
+ }));
13947
+ placed.sort((a, b) => a.timestamp - b.timestamp);
13936
13948
  steps.sort((a, b) => a.startTime - b.startTime);
13937
13949
  return {
13938
- frames,
13950
+ frames: placed,
13939
13951
  steps
13940
13952
  };
13941
13953
  }
@@ -13955,13 +13967,22 @@ function titleOf$1(event) {
13955
13967
  return "";
13956
13968
  }
13957
13969
  /**
13958
- * The frame on screen at `time`: the last one captured at or before it, or —
13959
- * when the step began before any frame was captured — the first frame after.
13960
- * Null when the trace holds no frames at all. `frames` comes from
13961
- * {@link parseTraceEvents}, which sorts them by timestamp.
13970
+ * One paint interval at 60fps. An assertion passes on the DOM, so a step can
13971
+ * end before the frame showing that DOM is painted — at most one interval later.
13972
+ */
13973
+ const ONE_FRAME_MS = 17;
13974
+ /**
13975
+ * The frame showing the page as it was at `time`: the last one painted within
13976
+ * a frame interval of it, or — when the step began before any frame was
13977
+ * captured — the first frame after. Null when the trace holds no frames at
13978
+ * all. `frames` comes from {@link parseTraceEvents}, sorted by paint time.
13979
+ *
13980
+ * A step's start takes the same allowance as its end: it is the same boundary
13981
+ * as the previous step's end, and would otherwise show that step unfinished.
13962
13982
  */
13963
13983
  function frameAt(frames, time) {
13964
- return frames.findLast((f) => f.timestamp <= time) ?? frames[0] ?? null;
13984
+ const painted = time + ONE_FRAME_MS;
13985
+ return frames.findLast((f) => f.timestamp <= painted) ?? frames[0] ?? null;
13965
13986
  }
13966
13987
  //#endregion
13967
13988
  //#region src/targets/playwright/trace-capture.ts
@@ -27331,7 +27352,7 @@ const evidenceCommand = addLanguageOption(new Command("evidence").argument("<cas
27331
27352
  anchors = await findSourceAnchors(sourceNeedles([...recording.actions, ...recording.cleanup ?? []]), roots);
27332
27353
  }
27333
27354
  const out = resolve(cwd, opts.out ?? join(testCase.ref.dir, "evidence.md"));
27334
- await writeFile(out, scrubEnvValues(renderEvidence({
27355
+ const markdown = renderEvidence({
27335
27356
  testCase,
27336
27357
  recording,
27337
27358
  test: {
@@ -27344,7 +27365,9 @@ const evidenceCommand = addLanguageOption(new Command("evidence").argument("<cas
27344
27365
  ...resolved.targetConfig.allowExpectInCleanup ? {} : { cleanupUnchecked: testCase.cleanupExpectations },
27345
27366
  ...review ? { review } : {},
27346
27367
  ...anchors ? { anchors } : {}
27347
- }), buildProseEnvScrubMap([], [])), "utf8");
27368
+ });
27369
+ await mkdir(dirname(out), { recursive: true });
27370
+ await writeFile(out, scrubEnvValues(markdown, buildProseEnvScrubMap([], [])), "utf8");
27348
27371
  process.stdout.write(`${relative(cwd, out) || out}\n`);
27349
27372
  hint("paste it into the pull request, or attach it — ccqa writes the table, not the body");
27350
27373
  }));
@@ -35,9 +35,9 @@ declare const RunSchema: z.ZodObject<{
35
35
  running: "running";
36
36
  }>;
37
37
  kind: z.ZodDefault<z.ZodEnum<{
38
+ record: "record";
38
39
  run: "run";
39
40
  drift: "drift";
40
- record: "record";
41
41
  }>>;
42
42
  drift: z.ZodDefault<z.ZodNullable<z.ZodObject<{
43
43
  specs: z.ZodNumber;
@@ -652,8 +652,8 @@ declare const ReportSpecResultSchema: z.ZodObject<{
652
652
  title: z.ZodNullable<z.ZodString>;
653
653
  target: z.ZodOptional<z.ZodString>;
654
654
  mode: z.ZodOptional<z.ZodEnum<{
655
- deterministic: "deterministic";
656
655
  live: "live";
656
+ deterministic: "deterministic";
657
657
  }>>;
658
658
  status: z.ZodEnum<{
659
659
  passed: "passed";
@@ -831,9 +831,9 @@ type ReportSpecResult = z.infer<typeof ReportSpecResultSchema>;
831
831
  declare const RunReportDataSchema: z.ZodObject<{
832
832
  schemaVersion: z.ZodLiteral<1>;
833
833
  kind: z.ZodDefault<z.ZodEnum<{
834
+ record: "record";
834
835
  run: "run";
835
836
  drift: "drift";
836
- record: "record";
837
837
  }>>;
838
838
  createdAt: z.ZodString;
839
839
  runId: z.ZodNullable<z.ZodString>;
@@ -874,8 +874,8 @@ declare const RunReportDataSchema: z.ZodObject<{
874
874
  title: z.ZodNullable<z.ZodString>;
875
875
  target: z.ZodOptional<z.ZodString>;
876
876
  mode: z.ZodOptional<z.ZodEnum<{
877
- deterministic: "deterministic";
878
877
  live: "live";
878
+ deterministic: "deterministic";
879
879
  }>>;
880
880
  status: z.ZodEnum<{
881
881
  passed: "passed";
@@ -35,9 +35,9 @@ declare const RunSchema: z.ZodObject<{
35
35
  running: "running";
36
36
  }>;
37
37
  kind: z.ZodDefault<z.ZodEnum<{
38
+ record: "record";
38
39
  run: "run";
39
40
  drift: "drift";
40
- record: "record";
41
41
  }>>;
42
42
  drift: z.ZodDefault<z.ZodNullable<z.ZodObject<{
43
43
  specs: z.ZodNumber;
@@ -652,8 +652,8 @@ declare const ReportSpecResultSchema: z.ZodObject<{
652
652
  title: z.ZodNullable<z.ZodString>;
653
653
  target: z.ZodOptional<z.ZodString>;
654
654
  mode: z.ZodOptional<z.ZodEnum<{
655
- deterministic: "deterministic";
656
655
  live: "live";
656
+ deterministic: "deterministic";
657
657
  }>>;
658
658
  status: z.ZodEnum<{
659
659
  passed: "passed";
@@ -831,9 +831,9 @@ type ReportSpecResult = z.infer<typeof ReportSpecResultSchema>;
831
831
  declare const RunReportDataSchema: z.ZodObject<{
832
832
  schemaVersion: z.ZodLiteral<1>;
833
833
  kind: z.ZodDefault<z.ZodEnum<{
834
+ record: "record";
834
835
  run: "run";
835
836
  drift: "drift";
836
- record: "record";
837
837
  }>>;
838
838
  createdAt: z.ZodString;
839
839
  runId: z.ZodNullable<z.ZodString>;
@@ -874,8 +874,8 @@ declare const RunReportDataSchema: z.ZodObject<{
874
874
  title: z.ZodNullable<z.ZodString>;
875
875
  target: z.ZodOptional<z.ZodString>;
876
876
  mode: z.ZodOptional<z.ZodEnum<{
877
- deterministic: "deterministic";
878
877
  live: "live";
878
+ deterministic: "deterministic";
879
879
  }>>;
880
880
  status: z.ZodEnum<{
881
881
  passed: "passed";
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.57.1",
3
+ "version": "1.57.2",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccqa",
3
- "version": "1.57.1",
3
+ "version": "1.57.2",
4
4
  "type": "module",
5
5
  "description": "Browser test recorder powered by Claude Code and agent-browser",
6
6
  "repository": {