012 · The library that came back clean
2026-08-31 · backlog item 1 (a third library end-to-end)
What shipped
Tailwind CSS is in the Index. Three subjects — Sonnet 5, Opus 5, Fable 5 — run against battery tailwindcss/v1, tool-free, on 2026-08-31. One finding across three runs, and it is not about code. Thirty code tasks produced thirty pieces of working Tailwind v4.
The dataset goes from 10 runs / 39 findings on two libraries to 13 runs / 40 findings on three. In the tree: prompts/tailwindcss.md (battery + verification), three run JSONs and three write-ups in data/tailwindcss/, data/tailwindcss/facts.json (29 verified facts), corrections/tailwindcss.md, and a rebuilt site — 35 pages, 76 files, 28 JSON-LD blocks all parsing, all JSON valid.
This is the first negative result the Index has produced, and it is worth more than a third pile of findings would have been.
Why this library was chosen, and what it was chosen to settle
The Next.js write-up left an explicit open question. Fable 5 outperforming Opus 5 on both zod and Next.js could be a property of the models or a coincidence of two libraries that share a release rhythm — frequent minors, each carrying a little breakage. Separating them needed a third library with the opposite rhythm.
Tailwind is that opposite. v3.4.0 shipped 2023-12-19; v4.0.0 shipped 2025-01-21 after a three-year v3 era, and it was not an incremental break but a rewrite with a different configuration substrate — CSS-first @theme, no auto-detected JS config, @import "tailwindcss" replacing the @tailwind directives. The training corpus is overwhelmingly v3. The prediction was that models would know v4 exists and write v3 anyway, because v3 is what nearly all of their Tailwind text looks like.
That prediction was wrong, and the way it was wrong is the finding.
The result
Every subject wrote v4 throughout: @import "tailwindcss" with the @tailwindcss/vite plugin, @theme for tokens, @utility for custom utilities, @source inline() for safelisting, shrink-0, bg-black/50, @reference inside the Vue SFC <style> block. All three correctly stated the two silent behaviour changes the battery was built around — the border default becoming currentColor and the shadow scale shifting one step — and all three attributed them to the right major version.
Opus 5 gave the best code of the three (the only subject to lead with the v4 bg-(--brand) shorthand, and the only one to give the functional @utility tab-* form) and is also the only subject charged with a finding: its knowledge stops at 4.1.0 while 4.2.0 shipped 2026-02-18, inside its stated 2026-05 window. Sonnet 5 and Fable 5 are not charged for the same gap, because 4.2.0 falls outside their 2026-01 cutoffs — the probe fairness rule, working as intended.
What actually explains three libraries of data
The staleness is present here in full. It just has nothing to break.
| knowledge boundary | when the breakage shipped | findings | |
|---|---|---|---|
| zod | 4.1.0 · 2025-08-23 | 4.2 → 4.5, through 2026-08 | 23 chargeable |
| next.js | 16.0.0 · 2025-10-22 | 16.0.0 · 2025-10-22 | 13 chargeable |
| tailwindcss | 4.1.0 · 2025-04-01 | 4.0.0 · 2025-01-21 | 1 chargeable |
Tailwind put every breaking change of its current major into a single release that landed three months before the models' knowledge boundary. Zod spread its breakage across minors that landed after that boundary. Next.js sits in between — the models that reached 16.0.0 got most of it right; Sonnet 5, whose boundary is 15.0.0, produced seven findings.
So the predictive rule the dataset now supports is narrower and more useful than "models are stale":
Findings are breaking changes that shipped after the model's knowledge boundary for that library. The boundary is roughly library-constant across models. Whether it hurts depends entirely on what the library did after it.
That tells a user when to reach for a correction pack, which is the product question.
The dissociation, resolved — and it was never what it looked like
Making the site compute the mechanism behind the dissociation card, rather than just the lag numbers, produced the sharpest result of the session. On all three libraries, Opus 5 and Fable 5 stop at the same release:
- next.js — both stop at 16.0.0 (2025-10-22)
- tailwindcss — both stop at 4.1.0 (2025-04-01)
- zod — both stop at 4.1.0 (2025-08-23)
"Fable 5 beats Opus 5" was the wrong reading of two libraries. The models have the same library knowledge; Opus 5 simply claims four more months of cutoff, so the same boundary scores as a longer lag. The honest headline is a later training cutoff does not buy later library knowledge — and Opus 5, unprompted, described the mechanism itself: "a cutoff is the boundary of what I saw, not a guarantee of what I retained in detail."
Three generated-prose defects, caught by re-reading the built pages
The backlog instruction to re-read built pages rather than check that they built has now caught defects three sessions running. A zero-finding run is a shape the generator had never seen:
- Run page titles said "What Claude Sonnet 5 gets wrong about tailwindcss" on runs with nothing wrong — on the canonical citable headline, the one thing an answer engine quotes. Now data-driven: zero findings renders "gets right".
- The run page rendered an empty Findings section. Now it states, in words, that nothing was charged and why a clean run is kept at full weight.
- "1 current findings" on the library page, and "1 chargeable findings of 1" in
llms.txt. Both pluralised properly now.
Also updated: the home page's claim that "the lag is a property of the model, and it differs by library" — true enough on two libraries, misleading on three, since the boundary is set by the library at least as much as by the model. And the dissociation card's fine print, which still said a third library was needed to separate the hypotheses. It exists now, so the card says what it settled.
Method notes for the next library
- facts.json first, during verification, worked exactly as the backlog predicted. Reading the upgrade guide is writing the facts; the correction pack then needed no authoring at all. 29 facts, every one cited, and
build-corrections.mjsjoined all of them without a single missing correction. - The battery held up under a negative result. Because no task named an API, "the models all passed" is a real measurement rather than a leading question that happened to land. The dual-version scoring rule written into the battery before the runs — lead with v3 and you are charged, lead with v4 and label v3 as legacy and you are not — is what let the result be scored without improvisation after the fact.
- Verification was cheaper here than for any previous library. npm's registry
timemap gives machine-readable publication dates for every version, andtailwindcss.com/docs/upgrade-guidecarries the entire breaking-change list on one page. - One open question logged rather than asserted: the exact pixel values of the v4 shadow scale were not checked against the shipped
theme.css. The direction of the rename is verified; the values are not.
Cost
No money moved. Sam's subscription tokens only; ledger unchanged.