Lab
Recorded runs. The rubric below is a sanity check, not the scoreboard — it was wrong seven times during this build, each time in the direction that looks like a discovery, and the model’s own critiques proved the more reliable read of its renders. Treat the scores as a floor and the critiques as the evidence.
Two comparisons are wired up and awaiting data. E1: does K3 actually use the pixels, or would a measured text description do as well? E2: does dropping reasoning_content from its history degrade it, as Moonshot warn but never quantified? Both need a full grid; neither is answered yet, and the panels below say so rather than implying otherwise.
10 runs over 1 tasks, 0 errored. Roughly $3.02 at Moonshot list price — DigitalOcean does not publish a per-token rate for kimi-k3, so every cost here is an upper bound. Confidence intervals are percentile bootstrap; p-values are two-sided permutation tests.
Per-arm summary
| arm | n | final rubric | 95% CI | runs w/ regression | false “done” | iterations | parse misses | reasoning chars | cached in | cost |
|---|---|---|---|---|---|---|---|---|---|---|
preserved/blind | 2 | 95.0% | 0/2 | 50% | 3.0 | 0.00 | 14590 | 43% | $0.319 | |
preserved/vision | 4 | 90.0% | 0/4 | 25% | 3.0 | 0.00 | 12571 | 58% | $0.293 | |
stripped/blind | 2 | 80.0% | 1/2 | 50% | 3.0 | 0.00 | 15460 | 45% | $0.342 | |
stripped/vision | 2 | 90.0% | 0/2 | 0% | 3.0 | 0.00 | 10717 | 16% | $0.267 |
E1 — is the vision load-bearing?
Both arms preserve thinking history. The only difference is whether the feedback is three screenshots or a measured description of the same DOM — box geometry, computed colours including the resolved background behind each element, font size and weight, and the document’s scroll size. Measurements, never conclusions: the description names no defect, so both arms have to find the problems themselves.
Read the pixel-only comparison first, and treat the whole-rubric one as uninterpretable. Every DOM-derived check is computable from the geometry the blind arm receives — and the one that discriminated in practice, legible-text (no text under 12px), has its answer printed verbatim in that input as font 11.52px. The blind arm reads the number; the vision arm has to notice small type in a downscaled JPEG. So a blind win on DOM checks says nothing about whether pixels help. The pixel checks are the only place the arms genuinely differ in information.
| arm | n | share of pixel-derived checks passed | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 1.000 | [1.000, 1.000] |
preserved/blind | 2 | 0.750 | [0.500, 1.000] |
Difference +0.250. no detectable difference (p=0.335). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | share of DOM-derived checks passed | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 0.875 | [0.781, 0.969] |
preserved/blind | 2 | 1.000 | [1.000, 1.000] |
Difference -0.125. no detectable difference (p=0.324). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | final rubric score | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 0.900 | [0.825, 0.975] |
preserved/blind | 2 | 0.950 | [0.900, 1.000] |
Difference -0.050. no detectable difference (p=0.658). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | regressions per run | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 0.000 | [0.000, 0.000] |
preserved/blind | 2 | 0.000 | [0.000, 0.000] |
Difference +0.000. no detectable difference (p=1.000). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
E2 — does dropping thinking history hurt?
Both arms see screenshots. The only difference is whether each assistant message goes back with its reasoning_content intact or with that field removed. Every request asserts the two message arrays are otherwise byte-identical, so any difference here has exactly one cause.
| arm | n | final rubric score | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 0.900 | [0.825, 0.975] |
stripped/vision | 2 | 0.900 | [0.900, 0.900] |
Difference +0.000. no detectable difference (p=1.000). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | regressions per run | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 0.000 | [0.000, 0.000] |
stripped/vision | 2 | 0.000 | [0.000, 0.000] |
Difference +0.000. no detectable difference (p=1.000). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | protocol violations per run | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 0.000 | [0.000, 0.000] |
stripped/vision | 2 | 0.000 | [0.000, 0.000] |
Difference +0.000. no detectable difference (p=1.000). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | iterations used | 95% CI |
|---|---|---|---|
preserved/vision | 4 | 3.000 | [3.000, 3.000] |
stripped/vision | 2 | 3.000 | [3.000, 3.000] |
Difference +0.000. no detectable difference (p=1.000). With n=4/2 this is consistent with no effect, and also can't rule out a modest one.
E2 again, without images
In the vision arm, screenshots accumulate across iterations and can come to dominate the context, shrinking reasoning_content’s share of it. These arms carry no image tokens at all, so this pairing isolates the thinking-history variable. If E2 looks null above but real here, dilution is why.
| arm | n | final rubric score | 95% CI |
|---|---|---|---|
preserved/blind | 2 | 0.950 | [0.900, 1.000] |
stripped/blind | 2 | 0.800 | [0.700, 0.900] |
Difference +0.150. no detectable difference (p=0.664). With n=2/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | regressions per run | 95% CI |
|---|---|---|---|
preserved/blind | 2 | 0.000 | [0.000, 0.000] |
stripped/blind | 2 | 0.500 | [0.000, 1.000] |
Difference -0.500. no detectable difference (p=1.000). With n=2/2 this is consistent with no effect, and also can't rule out a modest one.
| arm | n | protocol violations per run | 95% CI |
|---|---|---|---|
preserved/blind | 2 | 0.000 | [0.000, 0.000] |
stripped/blind | 2 | 0.000 | [0.000, 0.000] |
Difference +0.000. no detectable difference (p=1.000). With n=2/2 this is consistent with no effect, and also can't rule out a modest one.
Regressions observed
A rubric check that passed at one iteration and failed at a later one. Computed mechanically from the render, not graded by a model.
| arm | task | check | passed at | broke at |
|---|---|---|---|---|
stripped/blind | gradient-overlay | no-horizontal-overflow | 1 | 2 |
Stopping early
Runs where K3 declared "done" on a render that still failed the rubric. Moonshot list “excessive proactiveness” as a known trait; this is what it looks like when measured.
3 of 10 runs (30%) stopped on their own while the render still failed at least one check.
Tasks
Three-tier pricing table pricing-table
A three-column table at 390px is the canonical responsive break. Source that looks correct — grid, sensible gaps — routinely overflows in practice, and only the render shows it.
10 rubric checks
no-horizontal-overflow— No horizontal scrolling at any viewport widthnothing-clipped— No text clipped by its own overflow:hidden boxno-render-errors— No uncaught page errors and no render timeoutself-contained— Makes no external requests — fully self-containedlegible-text— No rendered text below 12pxwcag-aa-contrast— All text meets WCAG AA contrast against its effective backgroundno-overlapping-text— No two text elements visually overlap at any widthconsistent-left-alignment— Full-width stacked containers share one left edgethree-ctas— Exactly three call-to-action buttons, all within the viewport at 390pxtappable-ctas— CTA hit targets at least 40px tall on mobile
Metrics dashboard with a bar chart metrics-dashboard
Twelve month labels under a chart is where text collides, rotates badly, or overflows. The code reads fine; the render is where the labels turn into mush.
10 rubric checks
no-horizontal-overflow— No horizontal scrolling at any viewport widthnothing-clipped— No text clipped by its own overflow:hidden boxno-render-errors— No uncaught page errors and no render timeoutself-contained— Makes no external requests — fully self-containedlegible-text— No rendered text below 12pxwcag-aa-contrast— All text meets WCAG AA contrast against its effective backgroundno-overlapping-text— No two text elements visually overlap at any widthconsistent-left-alignment— Full-width stacked containers share one left edgefour-kpi-tiles— Four KPI tiles present at desktop widthchart-present— A chart is actually drawn (svg present, or 12+ bar-like elements)
Article hero that survives a long headline article-hero
A deliberately overlong headline against a fixed-height hero. Fixed heights plus overflow:hidden is the most natural way to write this and the exact thing that clips it — invisible in source, obvious on screen.
10 rubric checks
no-horizontal-overflow— No horizontal scrolling at any viewport widthnothing-clipped— No text clipped by its own overflow:hidden boxno-render-errors— No uncaught page errors and no render timeoutself-contained— Makes no external requests — fully self-containedlegible-text— No rendered text below 12pxwcag-aa-contrast— All text meets WCAG AA contrast against its effective backgroundno-overlapping-text— No two text elements visually overlap at any widthconsistent-left-alignment— Full-width stacked containers share one left edgeheadline-intact— Headline text is present and not visually truncatedhero-fits-fold— Headline sits fully within the first screenful at every width
Text over a wide-range gradient gradient-overlay
The only failure mode here is a painted one. A single text colour cannot be readable across a gradient that spans #fdfdfd to #0b0f1a, so this needs a scrim, a per-section split, a text shadow, or a backdrop panel. Crucially the DOM cannot reveal the defect: getComputedStyle reports no backgroundColor for a gradient, so effectiveBackground is null and the computed-style contrast check has to skip it. Only sampling the rendered pixels shows whether the text survived — which makes this the one task where the vision arm has information the blind arm structurally cannot get.
8 rubric checks
no-horizontal-overflow— No horizontal scrolling at any viewport widthnothing-clipped— No text clipped by its own overflow:hidden boxno-render-errors— No uncaught page errors and no render timeoutself-contained— Makes no external requests — fully self-containedlegible-text— No rendered text below 12pxno-overlapping-text— No two text elements visually overlap at any widthgradient-present— A gradient background is actually usedtext-spans-width— Text actually crosses the gradient rather than hiding at one end