Fifteen single-purpose CLI tools under one JSON envelope. A headless probe records what actually rendered — and which declaration won the cascade — so every drift two reviewers used to argue about becomes a deterministic, citable finding an agent can act on.
Ask audit-kit whether the spacing is off and it answers with a list: route, selector, property, observed value, nearest legal token — and the source declaration that caused it.
Fifteen tools speak one contract. A humans-first Markdown report and an agents-first JSON envelope come out of the same run; every finding carries a 12-hex content-hash id, so "this exact drift" means one thing forever, on any machine. Wire one parser and you can consume every tool the kit will ever ship — the envelope's schemaVersion has never moved off 1.0.0, by decision, not by luck.
It was born inside another drawing in this ledger: the consistency audit of KorCRM, Case File 002. That machine was this machine's first patient. And the kit is project-agnostic by enforcement, not intention — a lint rule treats any hardcoded client reference in the source as a bug.
Somewhere this week, two senior reviewers are disagreeing about a two-pixel gap, and both are right that neither can prove it.
The real scene behind this drawing: 127 screenshots across 19 directories, scrubbed by eye. One card sits at an 18px gap in a sea of 16s. A button ships #6d28d9 where the token says #7c3aed — two purples no human eye can split across two screenshots, which is exactly why "that's not our purple" starts a forty-minute argument and ends it with nothing.
FIG. 1 shows the loop as observed. It runs on opinion, produces no artifact, and exits nowhere. What it lacked was not taste — both reviewers had plenty — but evidence either of them could cite.
A headless browser crawls the route list and records, per element, what actually rendered — every computed style, every bounding box. Since v0.5 it also asks the Chrome DevTools Protocol which CSS declaration won each property, and walks that answer back through sourcemaps to the file you wrote. Cost: +16 ms on a 50-node route. If CDP won't attach, the run degrades to a diagnostic — it never crashes.
token-audit, spacing-audit, tokens-lint, a11y-audit, semantic-diff — all read the same metrics.json, all emit the same envelope. A drift finding names route, selector, property, observed value and the nearest legal token. Sixteen categories, five severities, closed enums: no surprise strings, ever.
Pointed at a real app — my own CRM — the first full run returned 4,306 findings: 782 spacing, 2,714 lint, 656 token, 154 other. Every one technically true; collectively unreadable. At four thousand findings nobody acts, human or agent. This is the wall where most linters go to be ignored.
The fix was not suppression — a mute button hides real drift. It was attribution: trace each finding to the source declaration that caused it, and group by that cause. One .gap-3 in a shared primitive cascading to 272 nodes becomes one finding with affectedNodeCount: 272. The 4,306 collapse to roughly 250 grouped findings pointing at a few dozen declarations — the to-do list the report always should have been.
Every tool exits the same way every time: 0 clean, 1 drift found, 2–6 each a distinct failure mode an agent can branch on without parsing prose. tokens-lint hard-bans raw hex and px in critical properties — three high-severity violations and the build fails at exit 1. Opinions don't gate; exit codes do.
An MCP server exposes all fifteen tools to agents; mark draws numbered boxes on screenshots so a multimodal model can point at finding №7 and mean it. Because every id is a content hash, --verify <id> re-checks one finding and returns the same answer on any machine. The dashed arc is the whole product: every finding arcs back to the one declaration that caused it.
The obvious design: a UUID per finding. It demos fine and makes "is this drift still open from yesterday?" permanently unanswerable.
The shared envelope is upstream of every tool and every downstream agent. One rename there is a fifteen-tool cascade and a broken parser somewhere you can't see.
schemaVersion has never left 1.0.0 — because the first broken downstream agent costs more than every convenience a v2 would buy. Cost, paid knowingly: a known --help description bug ships unfixed, and flow duplicates dom-probe's selector list rather than import it — sealed-tool isolation outranks DRY here. Revisit at a major version, never mid-flight. ADR-003 · ADR-007Real toolchains carry a revision history because real contracts get tested. Five of these rows closed inside the two-day sprint; the sixth is still open, and it's the funny one.
The pattern across them: when something broke, the fix was attribution or contract — never a mute button, never a patch on the symptom.
4px ×295 and 12px ×272 — stock Tailwind .gap-1/.gap-3. Nobody reads a 4,306-line report.affectedNodeCount and per-instance metadata. 4,306 → ≈250.tokens-lint would hand every agent-authored ruleset an eval surface inside a tool that runs in CI.storageState paths — where auth sessions live on disk — could reach envelopes, manifests and streams that get pasted into tickets.package.json declares MIT and lists LICENSE in its files array — but no LICENSE file exists. npm pack doesn't warn; it would silently ship the tarball without the license text. The tool that fails builds over a missing token is missing its own license.One number a skeptic should push on, answered before the interview: 4,306 → ≈250 is a dogfood measurement. Baseline and result were measured on the same real application — my own CRM, Case File 002 — with the same probes, and the raw breakdown above is from the decision log, not memory. It is not an external benchmark, and this page doesn't dress it as one.
What that buys a team: "the spacing looks off" stops costing a forty-minute meeting and starts costing a command. Your reviewer cites a finding id instead of a feeling; your agent fixes one declaration instead of 272 symptoms; and the next run either closes the case or reopens it — deterministically, either way.
Point this at your design system →A dossier about a drift auditor should audit itself, so here is its own finding list, ungrouped.
This tool has one user: me. "Used in practice" means dogfooded on my own CRM — a real application, but mine. It is not on npm; it sits at the v1.0 gate behind three items, one of which is that the package declares MIT and ships no LICENSE file. The repository has no remote — the cleanest, most publishable code in this ledger currently exists on exactly one machine. It was built in a compressed two-day multi-agent sprint at the end of April, and it has not been touched since.
I think that's the honest state of a two-day-old power tool, not a confession of abandonment. What those two days bought was not polish — it was contract discipline: 51 logged decisions, 703 passing tests, an envelope that never moved, and a rule that treats any client reference in the source as a bug. The next project doesn't rebuild any of it; it runs one install and inherits a witness.
This is the quiet promise: the drift you could only feel becomes evidence you can cite, and the screenshot ends the argument.
Bring the review that always ends in opinions. Point the probe at one route and by the second coffee you'll know exactly what drifted, which declaration caused it, and whether it was ever worth a meeting.