refactor(cli): single-source-of-truth pass over the check branch

Every duplicated decision gets one owner: rectToBbox lives in checkTypes
(was verbatim in pipeline and browser layers); the audit seek tuning is
one exported AUDIT_SEEK_OPTIONS consumed by check and the deprecated
inspect path; zoom padding/scale defaults export from the capture module
instead of re-literalized in three files; the optional run_id property
is built by one helper across all three telemetry events; check's
--max-transition-samples parsing reuses its own positiveInteger helper;
validate drops a leftover re-export and redundant explicit-default args
go away.

Tests: the contrast candidate round-trip gains a real integration
anchor (the actual browser script eval'd in-page, a wrapper asserting
finish receives the page-script bbox shape) replacing regex-over-source
as the primary guard; the redundant geometry source-golden and a
duplicated deprecation-envelope assertion are dropped.
This commit is contained in:
Miguel Angel Simon Sierra
2026-07-10 13:52:31 -04:00
parent cf7c1d7609
commit cea3458016
13 changed files with 171 additions and 66 deletions
+10 -22
View File
@@ -2,6 +2,9 @@ import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import type { Page } from "puppeteer-core";
import {
AUDIT_SEEK_OPTIONS,
DEFAULT_ZOOM_PADDING_PX,
DEFAULT_ZOOM_SCALE,
captureRegionCrop,
openSettledCompositionPage,
padCropRegion,
@@ -15,6 +18,7 @@ import { normalizeErrorMessage } from "./errorMessage.js";
import { ambiguousIssue, type MotionFrame } from "./motionAudit.js";
import type { LayoutIssue, LayoutIssueCode, LayoutRect } from "./layoutAudit.js";
import { serveStaticProjectHtml } from "./staticProjectServer.js";
import { rectToBbox } from "./checkTypes.js";
import type {
AnchoredLayoutIssue,
CheckAnchor,
@@ -35,18 +39,6 @@ import type {
} from "./checkTypes.js";
import type { ProjectDir } from "./project.js";
const SEEK_OPTIONS = {
fallbackToBridgeAndTimelines: true,
animationFrameSettle: "double" as const,
waitForFontsMs: 500,
settleMs: 120,
};
// --zoom's default padding/scale, reused here so finding crops carry the same
// bit of surrounding context an agent gets from `snapshot --zoom`.
const FINDING_CROP_PADDING_PX = 24;
const FINDING_CROP_SCALE = 3;
interface RuntimeDraft {
code: string;
severity: CheckSeverity;
@@ -113,7 +105,7 @@ export async function runBrowserCheck(
});
chromeBrowser = session.browser;
const page = session.page;
await waitForPreferredSeekTarget(page, 500);
await waitForPreferredSeekTarget(page);
const rootAnchor = await resolveRootAnchor(page);
const launchSettleMs = Date.now() - launchSettleStart;
@@ -157,18 +149,18 @@ export async function captureFindingCrops(
});
chromeBrowser = session.browser;
const page = session.page;
await waitForPreferredSeekTarget(page, 500);
await waitForPreferredSeekTarget(page);
const snapshotDir = join(project.dir, "snapshots");
mkdirSync(snapshotDir, { recursive: true });
for (const request of requests) {
await seekCompositionTimeline(page, request.time, SEEK_OPTIONS);
await seekCompositionTimeline(page, request.time, AUDIT_SEEK_OPTIONS);
const canvas = await page.evaluate(() => ({
width: window.innerWidth,
height: window.innerHeight,
}));
const region = padCropRegion(request.bbox, canvas, FINDING_CROP_PADDING_PX);
const buffer = await captureRegionCrop(page, region, FINDING_CROP_SCALE);
const region = padCropRegion(request.bbox, canvas, DEFAULT_ZOOM_PADDING_PX);
const buffer = await captureRegionCrop(page, region, DEFAULT_ZOOM_SCALE);
writeFileSync(join(snapshotDir, request.filename), buffer);
written.push(join("snapshots", request.filename));
}
@@ -253,7 +245,7 @@ function createPageDriver(page: Page, setTime: (time: number) => void): CheckAud
findAmbiguousSelectors: (selectors) => findAmbiguousSelectors(page, selectors),
seek: async (time) => {
setTime(time);
await seekCompositionTimeline(page, time, SEEK_OPTIONS);
await seekCompositionTimeline(page, time, AUDIT_SEEK_OPTIONS);
},
collectLayout: (time, tolerance) => collectLayout(page, time, tolerance),
collectLayoutGeometry: () => collectLayoutGeometry(page),
@@ -899,10 +891,6 @@ function fallbackAnchor(request: AnchorRequest | undefined): CheckAnchor {
};
}
function rectToBbox(rect: LayoutRect): CheckBbox {
return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
}
function parseBbox(value: unknown): CheckBbox | null {
if (!isRecord(value)) return null;
const x = numberValue(value, "x");