Rendered reality
What to do when a screenshot shows a break the gates missed — the reproduction procedure, the serving traps that fake hydration errors, and the mount and anatomy detectors.
Someone shows you a screenshot of a page that is plainly broken. You open the same URL and it is fine. Every gate is green. This file is the procedure for that moment — written from a live incident (2026-09-23, the combobox playground) where the procedure worked, including the parts where the investigator's first readings were wrong.
The premise: the corpus makes builders write correct responsive code. It cannot police rendered reality. Three failure classes live entirely outside the rules, and each has a different detector:
| Class | Detector |
|---|---|
| Arrangement that passes every gate | anatomy assertions (qa:mounted seeds) + a person |
| A state that exists on one machine only | this procedure |
| Client-only mount windows / chunk failures | qa:mounted + the preview pipeline's own error handling |
1. Believe the screenshot, then classify
The screenshot is data. It shows a state that existed. Your job is to find which kind of state: a settled layout you can reproduce, or a transient / machine-local one you cannot. Do not argue with the reporter about what they saw; find out when what they saw can exist.
2. The settled-state sweep
Measure the real page, by geometry, across the axes a user's machine can vary.
Every probe is getBoundingClientRect + computed style — never eyeballing.
- Widths: 320 · 430 · 766 · 881 · 1024 · 1400 · 1512 (or bisect around the
reporter's). Remember the pane scales: assert
clientWidthequals the width you asked for before trusting any number from it — a "23px overflow at 768" in the incident was an artifact of measuring at 753. - Root font size: 16 / 20 / 24px via
document.documentElement.style.fontSize— simulates the browser's default font setting, the axis our px breakpoints ignore (01). A rem-built component should scale its boxes; the incident component grew 288 → 360 → 432 cleanly, which cleared this hypothesis. - Font stack: swap
fontFamilytosystem-ui,Arial,Segoe UI, and measure clipping — a webfont that failed on the reporter's machine renders wider and clips where yours fits.
Two self-traps from the incident, so they are not rediscovered:
- A "same row" check with a ±26px tolerance called a 20px-stacked label "beside" its control. Pick tolerances from the measured healthy layout, not from air.
input.scrollWidth === clientWidthlooked like "fits with zero slack — fragile!". It was nothing of the kind: the input isflex-grow: 1, so the two are equal by construction at any font. Know what the equality means before reading it as a signal.
3. The client-only window
curl the URL and grep the raw HTML for the content in the screenshot.
If it is absent from the server payload, the element mounts client-side and everything between first paint and settled hydration is a state a screenshot can catch — and, with an error, a state that can persist. In the incident, "Select a fruit" appeared nowhere in 538KB of SSR HTML.
Then check the error path in the pipeline that mounts it:
- Is there a
.catchon the dynamic import? An error boundary above it? A rejectedReact.lazystays rejected in any module-level cache — the page is then broken until a hard reload, which is exactly the signature "it looked broken for a while / reload fixed it". - Deploy skew: chunk hashes rotate every deploy. A tab opened before a deploy 404s its old chunk names. Check the deploy log for that day.
The one-question discriminator to send the reporter: does a hard reload fix it? Heals → stale-chunk / mid-mount class, mechanism above. Survives → it is a settled state; go back to §2 and bisect harder.
4. Serving traps that fake the whole investigation
The export writes both route.html and a route/ directory of RSC
payloads. A generic static server that resolves the directory first — or a
probe that appends a trailing slash — hydrates the wrong payload and throws
React #418 on every route. In the incident this manufactured 110 phantom
hydration failures until the canonical scripts/serve-export.ts was used.
Measure the export only through it.
And read suite results from a JSON reporter file, never from piped stdout:
the incident's first run printed "49 passed" through the shell filter while the
true count was 74 failing of 118 (reference_rtk_output_filtering).
5. The detectors we now own
qa:mounted (docs repo) loads every route of the export and asserts, per
page: zero page errors, zero failed chunk requests, and every
[data-preview-frame] contains at least one element with a real layout box —
the geometric mount gate the QA harness got in docs#454 and the site itself
never had. It waits for the geometry it asserts, not a proxy: its own first
draft waited on scrollWidth stability and failed 73 routes, because an empty
frame is perfectly stable. The suite carries a MUTATE= hook and is only
trusted because each detector was forced red: empty → 110, pageerror → 118,
anatomy → exactly the seeded 1, clean → 0.
Anatomy seeds (in the same suite) are the first positional assertions we
own — qa:styles records w/h but no x/y (08). Each seed names two slots
on one route and asserts left-edge alignment, vertical gap range, and a width
floor. An entry is added by measuring the healthy layout first — the
combobox seed's numbers (left delta ≤ 24, gap 0–16, width ≥ 200) are its
measured healthy values with margin, not invented thresholds. One seed per
incident: every layout that reaches this file's §1 earns its assertion on the
way out.
What none of this covers, so nobody over-reads a green run: a preview stuck on its Suspense fallback occupies a box and passes; deploy-skew itself is testable only in the pipeline's own retry tests; and arrangement on the ~100 unseeded routes is still guarded by exactly one thing — a person looking. That detector fired first in the incident too.
6. If you cannot reproduce it
Say so, with the matrix of what you ruled out — that is a result, not a failure. Ask for two facts only: browser + zoom, and the hard-reload test. Do not name a mechanism you have not measured; the incident's investigator wrongly proposed two before landing on the one the evidence supported, and both wrong turns are recorded above so they cost nothing next time.