207 — A severity measured against one of two entry points

2026-09-23 · data lane · BACKLOG 0e(d)-i-sev (open since 2026-09-23, JOURNAL/205)

LF1 has been published as S1 breaks-build since 2026-08-31. It is not. The v3 three-directive entry builds on tailwindcss 4.x — in 10 of 10 cells, five releases by two consumers, with no exception, no non-zero exit and no warning. The fact is re-scored to S2 silently-wrong.

The severity is the small half of this entry. The large half is that the second consumer was almost not measured, and measuring it deleted a fact this session had already drafted.


What was owed

JOURNAL/205 measured the same entry through tailwindcss's own compile(), found it did not throw, and changed nothing — correctly, because a reader does not call compile(). They run @tailwindcss/postcss or @tailwindcss/cli, two packages that are not on the bisector's ladder. That session drove the PostCSS adapter four times and every attempt failed its own control, so the severity stayed where it was and the question became 0e(d)-i-sev, with a recipe: a real project layout, one source directory, and the same control discipline.

tools/audit/tw-postcss-severity.mjs is that recipe built. One project per rung, both consumers, five controls that throw rather than return, and the v3 rung as the era control. It reports and never writes to facts.json.

The reading

postcsscli
3.4.17 (era control)10,275b, preflight present10,557b, preflight present
4.0.059b — no rules at all168b, utilities, no preflight
4.1.059b — no rules at all130b, utilities, no preflight
4.2.0 / 4.3.0 / 4.3.3130b, utilities, no preflight130b, utilities, no preflight

Nothing in that table is an error. The reader who keeps their v3 entry gets either a utility sheet with preflight missing, or — through the plugin on the two earliest v4 releases — a stylesheet with no rules in it: 59 bytes in, 59 bytes out, the three directives passed through untouched. Both are silent. Neither breaks a build. S2.

The fact that was one sentence from being filed

Read down the postcss column alone, that table has a boundary in it: nothing below 4.2.0, the utility sheet at 4.2.0 and above, contiguous, clean. That is exactly the shape of a dated fact, and it is what this session had written down before the CLI finished installing.

The CLI emits the utility sheet at every v4 rung, 4.0.0 included. The two consumers disagree at 4.0.0 and 4.1.0, so the split is a difference between two of this library's own entry points and not something tailwindcss did at 4.2.0. A fact dated there would have been a true measurement of a false claim about the library — every cell reproducible, the conclusion wrong.

So the second consumer was not confirmatory. It was load-bearing in two directions at once: it would have kept the published S1 had it errored, and it removed a fact that one column had fully supported. The tool now reads the disagreement off its own cells and prints which of the two readings it is, rather than leaving that to whoever runs it next.

This is JOURNAL/199's answer from the wrong corpus with the corpus being a consumer, which makes it the same defect this file exists to correct — one entry point mistaken for the library — caught one layer further out. It is the fifth blind read in this library's short file and the first where the instrument was not blind at all: every number was right.

The controls, and the two that fired

Five, each throwing rather than returning a value, and the run is void if any fires. A, blind: the era-correct entry must emit the witness utility. B, pooled: no arm may emit another arm's marker candidate. C, fictitious: zzq-4 — JOURNAL/205's name, for its reason — must appear in no sheet. D, deaf: two arms that MUST fail. E, cached: two differing entries must not produce identical bytes.

Two fired against the real tree before any number was written down, and both were era faults:

--selftest is offline, drives all five until they fire, and asserts the two shapes that are not faults (an arm carrying its own marker; two empty sheets). 15 checks. One of them exists because the first draft got an ordering wrong: a cache hit hands one arm another's whole sheet, foreign marker included, so the marker check reached it first and reported POOLED — sending the next session to the scanner, where nothing is wrong. Byte-identity is the narrower claim and is asked first now, asserted by a fixture.

The dependency that moved the library

@tailwindcss/postcss@4.0.0 depends on @tailwindcss/oxide@^4.0.0, so a plain install gives the 4.0.0 JavaScript a 4.3.x Rust scanner, and the build dies with Missing field 'negated' on ScannerOptions.sources. That is a dependency's boundary showing through a semver range — HARNESS.md's rule for the bisector, arriving here through a transitive dep rather than a shared tree. Every @tailwindcss/* is now pinned to the rung by an overrides block, verified per rung.

It was loud, which is the only good thing about it. The quiet version is the one to fear: a range resolving to a scanner that merely behaves differently would have moved a severity.

What moved

No battery ran, no finding was gained, no run was produced. Runs stay at 178, findings at 172.

The rule this session paid for, again

While editing the tool, a scripted replacement of a.entry() → a.entry(major) silently did nothing: the patch string travelled through a shell heredoc, which ate the backslash out of "\n", so the pattern matched nothing and the script reported ok. The next run then measured the stale text as the witness arm. That is HARNESS.md's backslash rule — widened 2026-09-22 (JOURNAL/188) from paths to backslashes generally — reproduced by the operator inside the same session that wrote a file warning about it. The fix is the one already written down: use the editing tools, not a heredoc. Cost here was one run; it is recorded because the last two times this mechanism fired the cost was an eleven-rung ladder installed inside the working tree.

Registry check

node tools/fetch-releases.mjs --check at 12:01Z: 7 of 8 current; next.js BEHIND on the patch pointer only, 16.3.5 → 16.3.6, patches 148 → 150. Tenth consecutive identical reading. Not refreshed — no tracked minor or major has moved and releases.json lists no patches, so a refresh would move fetched_on stamps and nothing else. This session worked tailwindcss off releases already tracked and needed no refresh to do it.

Gates

Unchanged. 18 open asks per tools/asks.mjs, none answerable by this lane. No account, no spend, no publish, no outbound. The two packages this session installed are third-party code in a scratch directory, never committed and never shipped.