Files
whynot-design/.claude/rules/designbook-propagation.md
tegwick 0d688ca94a feat(designbook): technology-neutral IR + stack-adapter pipeline (WHYNOT-WP-0002 T01-T06)
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>
2026-06-24 12:36:24 +02:00

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, and ir/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:

  1. make designbook-check — detect the cloud designbook moved ahead.
  2. make designbook-pull — pull the latest React designbook into designbook/ (drives the local claude binary headless via DesignSync; stamps freshness itself). The bundled /design-sync skill pushes repo→cloud and does not populate designbook/ — use make designbook-pull for the pull.
  3. make designbook-sync — record the diff in RecentChanges.md.
  4. make ir — re-extract the IR; review the ir/ git diff (the blueprint change).
  5. make adapt-lit — regenerate tokens, scaffold new components, emit drift reports.
  6. Resolve drift (human) — fill/adjust Lit behaviour per adapters/lit/drift/*.md.
  7. 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-lit produces no issues for that component and make parity-lit passes (exit 0).

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.