Skip to content

feat(design): a passive layout audit with an inbox the person triages - #154

Merged
filipeforattini merged 1 commit into
mainfrom
feat/design-layout-audit
Sep 6, 2026
Merged

feat(design): a passive layout audit with an inbox the person triages#154
filipeforattini merged 1 commit into
mainfrom
feat/design-layout-audit

Conversation

@filipeforattini

@filipeforattini filipeforattini commented Sep 6, 2026

Copy link
Copy Markdown

Tranche B of the lavish-axi parity plan: the passive layout audit.

Inside the prototype (client/audit.ts, bundled beside the helpers): after fonts.ready, a ResizeObserver settle (180 ms / 2 s), finite animations (≤ 4 s) and two rAF, the page is sampled twice 120 ms apart and once more after DOM quiescence; only findings present in both samples survive. Six rules — page-horizontal-overflow, clipped-text, clipped-control, viewport-unreachable-control, viewport-unreachable-content, overlapping-text — with lavish's thresholds and suppressions (diagrams/SVG, visually-hidden text, ellipsis/line-clamp, real scrollers, elements in motion, positioned decoration, data-redcode-ui). The pure classifiers live in helpers.ts and are unit-tested. A pass carries its own completeness.

Server (layout-warnings.ts, a port of lavish's lifecycle with its 27 tests): fingerprint sha256(rule|target|viewport)[:16] without magnitude; statuses open|queued|recurring|unverified|reopened|resolved|dismissed|obsolete; a warning clears only on a complete pass of a newer revision, a failed pass marks it unverified, another viewport class never touches it, dismissal lasts one revision, ≤ 200 stored, ≤ 50 per note, history ≤ 20. Warnings persist in the review sidecar.

Load epochs: the shell names every frame load (POST /design/:id/loads/begin, per shell, out-of-order detected) and the token rides on the frame URL; index.html?load= refuses a replaced load with 409, &probe=1 answers whether the document can be served. A pass is accepted only under a current token, matching revision and increasing sequence.

Routes: POST /layout-diagnostics (never wakes the agent), GET /layout-warnings, POST /layout-warnings/queue (prepares the note; 409 conflict when the revision moved; committed to queued when the note is delivered through /feedback), POST /layout-warnings/dismiss, POST /artifact-failures (artifact-unavailable / artifact-asset-unavailable, deduped per load — the one report that wakes the agent, as <artifact-failures>). The event stream sends layout-warnings on open and on change.

Shell: "Layout issues" badge and drawer (select all, per-row Reveal/Dismiss, "Queue selected fixes" → one layout-warnings note with lavish's exact prompt payload; selection persisted per tab; rows already queued to send are shown as such), a curtain until the first pass with "Show anyway" and a 12 s cap (experimental.design.gate, gate_timeout ≤ 60 s, ?gate=0 per tab), an 8 s silence probe and a 15 s boot failsafe card whose Retry asks the server first. The reload debounce widens to 900 ms while a batch of fixes is outstanding. Also fixes a latent ReferenceError in the shell's end-review path.

Config: experimental.design.viewports (a class left out has its warnings marked obsolete, never resolved), gate, gate_timeout.

Agent side: design_preview names open, unqueued issues as a note; the mode prompt explains the inbox, the layout issues: N queued for repair target, and <artifact-failures>.

Tests: layout-warnings.test.ts (27, ported), classifiers and bundle in sdk.test.ts, five route scenarios (pass never prompts, replay/forged stale, queue conflict + commit on delivery, dismiss for one revision, failures prompt once and are stale under an old load, SSE carries the inbox), a registry load test, shell markup/handshake/script-parse tests, sidecar round trip. 219 design tests pass.

https://claude.ai/code/session_013JrKXL4pdgTu2EtCjgiYyq


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

The prototype audits its own layout once fonts, geometry and finite animations settle — clipped text and controls, controls and text outside the viewport, a page that scrolls sideways, text covered by an opaque sibling — keeps only what two samples agree on, and reports each pass with its own completeness. Passes land in a "Layout issues" inbox on the review page (badge, drawer, select, queue, dismiss, reveal); nothing reaches the agent until the person queues it, and then it is one ordinary note. A warning clears only on a complete pass of a newer revision that no longer finds it; a failed pass, another viewport or a reload in flight never clears anything, and a dismissal lasts one revision. Every frame load is named by a token so a replaced frame's pass is discarded, the page holds the prototype behind a short curtain until its first pass, probes the server when the frame stays silent, and the one unasked report is a prototype that cannot be shown at all.

Ported from lavish-axi's layout-warnings lifecycle and artifact audit, with the same thresholds and timings.

Claude-Session: https://claude.ai/code/session_013JrKXL4pdgTu2EtCjgiYyq
@filipeforattini
filipeforattini merged commit 6e2e844 into main Sep 6, 2026
12 checks passed
@filipeforattini
filipeforattini deleted the feat/design-layout-audit branch September 6, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant