From 7e8863fc7e65806f41e550fc42172685f31764ef Mon Sep 17 00:00:00 2001 From: Samraaj Bath Date: Sat, 4 Jul 2026 13:49:14 -0700 Subject: [PATCH] Capture hardening: deterministic env shim, extended lazy sweep, nav budget with bot-wall fast-fail Salvaged and re-implemented from PR #15: - Deterministic environment shim (seeded Math.random, pinned-but-advancing Date consistent across constructor/now/getTime/valueOf/toISOString) so time/random-dependent pages capture reproducibly; epoch and seed are recorded run metadata, performance.now stays real for motion sampling - Post-snapshot lazy-asset discovery sweep for channels the walker misses: noscript contents (DOMParser), inline style url(), data-background(-image), img[loading=lazy] currentSrc - Navigation gets a total 90s budget, an early bot-wall probe that aborts with a pollution-style error instead of capturing garbage (WALL_RE now shared with the validator gate), and one fresh-context retry scoped to the initial nav on retryable failure classes only 505 tests pass (29 new), typecheck clean. Co-Authored-By: Claude Fable 5 --- compiler/src/capture/capture.ts | 291 ++++++++++++++++++++++----- compiler/src/util/captureFailure.ts | 73 +++++++ compiler/src/util/envShim.ts | 103 ++++++++++ compiler/src/validate/gates.ts | 4 +- compiler/test/captureFailure.test.ts | 117 +++++++++++ compiler/test/envShim.test.ts | 162 +++++++++++++++ compiler/test/lazySweep.test.ts | 85 ++++++++ 7 files changed, 781 insertions(+), 54 deletions(-) create mode 100644 compiler/src/util/captureFailure.ts create mode 100644 compiler/src/util/envShim.ts create mode 100644 compiler/test/captureFailure.test.ts create mode 100644 compiler/test/envShim.test.ts create mode 100644 compiler/test/lazySweep.test.ts diff --git a/compiler/src/capture/capture.ts b/compiler/src/capture/capture.ts index 010a2aa..e6f45a8 100644 --- a/compiler/src/capture/capture.ts +++ b/compiler/src/capture/capture.ts @@ -15,6 +15,8 @@ import { discoverBreakpoints } from "./breakpoints.js"; import { writeJSON, writeJSONCompact, writeBytes, ensureDir } from "../util/fsx.js"; import { sha1_12, round } from "../util/canonical.js"; import { isZipArchive, extractDotLottieJson } from "./dotlottie.js"; +import { buildDeterministicEnvShim, captureEpochMs, DEFAULT_PRNG_SEED } from "../util/envShim.js"; +import { isBotWall, classifyNavFailure } from "../util/captureFailure.js"; export const REQUIRED_VIEWPORTS = [375, 768, 1280, 1920] as const; // The dense width set captured for SIZE INFERENCE: a node sampled at 9 widths reveals its sizing @@ -65,6 +67,10 @@ export type SeoResource = { export type CaptureResult = { sourceUrl: string; capturedAt: string; + // Deterministic-env shim parameters actually used for this run (Item 1). Recorded + // so a recapture can reuse the exact {seed, epochMs} — the pinned wall clock is a + // run-metadata value, not a hardcoded constant. Absent when the shim was disabled. + deterministicEnv?: { seed: number; epochMs: number }; viewports: number[]; // Browser-as-oracle: the widths where the SOURCE layout actually restructures (display / // flex-direction / wrap / grid-track-count / position / visibility flips), found by sweeping the @@ -797,6 +803,66 @@ async function captureCanvasStills(page: import("playwright").Page): Promise fallback markup (the walker skips