It has no list of banned patterns
Forbid the purple gradient and the generic reappears wherever the list does not reach. A finding here is two things at once: the pattern is present, and there is no evidence anyone chose it. Neither half alone is a finding.
So the auditor starts by looking for proof that somebody chose the value.
That proof might live in a variables file, a :root block, a
theme config or a comment beside the value. When it finds proof, the
report says nothing about the pattern.
A generic page beside the product it was meant to explain.
The first pair holds the subject constant. Both pages are for Merge Odds. One could advertise any tool; the other opens with the policy gate the product actually applies and lets the reader inspect measured projects.
MERGE ODDS · SAME PRODUCT
BEFORE interchangeable promises
AFTER the product defines the page
LULL · ANOTHER DECIDED PRODUCT
BEFORE defaults left in place
AFTER decisions made visible
What a run gives you back
A verdict in plain words, then a ranked list. ROOT holds the findings that close others when you fix them; THEN holds the rest. One row, one id, one place to open.
| id | what is missing | where |
|---|---|---|
| ROOT | ||
| A1 | The theme picks no colour, no radius and no type scale | tailwind.config.ts:5 |
| A10 | The card's classes retyped by hand instead of reused | components/stat-card.tsx:3 |
| THEN | ||
| F1 | The page never says what language it is in | app/layout.tsx:7 |
| F11 | Rows built from a list with nothing to tell them apart | components/table.tsx:17 |
| W3 | The empty table reports a count instead of offering a first step | components/table.tsx:13 |
Five real findings, each checked against
fixtures/slop-dashboard on 2026-08-18. The two under ROOT
are there because the same evidence produces four more: the empty theme
is also why A3 and A5 fire, and the retyped card is also why A4 and A6
do. Two files close six findings. Twenty-one blind reports are committed
under calibration/, written by agents that were given the
skill and the directory and nothing else.
Two skills, and they are one loop
anti-slop:audit
Reads what already exists. Run it on the whole project or on one file, and on all five axes or on one of them. It reads any web stack: 39 of the 49 tells never name a framework, a build tool or a library.
anti-slop:build
Runs before the components exist. It asks four questions the auditor cannot answer. What is the product? How does it talk? How sober should it look? How much belongs on one screen? It records each derived value and the reason for it where the auditor searches for evidence.
Which is how each half tests the other: a tell that fires on a tree the build skill produced is the build skill's failure, and it arrives with a file and a line.