Retiring rulebook #2 left the /design drift panel with no data source, and
because its empty state was well-written the feature read as working while it
could only ever render "nothing designated" (#2419). The original question is
genuinely gone: theme.css is generated from design system 2, so checking the
system against a sheet derived from it would be a tautology.
The question that survives is the one no server can answer. A generated sheet
still has to be LOADED and APPLIED, and nothing checked that it was:
absent the record declares a token the app doesn't have — the sheet was
never regenerated after the record changed, or never loaded
differs the app has it with another value — a stale sheet, or a later
rule that overrode it
unrecorded the app declares a token in the record's own family that the
record has never heard of
Both sides go through the same engine so the comparison is honest: declared
values are set on an offscreen probe and read back, which performs the same
var() substitution the browser already did to the live values. Comparing raw
strings would mark every derived token as drift.
The designation moved with the feature — design_rulebook_id becomes
ui_design_system_id, with a migration deleting the retired key rather than
leaving an inert row. The prose extractor it fed goes too (#2288 said its
runtime role ended when the import landed).
Three orphans of the same shape, found alongside and fixed here:
- darkOverriddenNames hardcoded [data-theme="dark"]. The sheet went dark-first
months ago, so it matched nothing and the "mode-aware" flag silently left the
gallery. Now matches the SHAPE of a mode selector, which also holds for an
install whose modes aren't light and dark.
- groupFor's prefix table never heard of --fs-, so 110 tokens sat under
"other". Groups now come from the record where there is one; the table can
only know families that shipped with the product (rule #115).
- The type scale was a hand-written table of nine sizes marked "no token",
true when written and false since the scale was recorded. Now rendered from
whatever size tokens the sheet declares, so it can't go stale twice.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs