feat(design-explorer): the drift panel — rulebook says X, tokens say Y
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / TypeScript typecheck (push) Successful in 11s
CI & Build / integration (push) Successful in 15s
CI & Build / Python tests (push) Successful in 43s
CI & Build / Build & push image (push) Successful in 40s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / TypeScript typecheck (push) Successful in 11s
CI & Build / integration (push) Successful in 15s
CI & Build / Python tests (push) Successful in 43s
CI & Build / Build & push image (push) Successful in 40s
Milestone #251 step 5 (#2262), plus the Settings control that makes it reachable. The comparison is deliberately thin — set arithmetic over live token values, which is the one thing the browser knows and the server doesn't. The hard half (prose to claims) already lives in Python where pytest can assert on it. Three claim kinds, and the third inverts the test: a `token` claim asks whether a custom property of that name exists; a `color` claim asks whether any token resolves to that value; a `prohibited_color` claim FAILS when present. normalizeColour is the client-side twin of normalize_hex and has one job the server cannot do: getComputedStyle reports colours as rgb()/rgba() regardless of how they were authored. So one colour has three spellings in play — #FFFFFF in the rulebook, #fff in the stylesheet, rgb(255,255,255) from the browser — and a comparison that misses any of them under-reports silently rather than erroring. THE PANEL STATES ITS OWN BLIND SPOT, which matters more than it sounds. This compares the rulebook against TOKENS. A literal hardcoded in a component, where a token should have been referenced, is invisible to it — the drift isn't in the tokens at all (#2275: 67 hardcoded whites against a rule forbidding pure white). Reading those would mean bundling every SFC's source into the app; the check belongs in CI and is tracked at #2277. A drift report that silently omitted a whole category would invite the reader to conclude the category is clean, so the panel says so in the panel rather than in a comment nobody reads. Findings are ranked violated → missing → ok, and `ok` rows are hidden behind a toggle. Same principle the auto-inject menu is built on: a short list that gets read beats a complete one that doesn't. Settings gains a rulebook picker. "None" is a first-class choice, not an unset error — most installs have no rulebook describing their design system, and saving empty DELETES the setting rather than storing a zero. The panel's empty state points at Settings and Settings points back at the panel, so neither is a dead end. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
import { apiGet } from "@/api/client";
|
||||
import type { ExpectationResponse } from "@/utils/designDrift";
|
||||
|
||||
/** Checkable claims from the rulebook this install designated as its design system.
|
||||
*
|
||||
* `rulebook_id: null` means none has been designated — the normal state for a
|
||||
* fresh install, not an error. The caller shows an explanatory empty state. */
|
||||
export const fetchDesignExpectations = () =>
|
||||
apiGet<ExpectationResponse>("/api/design/expectations");
|
||||
Reference in New Issue
Block a user