feat(check): opt-in --layout proseCoverageFloor (#2834)

* feat(check): opt-in --layout proseCoverageFloor for text_occluded

Keep the default prose coverage floor at 0.15 for all callers, and allow
stricter agents (e.g. Zephyr) to lower it via --layout "proseCoverageFloor=0.05"
without changing other layout gates.

Co-authored-by: Cursor <cursoragent@cursor.com>

* style(check): collapse --layout comments and docs to one line

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(check): strict proseCoverageFloor parse + pin 0.07 floor tests

Reject trailing-garbage fractions that Number.parseFloat would accept, and
pin the existing ~0.07 coverage fixture for default vs floor=0.05 (atomic
labels unchanged) plus a collectLayout forwarding assertion.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(check): share parseNumberStrict across layout and frame-check

Sweep the sibling --frame-check tol parser (and caption fractions) onto the
same strict Number() helper so trailing garbage cannot prefix-parse.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Xuanru Li
2026-07-27 16:27:09 -07:00
committed by GitHub
co-authored by Cursor
parent 37295b341f
commit 209e6e0148
7 changed files with 177 additions and 23 deletions
+11 -3
View File
@@ -42,6 +42,7 @@ import type {
ContrastAuditEntry,
ContrastCapture,
GeometryCandidateRequest,
LayoutOptions,
MotionSpecResolution,
OffPivotFrame,
OffPivotRotationSample,
@@ -353,7 +354,7 @@ function createPageDriver(page: Page, setTime: (time: number) => void): CheckAud
setTime(time);
await seekCompositionTimeline(page, time, DENSE_GEOMETRY_SEEK_OPTIONS);
},
collectLayout: (time, tolerance) => collectLayout(page, time, tolerance),
collectLayout: (time, tolerance, layout) => collectLayout(page, time, tolerance, layout),
collectOverlap: (time) => collectOverlap(page, time),
collectLayoutGeometry: () => collectLayoutGeometry(page),
collectRotationSample: (time) => collectRotationSample(page, time),
@@ -457,15 +458,22 @@ async function collectLayout(
page: Page,
time: number,
tolerance: number,
layout?: LayoutOptions,
): Promise<AnchoredLayoutIssue[]> {
const raw = await page.evaluate(
(options: { time: number; tolerance: number }) => {
(options: { time: number; tolerance: number; proseCoverageFloor?: number }) => {
const audit = Reflect.get(window, "__hyperframesLayoutAudit");
if (typeof audit !== "function") return [];
const result = Reflect.apply(audit, window, [options]);
return Array.isArray(result) ? result : [];
},
{ time, tolerance },
{
time,
tolerance,
...(typeof layout?.proseCoverageFloor === "number"
? { proseCoverageFloor: layout.proseCoverageFloor }
: {}),
},
);
return anchorLayoutIssues(page, raw.flatMap(parseLayoutIssue));
}