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>
72 lines
3.9 KiB
JavaScript
72 lines
3.9 KiB
JavaScript
// =============================================================
|
||
// Sample data — prototypes, signals, inbox items
|
||
// =============================================================
|
||
|
||
const PROTOTYPES = [
|
||
{
|
||
id: 'WNO-014',
|
||
pitch: 'A field-notebook for catching weird ideas before they evaporate.',
|
||
learning: 'Do people return to capture more than once?',
|
||
test: 'One-page landing + email capture, 14 days.',
|
||
target: 'Coulomb',
|
||
stage: 'experiment',
|
||
stageLabel: 'Experiment',
|
||
signal: 'S1',
|
||
risks: 'Confused with note-taking apps.',
|
||
},
|
||
{
|
||
id: 'WNO-017',
|
||
pitch: 'A LEGO-brick mood board for engineers who don’t think in mood boards.',
|
||
learning: 'Will engineers attach metaphors to their tickets?',
|
||
test: 'Slack bot, three teams, two weeks.',
|
||
target: 'Helix',
|
||
stage: 'signal',
|
||
stageLabel: 'Signal review',
|
||
signal: 'S3',
|
||
risks: 'Cute but unused after a week.',
|
||
},
|
||
{
|
||
id: 'WNO-021',
|
||
pitch: 'Concierge-style “prototype triage” for indie hackers.',
|
||
learning: 'Will three founders pay for a one-hour triage call?',
|
||
test: 'Offer beta · 3 calls · listed price.',
|
||
target: 'Plenitude',
|
||
stage: 'experiment',
|
||
stageLabel: 'Experiment',
|
||
signal: 'S2',
|
||
risks: 'Time-cost outruns signal value.',
|
||
},
|
||
{
|
||
id: 'WNO-024',
|
||
pitch: 'A relevant-#CoronaPolitics timeline, re-released with one editor.',
|
||
learning: 'Is there residual demand five years on?',
|
||
test: 'Static preview page, 30 days, count returns.',
|
||
target: 'None yet',
|
||
stage: 'parked',
|
||
stageLabel: 'Parked',
|
||
signal: 'S0',
|
||
risks: 'Topical relevance has clearly faded.',
|
||
},
|
||
];
|
||
|
||
const INBOX = [
|
||
{ id: 1, ts: '2026-03-02 14:21', text: 'Idea: “subway map” view of the prototype pipeline. People understand transit maps; they don’t understand kanban boards.', from: 'Tegwick' },
|
||
{ id: 2, ts: '2026-03-01 09:08', text: 'Weird observation from yesterday’s call: three founders independently asked for “something to capture the half-formed stuff”.', from: 'note-to-self' },
|
||
{ id: 3, ts: '2026-02-28 23:55', text: 'Could the LEGO-brick metaphor extend to a public “build log” format? One brick = one decision.', from: 'Tegwick' },
|
||
{ id: 4, ts: '2026-02-27 11:34', text: 'Park idea: realtime sentiment dashboard for prototype landing pages. Probably worse than reading the comments.', from: 'note-to-self' },
|
||
{ id: 5, ts: '2026-02-26 17:02', text: 'Conversation with R. about closed-beta etiquette. Useful: pre-write the exit email before the beta opens.', from: 'note-to-self' },
|
||
{ id: 6, ts: '2026-02-25 08:12', text: 'fuerindifferenz shirts: residual interest from old whywhynot.de page. Could a yearly drop work?', from: 'Tegwick' },
|
||
{ id: 7, ts: '2026-02-24 15:40', text: 'Tiny idea: a “reject log” that publishes the ideas you said no to, with one-sentence reasons.', from: 'note-to-self' },
|
||
];
|
||
|
||
const SIGNALS = [
|
||
{ id: 'SIG-031', proto: 'WNO-017', level: 'S3', what: 'Two teams shipped public README sections labelled “brick: scope” after using the bot for a week.', source: 'usage log', date: '2026-03-04' },
|
||
{ id: 'SIG-030', proto: 'WNO-017', level: 'S2', what: 'Three engineers DM’d asking for an export-to-Notion option.', source: 'Slack', date: '2026-03-03' },
|
||
{ id: 'SIG-029', proto: 'WNO-014', level: 'S1', what: 'Landing page: 34 visits, 7 emails, 0 returns in week 1.', source: 'Plausible', date: '2026-03-01' },
|
||
{ id: 'SIG-028', proto: 'WNO-021', level: 'S2', what: 'First triage call booked at listed price; second declined on price.', source: 'Stripe / email', date: '2026-02-28' },
|
||
{ id: 'SIG-027', proto: 'WNO-021', level: 'S1', what: '“Interesting but I’d want a free first one” ×2.', source: 'interview', date: '2026-02-26' },
|
||
{ id: 'SIG-026', proto: 'WNO-024', level: 'S0', what: 'Static preview: 12 visits in 30 days, 0 returns.', source: 'Plausible', date: '2026-02-24' },
|
||
];
|
||
|
||
Object.assign(window, { PROTOTYPES, INBOX, SIGNALS });
|