chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* check-overflow.cjs — mode-agnostic frame-overflow WARNING for custom mode.
|
||||
*
|
||||
* Template mode has check-occlusion.cjs (which also flags frame-edge overflow),
|
||||
* but custom mode runs no gates. This is the cheap safety net: it loads the
|
||||
* rendered index.html, seeks the GSAP timeline across the clip, and flags ANY
|
||||
* visible text element (regardless of class) whose box leaves the canvas — i.e.
|
||||
* captions that fall off-frame (the bug we otherwise only catch by eye).
|
||||
*
|
||||
* WARNING ONLY — never fails the build (custom designs may bleed intentionally).
|
||||
* Exit 0 if it ran (with or without findings); exit 3 if it couldn't run.
|
||||
*
|
||||
* Usage: node check-overflow.cjs <project-dir>
|
||||
*/
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
|
||||
const HF_ROOTS = [
|
||||
process.env.HYPERFRAMES_ROOT,
|
||||
path.resolve(__dirname, "../../.."),
|
||||
path.join(os.homedir(), "Downloads", "hyperframes"),
|
||||
].filter(Boolean);
|
||||
let puppeteer = null;
|
||||
for (const root of HF_ROOTS) {
|
||||
const cands = [path.join(root, "node_modules", "puppeteer")];
|
||||
const bunDir = path.join(root, "node_modules", ".bun");
|
||||
try {
|
||||
if (fs.existsSync(bunDir)) {
|
||||
for (const d of fs.readdirSync(bunDir))
|
||||
if (d.startsWith("puppeteer@"))
|
||||
cands.push(path.join(bunDir, d, "node_modules", "puppeteer"));
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
for (const p of cands) {
|
||||
try {
|
||||
if (fs.existsSync(p)) {
|
||||
puppeteer = require(p);
|
||||
break;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
if (puppeteer) break;
|
||||
}
|
||||
if (!puppeteer) {
|
||||
console.error("[overflow] puppeteer not found");
|
||||
process.exit(3);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const projectDir = process.argv[2];
|
||||
const htmlName = process.argv[3] || "index.html"; // Standard mode passes "rail.html" to gate the rail too
|
||||
const indexPath = path.resolve(projectDir, htmlName);
|
||||
if (!fs.existsSync(indexPath)) {
|
||||
console.error(`[overflow] missing ${indexPath}`);
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const html = fs.readFileSync(indexPath, "utf8");
|
||||
const num = (re, d) => {
|
||||
const m = html.match(re);
|
||||
return m ? parseFloat(m[1]) : d;
|
||||
};
|
||||
const W = num(/data-width="([0-9.]+)"/, 1920);
|
||||
const H = num(/data-height="([0-9.]+)"/, 1080);
|
||||
const DUR = num(/data-duration="([0-9.]+)"/, 8);
|
||||
|
||||
const exe =
|
||||
process.platform === "darwin"
|
||||
? "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||||
: "/usr/bin/google-chrome";
|
||||
const browser = await puppeteer.launch({
|
||||
headless: "new",
|
||||
executablePath: fs.existsSync(exe) ? exe : undefined,
|
||||
args: [
|
||||
"--disable-web-security",
|
||||
"--allow-file-access-from-files",
|
||||
`--window-size=${W},${H}`,
|
||||
"--disable-dev-shm-usage",
|
||||
],
|
||||
});
|
||||
try {
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: Math.round(W), height: Math.round(H), deviceScaleFactor: 1 });
|
||||
const waitTL = async () => {
|
||||
const t0 = Date.now();
|
||||
while (Date.now() - t0 < 12000) {
|
||||
if (await page.evaluate(() => !!(window.__timelines && window.__timelines.main)))
|
||||
return true;
|
||||
await new Promise((r) => setTimeout(r, 200));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
await page.goto(`file://${indexPath}`, { waitUntil: "load", timeout: 20000 });
|
||||
let hasTL = await waitTL();
|
||||
if (!hasTL) {
|
||||
// GSAP loads from CDN — a blip leaves no timeline; retry once
|
||||
await page.reload({ waitUntil: "load", timeout: 20000 }).catch(() => {});
|
||||
hasTL = await waitTL();
|
||||
}
|
||||
if (!hasTL) {
|
||||
// NEVER claim "ok" when we couldn't actually evaluate the animated layout.
|
||||
console.error(
|
||||
"[overflow] ⚠ timeline did not register (GSAP CDN blocked?) — overflow check " +
|
||||
"INCONCLUSIVE; eyeball the render for off-frame captions.",
|
||||
);
|
||||
await browser.close();
|
||||
process.exit(0);
|
||||
}
|
||||
await page.evaluate(async () => {
|
||||
try {
|
||||
await document.fonts.ready;
|
||||
} catch {}
|
||||
});
|
||||
|
||||
const times = Array.from({ length: 9 }, (_, i) => +((DUR * i) / 8).toFixed(2));
|
||||
const found = new Map(); // key text → worst offense
|
||||
|
||||
for (const t of times) {
|
||||
await page.evaluate((t) => {
|
||||
window.__timelines.main.seek(t);
|
||||
void document.body.offsetHeight;
|
||||
}, t);
|
||||
await new Promise((r) => setTimeout(r, 25));
|
||||
const offenders = await page.evaluate(
|
||||
(W, H) => {
|
||||
const M = 2; // tolerance px
|
||||
const root = document.querySelector("#stage") || document.body;
|
||||
const out = [];
|
||||
for (const el of root.querySelectorAll("*")) {
|
||||
if (el.tagName === "VIDEO" || el.tagName === "AUDIO") continue;
|
||||
const own = [...el.childNodes]
|
||||
.filter((n) => n.nodeType === 3)
|
||||
.map((n) => n.textContent.trim())
|
||||
.join(" ")
|
||||
.trim();
|
||||
if (!own) continue;
|
||||
const cs = getComputedStyle(el);
|
||||
if (
|
||||
cs.display === "none" ||
|
||||
cs.visibility === "hidden" ||
|
||||
parseFloat(cs.opacity) < 0.06
|
||||
)
|
||||
continue;
|
||||
const b = el.getBoundingClientRect();
|
||||
if (b.width === 0 || b.height === 0) continue;
|
||||
const off = {
|
||||
left: Math.max(0, Math.round(-b.left - M)),
|
||||
right: Math.max(0, Math.round(b.right - W - M)),
|
||||
top: Math.max(0, Math.round(-b.top - M)),
|
||||
bottom: Math.max(0, Math.round(b.bottom - H - M)),
|
||||
};
|
||||
if (off.left || off.right || off.top || off.bottom)
|
||||
out.push({ text: own.slice(0, 42), off });
|
||||
}
|
||||
return out;
|
||||
},
|
||||
W,
|
||||
H,
|
||||
);
|
||||
for (const o of offenders) {
|
||||
const sides = Object.entries(o.off)
|
||||
.filter(([, v]) => v > 0)
|
||||
.map(([s, v]) => `${s} ${v}px`)
|
||||
.join(", ");
|
||||
const prev = found.get(o.text);
|
||||
const score = Object.values(o.off).reduce((a, b) => a + b, 0);
|
||||
if (!prev || score > prev.score) found.set(o.text, { sides, score, t });
|
||||
}
|
||||
}
|
||||
|
||||
if (found.size === 0) {
|
||||
console.log(`[overflow] ok — no caption text leaves the ${W}x${H} frame`);
|
||||
} else {
|
||||
console.error(
|
||||
`[overflow] ⚠ ${found.size} caption(s) leave the frame (custom mode — WARNING only, not blocking):`,
|
||||
);
|
||||
for (const [text, info] of found)
|
||||
console.error(` "${text}" → off-frame: ${info.sides} (@${info.t}s)`);
|
||||
console.error(
|
||||
`[overflow] if unintentional, reposition/resize; if it's deliberate bleed, ignore.`,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
main().catch((e) => {
|
||||
console.error("[overflow]", e.message);
|
||||
process.exit(3);
|
||||
});
|
||||
Reference in New Issue
Block a user