Nishi Browser — 2026-07-28: the stale-binary find, hidden-ink fix, and a census record

Windows daily driver (nishi.exe) vs the Chrome and Edge oracles, measured by the standing top-20 census (OCR reading-recall, permille vs Chrome=1000). Everything below is measured, gated, and reproducible; images are the actual renders.

30007-23 baseline
271–29607-27 (stale GUI)
34807-28 honest build
350+ rail fix
384+ wiki viewport
wiki 888+ tree keystone
414+ height/font resolvers (11:50) — RECORD

0-final · UPDATE 12:05 — mean 414‰, google 0→387, and author CSS renders like a real page

Two resolver keystones closed the day. (1) Percentage heights resolve to auto against indefinite parents (CSS 2.1 §10.5) — html,body{height:100%} had been resolving against the viewport WIDTH, manufacturing ~1,050px phantom containers: the CSS-on first-screen void, and google's blank first screen (its CSS is inline, so this bit even with CSS off). Google went 0 → 387‰ CONTENT-OK — the synthesized "Google Search / I'm Feeling Lucky" button labels now sit in the first viewport. (2) One shared font-size value resolver for measure and paint: px/%/em/rem/fractions, with calc() and keywords dropped like CSS drops unevaluable declarations. The kill: font-size:0.875rem had digit-scanned to ZERO — wikipedia sizes everything in rem, so styled runs measured at width 0 (the 1-char columns) and the vector-measure page collapsed to 37% height. After: 94–101% of Chrome's height.

wikipedia under its REAL 218KB stylesheet — typography scale, inline links, bordered banners (was: a 20px sliver this morning)

One more universal defect fell out of the same x-ray: the absolute CSS units were unhandled. font-size:10pt resolved to 10px instead of 13.3px — and news.ycombinator.com sizes its entire page in pt, so with author CSS on every run dropped under the OCR legibility cliff (its measured 438→0). Added pt/pc/in/cm/mm per CSS Values §5 (1in = 96px = 72pt = 6pc = 2.54cm), with the existing 13.5px→13 truncation contract preserved and verified by a 6-row unit ladder. With sizes correct, hackernews' remaining gap is now cleanly isolated as table column-width layout — its cells scatter while the page height proves the content is there. Named, filed, and probe-ready rather than guessed at.

Census pair verdict (the standing gate): OFF 414‰ vs ON ~242 on shared rows — CSS stays off for now; the styled-collapse blockers are named exactly (x 878→151, linkedin 843→159, hackernews 438→0) plus the OCR ruler's sub-14px cliff under-crediting styled text. Day arc: 300 → 414‰ (+38%), every step through probes, 20-tooth gates, and the 7-gate sweep. New standing tools: the layout x-ray (@region/@textsweep/@decls), the census-pair decision instrument, and the bitmap/vector A/B flag.

0 · UPDATE 09:35 — the raw-text double-pop keystone: wikipedia reaches READ-PARITY (888‰)

The deepest find of the day: the tokenizer's raw-text consumer leaves the cursor AT the close tag ("the next token IS the END_TAG") — but the tree builder ALSO popped eagerly after consuming, so the arriving END_TAG popped an ANCESTOR. Every <script>/<style>/<title> amputated one tree level on every page: body hung off the root, a script inside body re-parented all following content (probe: x=44→0), and script-bearing containers lost their spines — which WAS the "flattening" rock AND the catastrophic CSS sliver. The element extractor had the mirror bug: it tokenized script BODIES, so tag-like text in JS strings minted phantom elements that skewed every later element's identity. Both walkers fixed; probes + 20-tooth gate + 7-gate sweep GREEN.

Chrome oracle — wikipedia first viewport
Nishi daily driver after the keystone — 888‰ reading-recall, height ratio 96% (Chrome's own OCR ceiling is ~959)

Also from the same fix: netflix height 386%→152% (now CONTENT-OK), ebay 18.7k→8.9k px, shared-row census mean 344→365‰. Plus <input value=...> labels are now synthesized as text boxes — "Google Search" / "I'm Feeling Lucky" render as real buttons' text (google's remaining gap: its form sits ~3,300px down in source-order flow until CSS centering lands). Board: seq1132 + seq1137 EATEN; residual CSS-on defects filed precisely as seq1150.

1 · The find: every GUI build since July 16 was silently stale

build_nishiexe.sh wrote /tmp/nxwin.s while the PE wrapper nx_pe_compile_win_gui reads _offc/nishi_gui.s — so every rebuild re-wrapped 12-day-old assembly. Timestamp fresh, code old. The whole "CSS makes it worse" era and the 6,598-vs-18,500px GUI/shot paradox (seq1110) were this one build-lane bug. Proof: identical bytes through the fixed lane — GUI page_h 19,263 → 6,615 (Chrome ~7,000), box count exactly matching the reference renderer (2077). The GUI now writes an instrument line (boxes/vw/plen/bytesum) into its shot metadata so a stale binary can never hide again.

LAW: a rebuilt binary is unproven until the binary exhibits the new behavior — verify code, not timestamps. An instrument inside the artifact beats any build-log green.

2 · The "blob rail": hidden content was leaking ink

The first honest build exposed black "blobs" down the left edge of real pages. Zoomed 4x, the blobs are readable: Do/na/te … cc/ou/nt — wikipedia's hidden header links. Text under a display:none element was never laid out (kept x=0,y=0,w=0,h=0) but the painter drew it anyway, char-wrapped at zero width, every hidden run overprinting at the origin.

BEFORE — wikipedia left gutter, 4x zoom: hidden links overprinting
BEFORE — stackoverflow: hidden topbar item overprints the skip-link

Fix (3 guards at the shared core): the paint passes skip never-laid text boxes (h==0), the image blit skips never-laid boxes, and the inline flow now applies display:none like the block path — hidden inline spans finally hide. Regression-proofed: the bg gate grew 17 → 20 teeth (visible-control, hidden-block, hidden-inline); the 7-gate sweep stayed GREEN.

3 · Wikipedia first viewport: 61 → 444‰ (beats the July-16 peak 425)

With the rail gone, wikipedia's first screen was still TOC-first (article below the fold). The UA sheet now hides the .vector-toc* chrome (same policy as the existing wiki-nav hides) — the first screen is now the title, lead and hatnote, like Chrome's. Height ratio 99% of the Chrome oracle.

BEFORE — rail fixed but TOC-first, article below the fold (61‰)
AFTER — title + lead in frame 0 (444‰, CONTENT-OK, ratio 99%)

Found on the way: the box tree flattens deep nesting (descendants become siblings), so hiding only the TOC container could not hide its items — filed as seq1137, the next structural rock.

4 · The CSS on/off decision — decided by the census pair, not one site

Through honest binaries, author CSS wins on stackoverflow (232 vs 170‰, page_h 6,615 vs Chrome ~7,000; 281‰ vs the Edge oracle) — but the full census pair says OFF: mean 348‰ CSS-off vs 148‰ CSS-on. Author CSS currently collapses x (878→0), duckduckgo (833→0) and wikipedia into unreadable slivers. CSS_ENABLED stays 0; the sliver (seq1132) is the named gate to flipping it.

CSS-on WIN — stackoverflow renders light + readable at Chrome-like height
CSS-on LOSS — wikipedia: all content in a ~20px sliver (the seq1132 rock)
LAW: a single-site A/B cannot graduate a global flag — the census pair is the gate. The single site said ON; the pair said OFF by 200‰.

4b · Table layout — and the instrument that stopped a false verdict

Rows were flex containers, so every table cell got an equal share of the width regardless of content — a table-built site like hackernews scattered its columns. Implemented the CSS 2.1 auto table algorithm: column width = max-content across all rows, shared down the column, with nested tables saving and restoring their own column context (hackernews nests them). Tables are recognised through a table{display:table} UA rule, the same trick already used for flex and grid, since the box tree carries no tag names. Result on table-built sites: hackernews 438 → 471‰, ebay 178 → 229, yahoo 125 → 163.

The aggregate first read as a regression (414 → 396) because google scored 161. It was not a regression: the same binary renders both the saved page and a fresh fetch at 714px with the button correctly placed — google simply serves a different homepage variant per request. Excluding it, the census is flat (415 vs 416). That near-miss produced the fix: a deterministic saved-page A/B harness, so a layout change is judged on identical bytes and the live census measures the network-facing product separately. Live-page variance had already contaminated one earlier read; it will not contaminate a third.

LAW: judge a layout change on IDENTICAL BYTES. A live corpus measures the product; it cannot referee a diff.

4c · Colspan — probe-perfect, and an honestly open residual

colspan now works end to end: the tree builder stashes the span on the cell box (clamped against hostile values), column resolution spreads a spanning cell's content width ACROSS its span, and the row path gives it the sum of its columns. The hackernews-shaped control probe is pixel-correct — rank / vote / title columns aligned across rows, the colspan=2 subtext starting at the vote column directly under its story, exactly Chrome's arrangement. The deterministic A/B confirms zero blast radius: every corpus page byte-identical except hackernews itself.

The real hackernews page still misplaces its subtext — and three x-ray commands localized why: on the live page the inner table box is 19px tall and the story rows attach to the containing cell as its siblings, outside the table, so they consume the outer table's columns. Two minimal reproducers (bare nested tables; nested tables with HN's exact attribute shapes) both refused to fail — the nesting break needs the real page's full context. Next step is a mechanical prefix-bisect of the saved 42KB page; the finding stays filed as open (seq1159) because the acceptance number is not met. The board reflects reality, not effort.

4d · Since then: two more keystones, a sixth record, and three-browser parity

HTML5-lite end-tag matching — the sibling of the raw-text double-pop. Inside hackernews' vote cell, <center><a><div> made the block-resync pop the open anchor, then its </a> popped <center>, </center> popped the cell, and every element after it escaped the table. End tags now match the nearest open element by name (pop through on a deeper match, ignore when the element was already resync-popped). Effect: hackernews 471 → 695‰ at 92% of Chrome's height, wikipedia CSS-on to 99% height, and the sixth census record of the day: 432‰ (the arc: 300 → 348 → 350 → 384 → 414 → 432).

The styled-page UA correction. A theory that Chrome indents wikipedia died on one pixel probe — Chrome's first ink is at x=24; its sidebar grid needs a 1120px viewport. The offender was ours: our UA sheet's 44px body padding (a readability choice for unstyled pages) survived under author CSS, pushing every styled page right of Chrome. Now a Chrome-parity body{padding:8px} is injected between our UA sheet and the page's own CSS. Structural matching on styled wikipedia went 807 → 846‰ deep-page and 538 → 692‰ on the first screen. Landed alongside: max-width, auto-margin centering, the grid-template shorthand, and rem/fraction grid tracks.

JavaScript, phase 1 of a frontier-driven plan: generators (function*, yield, yield*) and object getters/setters now parse, with execution honestly stubbed where full semantics are a separate rung. Netflix's parse frontier nearly doubled — 860,389 → 1,631,853 bytes of its 4.1MB bundle; conformance held at 92/92 and the 7-gate sweep stayed green throughout. The next construct is already named by the same instrument: object spread.

Three-browser parity is live. One command now captures Chrome and Waterfox and grades both: wikipedia at 96% of oracle height, 896‰ against Chrome and 897‰ against Waterfox — two independent engine families agreeing on our render to within one permille. (A first run scored a meaningless 70‰ because Waterfox ignored a lone window-size flag and shot at 1366px; verifying capture dimensions caught it. An oracle at a different viewport is not an oracle.)

4e · The styled pages, in pixels

Author CSS on, rendered by the Nishi engine. These are the sites that collapsed into unreadable slivers a day earlier.

x.com — after flex-basis:auto (hero centred; login card still slivered)
x.com — after flex-shrink: readable wrapped buttons in a centred card

LinkedIn's styled first screen across three consecutive fixes — 229 → 583 → 688 → 750‰:

1. before — hero as a 1-char column, giant black rectangle (229‰)
2. flex-direction:column implemented (583‰)
3. y-sentinel clamped + low-alpha fixed — header, hero, buttons, agreement text all placed (750‰)
hackernews before end-tag matching — metadata stranded mid-page
hackernews after — rows in flow, 92% of Chrome's height, 695‰
wikipedia under its real 218KB stylesheet (typography scale, inline links, banners)
the third oracle: Waterfox headless at matched 1024px — our render scores 897‰ against it, 896‰ against Chrome

5 · Census scoreboard (2026-07-28T02:10, record run)

siteclassratio%recall ‰note
duckduckgoCONTENT-OK10904site RECORD
xSPARSE-NISHI6878record band
exampleCONTENT-OK12842
linkedinSPARSE-NISHI79833was rail-corrupted: +71 from fix
wikipediaCONTENT-OK9944461 before this session
hackernewsCONTENT-OK135444
bbcSPARSE-NISHI113292
githubCANVAS-OFF93276
stackoverflowSPARSE-NISHI112167233 with CSS on
ebaySTRIP-COLLAPSE5296120height blowup rock
yahooCONTENT-OK41142
netflixCANVAS-OFF38630SPA + height rock
googleBLANK-NISHI690renders 5506px, OCRs 0: invisible-ink class
facebookSTRIP-COLLAPSE30SPA shell

Mean 384‰ over 14 measured rows; FETCH-EMPTY: youtube, reddit, instagram, craigslist; CHROME-BLOCKED (no oracle): amazon, bing. Sweep 7/7 GREEN after every change.

6 · Board state + next rocks

Eaten today: seq1110 (stale-lane paradox), seq1130 (hidden ink), seq1131 (wiki viewport). Filed: seq1129 (15 PE wrappers still read /tmp — the same stale trap armed), seq1132 (CSS-on sliver — the gate to author CSS), seq1137 (box-tree flattening breaks hide-subtree + hit-test). Next by evidence: google invisible-ink 0‰ · CSS-off height inflation (netflix/ebay/stackoverflow) · seq1132 · seq1137 · the 4 FETCH-EMPTY sites.

evidence id: census-record-384 · generated 2026-07-28 · instruments: nx_top20_parity + nx_visual_diff + Windows.Media.Ocr · gates: browser_regress_all 7/7, bg gate 20/20