Files
whynot-design/designbook/preview/page-signals-dashboard.html
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

136 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<!-- @dsCard group="Pages" name="Pages · Signals dashboard" subtitle="Market-signal log · filter by strength · evidence rows" viewport="1280x860" -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Signals · whynot-control</title>
<link rel="icon" href="../assets/whynot-logo.png">
<link rel="stylesheet" href="../colors_and_type.css">
<style>
html, body { margin: 0; background: var(--paper); color: var(--fg-1); }
.nav { height: 60px; display: flex; align-items: center; gap: 24px; padding: 0 40px; border-bottom: 1px solid var(--line); }
.nav .brand { display: flex; align-items: center; gap: 10px; }
.nav .brand img { width: 22px; height: 22px; }
.nav .brand .nm { font: 500 15px var(--ff-sans); letter-spacing: -0.01em; }
.nav .brand .slug { font: 400 12px var(--ff-mono); color: var(--fg-3); }
.nav .right { margin-left: auto; display: flex; align-items: center; gap: 16px; }
.nav .search { font: 400 12px var(--ff-mono); color: var(--fg-3); border: 1px solid var(--line); border-radius: var(--r-1); padding: 6px 10px; min-width: 220px; display: flex; gap: 8px; }
.nav .search .kbd { margin-left: auto; border: 1px solid var(--line); border-radius: 2px; padding: 0 5px; font-size: 10px; }
.app { display: grid; grid-template-columns: 220px 1fr; min-height: calc(100vh - 60px); }
.leftnav { display: flex; flex-direction: column; gap: 28px; padding: 28px 8px 24px 16px; border-right: 1px solid var(--line-soft); }
.leftnav .section { display: flex; flex-direction: column; gap: 8px; }
.leftnav .lbl { font: 500 11px/1 var(--ff-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-3); padding-left: 12px; opacity: 0.7; }
.leftnav .items { display: flex; flex-direction: column; gap: 1px; }
.leftnav .item { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-left: 2px solid transparent; color: var(--fg-3); font: 400 13px var(--ff-sans); text-decoration: none; }
.leftnav .item .ic { width: 16px; height: 16px; stroke: currentColor; stroke-width: 1.5; fill: none; flex: none; }
.leftnav .item .n { margin-left: auto; font: 400 11px var(--ff-mono); color: var(--ink-5); }
.leftnav .item.active { color: var(--fg-1); font-weight: 500; border-left-color: var(--ink); }
.leftnav .item.doc { font: 400 12px var(--ff-mono); }
.leftnav .footer { margin-top: auto; display: flex; align-items: center; gap: 8px; padding: 0 12px; font: 400 11px var(--ff-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--fg-3); }
.leftnav .footer .dot { width: 5px; height: 5px; border-radius: 999px; background: var(--ink-4); }
.main { padding: 40px 56px 80px; max-width: 1040px; }
.head { display: flex; flex-direction: column; gap: 10px; margin-bottom: 32px; }
.head .eyebrow { font: 500 11px/1 var(--ff-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-3); }
.head .row { display: flex; align-items: flex-end; gap: 24px; }
.head h1 { font: 400 32px/1.2 var(--ff-sans); letter-spacing: -0.02em; margin: 0; flex: 1; }
.head .lede { font: 400 16px/1.6 var(--ff-sans); color: var(--fg-2); margin: 4px 0 0; max-width: 58ch; }
.btn { font: 500 13px var(--ff-sans); padding: 9px 15px; border-radius: var(--r-2); border: 1px solid var(--ink); background: var(--ink); color: var(--paper); cursor: pointer; display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.btn .ic { width: 14px; height: 14px; stroke: currentColor; stroke-width: 1.5; fill: none; }
/* distribution strip */
.dist { display: flex; gap: 0; border: 1px solid var(--line); border-radius: var(--r-2); overflow: hidden; margin-bottom: 28px; }
.dist .cell { flex: 1; padding: 14px 16px; border-right: 1px solid var(--line-soft); display: flex; flex-direction: column; gap: 6px; }
.dist .cell:last-child { border-right: 0; }
.dist .cell .lv { display: inline-flex; align-items: center; gap: 6px; font: 500 10px/1 var(--ff-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-3); }
.dist .cell .lv .b { width: 8px; height: 8px; border-radius: 999px; }
.dist .cell .ct { font: 300 28px/1 var(--ff-sans); color: var(--fg-1); }
.b0 { background: var(--status-raw); } .b1 { background: var(--status-weak); } .b2 { background: var(--status-medium); } .b3 { background: var(--status-strong); } .b4 { background: var(--status-commercial); }
.filters { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.chip { font: 500 10px/1 var(--ff-mono); letter-spacing: 0.1em; text-transform: uppercase; padding: 5px 10px; border-radius: 999px; border: 1px solid var(--line); color: var(--fg-2); background: var(--paper); cursor: pointer; }
.chip.active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.filters .count { margin-left: auto; font: 400 11px var(--ff-mono); color: var(--fg-3); }
.rows { display: flex; flex-direction: column; }
.srow { display: grid; grid-template-columns: 90px 90px 1fr; gap: 6px 24px; padding: 20px 0; border-bottom: 1px solid var(--line-soft); align-items: baseline; }
.srow .id { font: 400 11px var(--ff-mono); color: var(--fg-3); }
.srow .pr { font: 400 11px var(--ff-mono); color: var(--fg-2); }
.srow .dot { display: inline-flex; align-items: center; gap: 6px; font: 500 11px/1 var(--ff-mono); letter-spacing: 0.06em; color: var(--fg-2); }
.srow .dot .b { width: 8px; height: 8px; border-radius: 999px; }
.srow .what { grid-column: 1 / -1; margin: 4px 0 0; font: 400 14px/1.55 var(--ff-sans); color: var(--fg-1); max-width: 64ch; }
.srow .src { grid-column: 1 / -1; font: 400 11px var(--ff-mono); color: var(--fg-3); }
</style>
</head>
<body>
<nav class="nav">
<div class="brand"><img src="../assets/whynot-logo.png" alt=""><span class="nm">whynot</span><span class="slug">/ control</span></div>
<div class="right"><div class="search"><span>Search…</span><span class="kbd">⌘ K</span></div></div>
</nav>
<div class="app">
<nav class="leftnav">
<div class="section">
<span class="lbl">Work</span>
<div class="items">
<a class="item"><svg class="ic" viewBox="0 0 24 24"><path d="M22 12h-6l-2 3h-4l-2-3H2"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg><span>Inbox</span><span class="n">7</span></a>
<a class="item"><svg class="ic" viewBox="0 0 24 24"><path d="M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"/><path d="M6.453 15h11.094"/><path d="M8.5 2h7"/></svg><span>Prototypes</span><span class="n">4</span></a>
<a class="item active"><svg class="ic" viewBox="0 0 24 24"><path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.5.5 0 0 1-.96 0L9.24 2.18a.5.5 0 0 0-.96 0l-2.35 8.36A2 2 0 0 1 4 12H2"/></svg><span>Signals</span><span class="n">12</span></a>
<a class="item"><svg class="ic" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/><path d="M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z"/></svg><span>Betas</span><span class="n">1</span></a>
<a class="item"><svg class="ic" viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg><span>Decisions</span><span class="n">3</span></a>
</div>
</div>
<div class="section">
<span class="lbl">Control docs</span>
<div class="items">
<a class="item doc"><span>MARKET_SIGNAL.md</span></a>
<a class="item doc"><span>OPERATING_MODEL.md</span></a>
</div>
</div>
<div class="footer"><span class="dot"></span><span>A1 · Incubating</span></div>
</nav>
<main class="main">
<div class="head">
<span class="eyebrow">whynot-control / signals</span>
<div class="row">
<h1>Signals</h1>
<button class="btn"><svg class="ic" viewBox="0 0 24 24"><path d="M12 5v14"/><path d="M5 12h14"/></svg>Record signal</button>
</div>
<p class="lede">A signal is evidence, not a vibe. Record what happened, who did it, and how strong the evidence is. Lack of signal is also information.</p>
</div>
<div class="dist">
<div class="cell"><span class="lv"><span class="b b0"></span>S0</span><span class="ct">1</span></div>
<div class="cell"><span class="lv"><span class="b b1"></span>S1</span><span class="ct">2</span></div>
<div class="cell"><span class="lv"><span class="b b2"></span>S2</span><span class="ct">2</span></div>
<div class="cell"><span class="lv"><span class="b b3"></span>S3</span><span class="ct">1</span></div>
<div class="cell"><span class="lv"><span class="b b4"></span>S4</span><span class="ct">0</span></div>
</div>
<div class="filters">
<span class="chip active">All</span>
<span class="chip">S0</span>
<span class="chip">S1</span>
<span class="chip">S2</span>
<span class="chip">S3</span>
<span class="chip">S4</span>
<span class="count">6 of 6</span>
</div>
<div class="rows">
<div class="srow"><span class="id">SIG-031</span><span class="pr">WNO-017</span><span class="dot"><span class="b b3"></span>S3</span><p class="what">Two teams shipped public README sections labelled “brick: scope” after using the bot for a week.</p><span class="src">usage log · 2026-03-04</span></div>
<div class="srow"><span class="id">SIG-030</span><span class="pr">WNO-017</span><span class="dot"><span class="b b2"></span>S2</span><p class="what">Three engineers DMd asking for an export-to-Notion option.</p><span class="src">Slack · 2026-03-03</span></div>
<div class="srow"><span class="id">SIG-029</span><span class="pr">WNO-014</span><span class="dot"><span class="b b1"></span>S1</span><p class="what">Landing page: 34 visits, 7 emails, 0 returns in week 1.</p><span class="src">Plausible · 2026-03-01</span></div>
<div class="srow"><span class="id">SIG-028</span><span class="pr">WNO-021</span><span class="dot"><span class="b b2"></span>S2</span><p class="what">First triage call booked at listed price; second declined on price.</p><span class="src">Stripe / email · 2026-02-28</span></div>
<div class="srow"><span class="id">SIG-027</span><span class="pr">WNO-021</span><span class="dot"><span class="b b1"></span>S1</span><p class="what">“Interesting but Id want a free first one” ×2.</p><span class="src">interview · 2026-02-26</span></div>
<div class="srow"><span class="id">SIG-026</span><span class="pr">WNO-024</span><span class="dot"><span class="b b0"></span>S0</span><p class="what">Static preview: 12 visits in 30 days, 0 returns.</p><span class="src">Plausible · 2026-02-24</span></div>
</div>
</main>
</div>
</body>
</html>