Author the design language once in the canonical React designbook and project it
one-way onto each stack: React -> designbook/ -> ir/ -> adapters/<stack>/.
Phase 0 — contracts & governance (T01-T03):
- ir/SCHEMA.md + ir/schema/{component,tokens}.schema.json — neutral IR contract
(W3C DTCG tokens; React prop -> HTML attribute mapping; non-portable props flagged).
- adapters/ADAPTER_CONTRACT.md — inputs, drift-report + parity-result shapes,
idempotency rules, CI exit codes (0 ok / 2 usage / 3 drift / 4 parity / 5 internal).
- .claude/rules/designbook-propagation.md + DesignSystemIntroduction.md §5.1 —
one-way directionality + drift-resolution workflow.
T04 — canonical React designbook + the missing pull tool:
- The bundled /design-sync skill only PUSHES repo->cloud; it cannot populate
designbook/. Added scripts/designbook_pull.py + `make designbook-pull`, which drives
the local claude binary headless (acceptEdits) so DesignSync fetch+write runs in a
subprocess (contents never hit the orchestrator's context). Pulled 44 files;
excludes the _whynot-design-seed/ self-copy. Corrected the docs that wrongly called
/design-sync the pull.
T05 — IR extractor (scripts/ir-extract.mjs + `make ir`):
- ir/tokens.json (80 tokens, DTCG, var() -> {ref} alias resolution); ir/components/*.json
(10 contracts parsed from .jsx signatures: enum/boolean/number inference, prop->attr
map, style/callback marked non-portable); ir/exemplars/*.
T06 — Lit token adapter (adapters/lit/ + `make adapt-lit`):
- Full-gen tokens into src/styles/colors_and_type.css :root (marker-bounded, idempotent
no-op on re-run; hand-authored type CSS preserved).
NOTE: token regen synced Lit to canonical React — fonts IBM Plex -> system stacks and 8
status tokens added. This is a VISUAL change: review and run `pnpm test:visual:update`
before merge. Remaining: T07 scaffold+drift, T08 parity, T09 runbook, T10 2nd-adapter.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
Designbook propagation & adapter governance (WHYNOT-WP-0002)
The whynot design language is technology-neutral. It is authored once and projected onto each UI stack through an intermediate representation. These rules keep that flow one-way and the stacks in sync.
Directionality — one way only
Claude Design (React, canonical) → designbook/ → ir/ → adapters/<stack>/ → stack source
- Claude Design (the React designbook) is the source of truth for the language.
- Never hand-edit
ir/—ir/tokens.json,ir/components/*.json, andir/exemplars/*are written only by the extractor (scripts/ir-extract.mjs,make ir). They are committed so blueprint changes show up as a git diff. Authored-by-hand exceptions:ir/schema/,ir/SCHEMA.md,ir/README.md. - Never back-edit React/Claude Design from a stack. A Lit (or any stack) change that should alter the shared language must be made in Claude Design and re-propagated. A direct stack→React edit that bypasses Claude Design is a governance violation — it desyncs the canonical source from the implementation.
- Adapters never overwrite hand-authored behaviour. Tokens regenerate fully;
new components get stubs; changed components get a drift report, never a
rewrite. See
adapters/ADAPTER_CONTRACT.md.
When the cloud designbook moves
Run the refresh sequence (orchestrated by make designbook-refresh, WHYNOT-WP-0002
Phase 5); do not shortcut it:
make designbook-check— detect the cloud designbook moved ahead.make designbook-pull— pull the latest React designbook intodesignbook/(drives the localclaudebinary headless viaDesignSync; stamps freshness itself). The bundled/design-syncskill pushes repo→cloud and does not populatedesignbook/— usemake designbook-pullfor the pull.make designbook-sync— record the diff inRecentChanges.md.make ir— re-extract the IR; review their/git diff (the blueprint change).make adapt-lit— regenerate tokens, scaffold new components, emit drift reports.- Resolve drift (human) — fill/adjust Lit behaviour per
adapters/lit/drift/*.md. make parity-lit— confirm appearance + contract parity (gate).
Drift triage
A drift report (adapters/lit/drift/<Name>.md, command exit code 3) is resolved
by a human, not the adapter:
- Decide direction: stale stack → fix the stack to match IR; language should change → edit Claude Design and re-propagate (never patch only the stack).
- Non-portable props (React objects, render props, callbacks) are surfaced as drift on purpose and must be handled explicitly — never silently dropped.
- A report is closed when a fresh
make ir && make adapt-litproduces no issues for that component andmake parity-litpasses (exit0).
Exit codes (CI)
0 ok · 2 usage/config error · 3 drift detected (stop for human triage) ·
4 parity failure (fail) · 5 internal error. See adapters/ADAPTER_CONTRACT.md.
Full narrative: DesignSystemIntroduction.md §5.1.