Verify 03: mind and standard group (clean room)

Date: 2026-10-13 · Scope: prototype/mind.html, prototype/standard.html, prototype/server.py, prototype/data/ets.sample.json · Inputs: the round-2 verdict (verify-02-mind-standard.md, its partial rows and section 5 as the work list), the two structured claim sets (mind-standard fixer, still-swap agent), the design direction and the brief. No fix-*.md or critique-*.md file was opened and no r3-* capture was used; every verdict below comes from fresh pixels, fresh measurements or the code.

Score for the group as shipped now: 92 / 100 (round 2: 86). All seven round-2 work-list items landed. Five are fully fixed. Two are fixed at the widths the fixer tested but still fail elsewhere: Register sits under the open dock at 821 to 1040 px, and a fresh phone deep link still shows two rules. The baked still is a clear win: in both routes it now reads as the matte display-mannequin cranium the owner asked for, with no rectangle edge and no halo. Three new minor findings remain: the 24 px head glyph still draws the round-2 capsule with a brow bar (a helmet read), the hero sample note runs across the head's eyes at tablet widths, and the dock-open nav overflow above. I found no regressions.


1. Method

Item Result
Port 8777 at start Free (no orphan to stop)
Server Started by the verifier: uv run --script server.py --pid-file <scratch>/v3-mind/server.pid (uv 1565, python 1568), listening 05:05:31
--selftest scanner fuzz 400/400 ok · sanitizer ok (3 dropped ids, 3 dropped components; component cap counts 2) · history echo ok · budget ok · history trust ok · public hosts ok (new) · digest 38,488 chars · exit 0
HTTP guard sample (raw sockets, no model calls) 6 / 6 pass (section 7)
--public-host and interface address Read from the code and exercised with a stub socket against the real Handler._hosts, _host_ok and public_hosts (no bind, no network)
Live exchanges 3 of 4: mind 1440, mind 390, dock merge 1440. All outcome=ok, request ids logged, zero dropped ids or components. The spare was not used
Everything else ?demo=1 or Playwright route mocks of /api/mind. A context-level route aborted and counted any unmocked /api/mind call; the leak counter stayed 0 in every context, and guard contexts made 0 /api/mind requests
Browser Chrome for Testing via Playwright 1.64.0-alpha, headless only; WebGL2 present (the opening realm reports webgl, settled, 120 fps). 1440x900 at DPR 2; 390x844 at DPR 3 with isMobile and hasTouch (pointer: coarse matched). Sweeps at 360x740, 430x932, 768x1024, 820x1180, 1024x768, 1280x800, 1920x1080, and dock-open widths 1300 down to 760
Head analysis Frozen pairs (all animations off; the still visible vs visibility:hidden), diffed per pixel with the still's alpha resampled onto the img box; contrast-stretched crops (levels 200..255 to 0..255) saved as *-stretch-*
Pixels 43 new captures (v3-mind-*, v3-standard-*), each read as pixels before it is cited
Static server python3 -I -m http.server 8793 (PID 28862) for one width sweep after server.py had stopped; stopped by that PID, 0 404s
Process note One early read-only inspection of the fixture ran as python3 -I -c (stdlib json, no writes) before all other Python went through uv run --script; that is a deviation from the uv-only rule, recorded here. Scratch v3-mind was removed at the end; earlier rounds' shots and reports were not touched
Shutdown SIGTERM to python 1568 at 05:25:00; python and uv gone; lsof shows 8777 and 8793 free; the pid file was removed by the server's finally; no stray Chrome or node processes

2. Owner decisions

# Decision Status Evidence
1 Fork copy (§3.2) Fixed (round-2 nit) The mind's door card explainer is Everything laid out: agenda, lineup, venue, tickets., byte-equal to the fork's .door__explainer read from index.html in the same run (equal: true); aria-label is the §3.2 link name (v3-mind-mock-unavailable-1440x900)
2 Real dates, decided lockup string Fixed p.when.tag.tag--caps: innerText // MAY 3-6, 2027 // AUSTIN, TX, textContent // May 3-6, 2027 // Austin, TX, text-transform: uppercase, Geist Mono, at 1440, 390, 360 and 768; the static markup carries the same string (v3-standard-nojs-1440x900)
3 Single accent Held (not re-scanned) No claim touched colour. Spot checks: composer focus hairline, Ask the mind →, reveal outline and busy dot are raspberry
4 Persona voice Held Live replies: "Here is the Day 2 program, from a sample lineup: ETS26 people standing in until ETS27's speakers are announced."; "Two ticket types, each cheaper if you buy before the early phase ends on November 19, 2026. Prices include fees, and tickets are non-refundable."; sentence case, no exclamation marks
5 Mannequin cranium, nose bridge up Fixed for the head; glyph open (N2) Both routes now show the baked still. At 1440 and 390 it reads as a smooth, matte display-mannequin cranium: domed crown, gently convex sides that taper below the sockets, soft light hollows (darkest composite pixel 173.4 of 255, no dark sockets), a faint bridge dissolving into the fog. No teeth or drips, no parallel-sided capsule, no brow band, no goggles. The 24 px glyph still draws the round-2 capsule (N2)
6 No head disc through content Held #head computes to opacity 0 after the first answer at 1440 and 390 (demo and live); the 24 px glyph shows in the top bar (v3-mind-demo-grid-1440x900, v3-mind-live-after1-*)
7 Escape link on every component Held [ open the map: lineup ] → #lineup, [ open the map: agenda ] → #panel-d2, partners, tickets → #register, venue (demo sweep and both live mind turns)

3. Round-2 work list (partial rows and section 5)

Round-2 item Status Evidence
Dock merges not reconciled with the final answer or cleared on error (claim 13) Fixed A MutationObserver on the page recorded, for a provisional 3-speaker grid then a final 1-speaker grid: bar showing 3 speakers · sample added (74 hidden), removed, then bar showing 1 speaker · sample added (76 hidden); the end state is 1 of 77 visible, one bar, one filtered on the page note, and status "One speaker fits that. Showing 1 speaker, sample data, 2 follow-up suggestions." (v3-standard-mock-reconcile-1440x900). For invalid and truncated after a merge, the bar was added (74 hidden) and then removed; the end state is 77 visible, no bar, no note, "Something came back garbled. Try again." and retry chips (v3-standard-mock-error-after-merge-1440x900). Matching provisional and final answers keep the merge (2 speakers). Live: provisional speaker_grid:12 equals the final, so the bar stands (v3-standard-live-merge-1440x900)
Dock open pushes the hero copy under the head Fixed (821 px and up) With the dock open, .hero-head opacity is 0 at 1440, 1280, 1024, 900 and 821; the description ends at 572 and the numerals at 688, with nothing under them (v3-standard-dock-open-1440x900). At 820 and below the dock overlays the page and the head returns by design
Facts hairline crosses the forehead Fixed Rule from x 48 to 827.5 at y 638.9 (max-width: 58%); the head's visible silhouette starts at x 1004, so the gap is 177 px (v3-standard-top-1440x900). Swept at 768, 820, 1024, 1280 and 1920: the rule never crosses the head
Phone head above the lockup Fixed 390: the slot spans y 57 to 260 and the copy block starts at 137.6, which is 39.9 % of the slot height. The visible head spans y 62.9 to 258.8, so 62 % of it sits behind the copy on the white gradient (v3-standard-top-390x844). 360x740 and 430x932: also 62 % (v3-standard-top-360x740)
Hero date line not the decided lockup Fixed Decision 2
Coarse-pointer // spacing regression Fixed ::before keeps margin-right: 1ch. The gap after the slashes is 7.19 px both on coarse pointers (chips and day tabs display: flex, 44 px tall) and on fine pointers (display: block) (v3-mind-chips-390, v3-standard-agenda-390x844)
Double hairline under the sticky nav Partial Desktop: a #panel-d2 deep link lands the section at 71.5 under the 73 px nav, and the row profile shows one rule (device rows 144-145, #e2e2df) (v3-standard-panel-d2-hairline-1440); a hashchange to #panel-d3 and nav clicks give the same. Phone menu → Agenda: 55.5 under the 57 px nav, one rule (v3-standard-agenda-hairline-390). A fresh phone deep link #panel-d2 lands the section at 107.5: two rules, 51 px apart (v3-standard-deeplink-d2-390x844, N4)
Summary grammar "Showing 1 speakers" Fixed Mind mock: "… Showing 1 speaker, sample data, 1 follow-up suggestion."; kit head 1 speaker · sample lineup; dock as above. A leftover in code only: the dock's sheet speaker_grid kit head is not pluralized (standard.html:605, N10)
"source:" hidden from assistive tech Fixed .src textContent is source: lineup sample · ets26 stand-ins (and four more); ::before is "// " / ""; the accessibility snapshot reads text: "source: lineup sample · ets26 stand-ins"
Door explainer punctuation Fixed Decision 1
--host 0.0.0.0 answers every client with 421 Fixed for direct clients Stub test against the real handler. With a remote bind (TOKEN set) and a connection arriving on 192.168.1.50, Host 192.168.1.50:8777 and Origin http://192.168.1.50:8777 pass, and Host 10.9.9.9:8777 gets 421. A loopback bind does not add the interface (421). --public-host demo.example accepts demo.example:8777. Gap: default-port or https fronts (N5)
Speaker names at uneven heights Fixed .sc { align-content: start }; the spread of name tops per row is at most 0.04 px (lineup, 6 rows at 1440) and 0.02 px (mind grid) (v3-standard-lineup-1440x900, v3-mind-demo-grid-390x844)
Register under the open dock Partial 1440: Register ends at 952 and the dock starts at 1000; 1060 to 1300 is also clear. 1024: 20 px under the dock; 960: 82 px; 900: 139 px (fully hidden); 821: 215 px, with Partners and Venue partly covered too (v3-standard-dock-open-1024x800, N1)

4. Claims

4.1 Mind-standard fixer

# Claim (abridged) Status Evidence
1 Claim 13: dock turns record page-backed trees; reconcile rebuilds merges and notes when the final differs; showError clears merges and drops notes Fixed Section 3, first row (observer trace, two mocks, one live)
2 Phone hero: --head-w, padding-top at 40 % of the head height, lower 60 % behind the eyebrow, mark and theme line Fixed Section 3. The eyebrow crosses at socket level and the mark over the lower head; both stay legible on the gradient (v3-standard-top-390x844)
3 Desktop: facts at 58 % (rule ends 828, head from 864); dock open: head fades, facts full column, nav padded, Register ends 952 at dock 1000 Partial At 1440 every part holds; with the still the head now starts at 1004. The nav padding overflows at 821 to 1040 (N1)
4 Decision 2: p.when.tag.tag--caps, natural-case DOM text rendered uppercase Fixed Decision 2
5 Coarse pointers: // plus margin-right: 1ch in both pages; 44 px chips and tabs read // who's speaking and // mon 3 Fixed 7.19 px gap, 44 px height (v3-mind-chips-390, v3-mind-empty-390x844, v3-standard-agenda-390x844)
6 Hairline: scroll-margin-top: var(--nav-h); applyHash scrolls to top minus the nav; deep link 72 under 73, phone agenda 56 under 57 Partial The stated cases hold (71.5 under 73; 55.5 under 57). A fresh phone deep link does not (N4)
7 Small ones: pluralized summaries, source: in the DOM, colon door explainer, .sc align-content, --public-host plus the interface address, selftest extended Fixed Section 3; selftest public hosts: ok. N5 records the https and default-port gap
8 N5: composerFirst before any await; draft read and removed; #q filled and focused, caret at the end; early keys appended; never sends Fixed End to end from index.html served by server.py, typing who at 40 ms per key: URL /mind.html#compose (no query), #q = who, focused, caret 3/3, 0 turns, draft null, mode live. All of it still holds 2 s later, and typing x gives whox. / gives an empty, focused composer; where plus Enter arrives as where (caret 5) with 0 turns. 0 /api/mind requests, 0 console errors (v3-mind-fork-1440x900, v3-mind-handoff-1440x900)
9 Re-ran round-2 checks: overflow, status texts, dock inert and hidden, phone peek, guard sample, selftest Fixed Overflow at 390 after five demo answers and a live answer: scrollWidth 390, 0 elements outside the viewport. Dock closed: inert, visibility: hidden, 40 Tab presses never entered it. Phone peek after a merge: 56 px bar at y 788 with the caption and a focused [ expand ]; expanding focuses the input (v3-standard-dock-peek-390x844). Selftest in section 1, guard sample in section 7

Skips: the live getsockname path is covered by my stub test of the same code, so the skip is accepted. The fixture was unchanged, as stated. The still landed this round through the still agent. Unused live exchanges are fine. Note confirmed: the cold first turn now logs prefix_measured=19331, which round 2 could not observe.

4.2 Still-swap agent

# Claim (abridged) Status Evidence
1 mind.html #head: one img, head-still.png, srcset @2x 2x, 800x924, alt="", decoding="async", draggable="false"; CSS block, 100 %, auto, margin-bottom: -3.3% Fixed mind.html:268, 54; currentSrc is the @2x file at DPR 2 and 3, naturalWidth 800, complete
2 standard.html .hero-head: the same swap in the unchanged wrapper Fixed standard.html:316, 66
3 Kept: 55 % and 64 % masks, white gradient, breathe, dock-open fade, 820 and 720 rules, the glyph Fixed (the glyph itself is N2) Masks computed at 55 % (desktop) and 64 % (phone); gradient 0 → .78 at 24 % → white at 50 %; breathe running, none under reduced motion; dock-open opacity 0, back to 1 at 820
4 Slots scaled by 0.743 Fixed Layout widths: mind 147 px at 1440 (16.34vmin) and 145 at 390 (37.14vw); standard 374 at 1440 (26 %) and 180 at 390 (0.743 x 241.8)
5 Foot trim: the slot ends where the dissolve ends Fixed The changed-pixel bounding box ends within 1 to 2 px of the slot bottom (mind 1440 and 390); the standard head's dissolve ends at the hero's lower edge
6 Placement: mind head 138.5 px = 38.7 % of the opening head; 35 and 33 px above the h1; standard x 1006 to 1356, 178 px clear; phone copy at 40 % Fixed My numbers: the visible silhouette is 137.4 px at 1440 and 135.6 at 390. The opening head measures 608 / 1.7 = 357.6 px (the head-only render's alpha width divided by its lens zoom), so the ratio is 38.4 % against the design's 38 %. Gaps above the h1: 36.2 and 34.4 px. Standard head 1004 to 1354 (right third from 960), 177 px clear; phone 39.9 %
7 Read as pixels: the matte mannequin cranium of the opening Fixed My own reads: v3-mind-head-1440, v3-mind-head-390, v3-standard-head-1440, v3-standard-top-390x844, v3-mind-fork-1440x900 (the same form as the opening head)
8 Edges: no change outside the slot or along its edges; edge pixels match; darkest pixel 173.4 Fixed Four frozen pairs (mind and standard at 1440 and 390): 0 changed pixels outside the img box; maximum
9 Fades: #head 0 after one answer; .hero-head 0 with the dock open Fixed Sections 2 and 3
10 Console and network clean Fixed Section 6
11 Skip: other viewports not captured ("no new overlap is possible") Not accepted in full The sweep found the sample note crossing the head at 721 to 1000 px (N3). The note sits outside the copy column, so the slot argument does not cover it. I re-checked reduced motion and no-JS: both fine (v3-standard-nojs-1440x900, v3-mind-nojs-1440x900)
12 Note: the Ask pill overlaps the lower right of the desktop dissolve Confirmed v3-standard-top-1440x900; pre-existing (N7)

5. New findings

ID Severity Finding Evidence Suggested fix
N1 Minor With the dock open between 821 and about 1040 px, the nav padded by --dock-w cannot fit its links and Register, so the row overflows under the dock Register right edge against the dock's left edge: 1024: 604 vs 584; 960: 602 vs 520; 900: 599 vs 460; 821: 596 vs 381 (v3-standard-dock-open-1024x800 shows REGISTE clipped) Below about 1060 px with the dock open, fold the links into [ menu ] (or hide the ul) so Register stays in view, or switch to overlay mode (no padding) below that width
N2 Minor The 24 px head glyph gHead (dock trigger on every standard page, dock header, mind top bar after the first answer) still draws the round-2 capsule: straight sides from y 11.6 to 23, a dark 0.9 outline, a near full-width brow stroke and a vertical nose bar. At 24 px it reads as a helmet with a T visor, the read the owner ruled out, and it no longer matches the still mind.html:251-259, standard.html:285-293; 8x zoom beside the still at the same width: v3-standard-glyph-vs-still-zoom Redraw the glyph from the still's silhouette (domed top, taper below the sockets, no outline, no brow stroke, two soft hollows, no nose bar), or use a 48 px render of the still
N3 Minor At 721 to 1000 px the hero sample note (max-width: 100%) runs across the head; at 768 and 820 it crosses the socket band, a text line across the eyes, close to the sleep-mask read 768: note x 31 to 700, y 901 to 915; head x 536 to 723, sockets y 880 to 915 (v3-standard-top-768x1024). 1024 and up are clear (5 px at 1024) Give .hero .sample-note the facts' max-width: 58%, or move it into the copy column
N4 Nit A fresh phone deep link to #panel-dN lands 51 px low, with two rules: applyHash scrolls while the web fonts are still loading, and the font swap then pushes the agenda down Trace at 390: lands at 55.6 (fonts loading); after the swap the section's document top moves +102 px and scrollY +50, leaving it at 107.5. Desktop moves 1 px. Cold and warm loads behave the same (v3-standard-deeplink-d2-390x844). This is the phone path of the mind's [ open the map: agenda ] Re-run scrollToSection after document.fonts.ready (or defer the first applyHash until then)
N5 Nit --public-host cannot express a default-port or https front. A bare name gets :8777 appended, browsers omit :443 and :80 from Host, and the Origin allow-list is built only as http://host. A TLS tunnel (named in the code comment) would get 421 on Host and 403 on Origin Stub test: Host demo.example → 421; Origin https://demo.example → not allowed; public_hosts("demo.example:443") keeps :443, which no browser sends (server.py:1017-1025, 783) Accept the bare name as given in addition to name:PORT, and allow both http:// and https:// origins for --public-host entries
N6 Nit (pre-existing) On coarse pointers the mind top bar is 90 px tall; its 18 px fade covers the top 9 px of the crown in the empty state Top bar 0 to 90 with the fade from 72 to 90; crown top at 80.7 (390). The slot top rule is unchanged from round 2 Raise the phone slot's top to clear the bar (about 5.75 rem on coarse pointers)
N7 Nit (pre-existing) The fixed Ask pill sits over the lower right of the desktop head's dissolve at rest v3-standard-top-1440x900 Accept, or nudge the slot left by the pill's width at 1280 px and up
N8 Nit (pre-existing) The hero copy column starts at x 48 while the nav and every section start at 128 (1440). At 1920 the hero spans the full width (head at 1449 to 1810) while the rest is centred at 1280 .hero .wrap { width: 100% }; same in v2-standard-top-1440x900 Keep the hero's .wrap at --content-max and position the head against it
N9 Nit (pre-existing) Prices have no thousands separator ($1227.91) mind.html:408, standard.html:563, 608; v3-mind-live-after1-390x844, v3-standard-venue-1440x900; same in v2 toLocaleString('en-US', {minimumFractionDigits: 2})
N10 Nit (code only) The dock's sheet speaker_grid kit head says ${n} speakers (and session_list ${n} sessions) with no pluralization; reachable only when nothing on the page matches standard.html:605-606 Use the existing plural() helper

6. Regressions, console and network

Regressions: none found. Compared with round 2: the venue and register bands, partners, footer, phone menu, the mind demo states and the no-JS pages match the v2 captures apart from the intended fixes (single rule under the nav, spaced //, the still in place of the SVG). Captures: v3-standard-venue-1440x900 against v2-standard-venue-1440x900, v3-standard-footer-1440x900 against v2-standard-footer-1440x900, v3-standard-partners-1440x900, v3-standard-menu-390x844 against v2-standard-menu-390x844, v3-mind-empty-390x844 against v2-mind-empty-390x844 (same white composer panel; the capsule head and the unspaced //who's speaking chips are gone), v3-mind-demo-after5-390x844. N1, N3 and N4 are untested paths, not regressions: the round-2 SVG was wider at tablet widths, and Register sat under the dock at every desktop width in round 2.

Console and network. Every non-mocked context had zero console errors, zero page errors, zero failed requests and zero HTTP responses of 400 or above. That covers the demo, live, hand-off, no-JS, reduced-motion, width-sweep and unclaimed-area contexts, including Google Fonts and the remote speaker photos. The /api/mind leak counter was 0 everywhere. The mocked contexts show only what the mocks caused (one 503 and its console line). One mock context threw 4 page errors from my own instrumentation (a MutationObserver attached before documentElement existed). I fixed the observer, re-ran those mocks, and they were clean.


7. Server checks

Guard sample over raw sockets (no request passes every guard, so there are no model calls):

Request Result
GET with Host evil.example:8777 421 misdirected request
POST with Origin http://evil.example 403 origin not allowed
POST with text/plain 415
POST chunked with no Content-Length 411
POST ending with an assistant message 400 bad_request
HEAD /mind.html 200, Content-Length 48191 (the exact file size), empty body, Server: ets27-proto/0.2

Live turn lines (no message text is logged by design; abridged: the model, first_say and fallback fields are omitted here, all three read model=claude-opus-5-5 and fallback=False):

turn session=mind-2kruiztk mode=mind turns=1 outcome=ok req=req_011CfzE3UxR28x2jZf2Xr7EX reset=False refusal=- in=2 cache_read=0 cache_write=19331 out=494 first_token=2662ms first_ui=4095ms total=6101ms dropped={'dropped_ids': 0, 'dropped_components': 0} prefix_measured=19331
turn session=mind-6dn37bv6 mode=mind turns=1 outcome=ok req=req_011CfzE59qn9G3Y6udj7zcjy reset=False refusal=- in=2 cache_read=19293 cache_write=37 out=114 first_token=1227ms first_ui=1759ms total=2201ms dropped={'dropped_ids': 0, 'dropped_components': 0} prefix_measured=19331
turn session=std-1miiagiq mode=standard turns=1 outcome=ok req=req_011CfzE6WxJcH7nHBrarLALF reset=False refusal=- in=2 cache_read=19304 cache_write=54 out=245 first_token=1940ms first_ui=3382ms total=3781ms dropped={'dropped_ids': 0, 'dropped_components': 0} prefix_measured=19331

The first turn hit a cold cache, so prefix_measured (19,331 tokens) is observed for the first time. In all three live turns the DOM matched the done answer exactly (a fetch tee captured the SSE stream). Mind 1440: speaker_grid:12, session_list:10@d2, choices. Mind 390: ticket_cta, choices. Dock: speaker_grid:12 merged as a filter, choices in the sheet. Each status line pluralized correctly.


8. Not verified

Real-device keyboard behaviour (interactive-widget, visualViewport); Safari and Firefox; the remote bind on a real interface (the logic was stub-tested; a live probe was avoided because of the home-LAN prefix collision and to avoid an incoming-connection prompt on the Mac); a live 429 budget; heartbeat comment lines on the wire; the one-frame decoding="async" gap on a cold load; the 1 h cache window across hours. The accent scan of round 2 was not repeated, because no claim touched colour.


9. Score rationale

Start from 100:

Deduction Reason
-2 The site's 24 px head glyph still reads as a helmet and no longer matches the still (N2)
-2 Dock-open nav overflow at 821 to 1040 px hides Register (N1)
-2 The sample note crosses the head's eyes at tablet widths (N3)
-1 A fresh phone deep link shows two rules (N4)
-1 Remaining nits (N5 to N10)

The decided head is now right in both routes and verified from pixels and diffs. Every round-2 work-list item is fixed at the widths it was raised for, and the live and mocked behaviour is clean: 92 / 100.


10. Captures written this run

prototype/shots/: