Skip to content

docs(design-system): system of record, builder contract, reference page + raw-color scanner & ratchet baseline (#1430) - #1916

Merged
dolho merged 1 commit into
devfrom
docs/1430-design-system-v1
Jul 31, 2026
Merged

dolho merged 1 commit into
devfrom
docs/1430-design-system-v1

Conversation

@vybe

@vybe vybe commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Stands up the written layer of the frontend design system (#1430): the system of record, the condensed builder contract, the operator-approved visual reference, and the raw-color scanner with its ratchet baseline. From this PR on, docs/memory/design-system.md is the reference point for all frontend work — CLAUDE.md Rule of Engagement #10 makes loading the contract mandatory before touching src/frontend/.

What's in it

File Role
docs/memory/design-system.md System of record — token taxonomy, both-theme rules incl. the dark ink ladder (secondary gray-300 / tertiary gray-400 / gray-500 floor), type & spacing scales, 10-primitive catalog with exact token recipes, the data-loading motion standard (scanline beam + wipe reveal; first load animates, background refresh is invisible), and 28 UI Construction Principles
docs/memory/design-system-contract.md Condensed binding contract (≤150 lines) — load before any src/frontend/ change; includes a 12-item PR self-check
docs/memory/design-system-reference.html Approved visual spec — self-contained page, all component types, both themes, live scanline-motion demo
src/frontend/scripts/scan-raw-colors.mjs Raw-color scanner aligned with check-design-tokens.mjs token families
src/frontend/raw-color-baseline.json Ratchet seed measured at dev@5b28999 — per-file counts may only shrink
CLAUDE.md Rule of Engagement #10 + Memory Files row

Why now — the drift is live

Re-running the 2026-07-03 audit (recorded in #1430) at dev@5b28999:

  • Raw non-gray palette usages: ~685 → 753 (+9.9%), 48 → 50 files — raw color is being added faster than it's migrated
  • Hardcoded hex/rgb in .vue: 383 across 24 files (82% in MobileAdmin, FleetGrid, SetupPassword, ReplayTimeline)
  • Semantic-token usages grew too (~3,200 → 3,459) — the codebase is diverging in both directions at once; a ratchet stops exactly this
  • Worst offenders: views/Settings.vue (63), views/enterprise/Audit.vue (39), components/NavBar.vue (37), components/process/TemplateSelector.vue (33), components/settings/TwoFactorPanel.vue (32)

Deliberately NOT in this PR (engineering's side of #1430)

  • CI wiring of the scanner into frontend-build.yml as a failing ratchet check (this PR only seeds the baseline + tool)
  • Building the primitives (BaseButton/BaseInput/…) to match the reference page, and the migration batches
  • Dev-skills submodule follow-up: the .claude submodule's implementation playbooks (sprint/implement) should add a "load docs/memory/design-system-contract.md first" step for frontend tasks — that repo is separate from this PR

Refs #1430

🤖 Generated with Claude Code

…ge + raw-color scanner & ratchet baseline

Stands up the frontend design system's written layer per #1430:

- docs/memory/design-system.md — system of record: token taxonomy,
  both-theme rules incl. the dark ink ladder, type/spacing/radius scales,
  10-primitive catalog with exact token recipes, the data-loading motion
  standard (scanline beam + wipe reveal; first load animates, background
  refresh is invisible), and 28 UI Construction Principles
- docs/memory/design-system-contract.md — condensed binding contract to
  load before any src/frontend change
- docs/memory/design-system-reference.html — approved visual spec (self-
  contained; both themes; live motion demo)
- src/frontend/scripts/scan-raw-colors.mjs — raw-color scanner aligned
  with check-design-tokens.mjs token families
- src/frontend/raw-color-baseline.json — ratchet seed at dev@5b28999:
  753 raw non-gray / 383 hardcoded colors; counts may only shrink
- CLAUDE.md — Rule of Engagement #10 + Memory Files row making the
  design system the mandatory reference for frontend work

Refs #1430

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dolho

dolho commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

/review Report

Branch: docs/1430-design-system-v1dev (merge-base 5b289996)
Files: 6 (+2253/−0) — 3 docs + a reference HTML + a read-only scanner + its baseline
Scope: CLEAN — design-system system-of-record + builder contract + visual reference + raw-color scanner & baseline seed, per #1430.
CI: mergeable, green.

No critical findings. It's docs plus one read-only dev script — no backend, auth, SQL, or credentials in scope. I verified the two things that could actually be wrong: the scanner's correctness and whether the committed baseline is real.

Verified (with evidence)

  • The baseline is genuine scanner output, and the tool is deterministic. Running node scan-raw-colors.mjs src/frontend on the current tree reproduces the committed raw-color-baseline.json exactlyraw_nongray 753 · raw_gray 7446 · hardcoded 383 · semantic 3459. So it's not hand-edited or stale; it's a reproducible snapshot at merge-base 5b289996 (the commit stamped in the baseline).
  • The semantic-token exclusion is correct. RAW_RE's (?<![\w-]) lookbehind means a palette word that tails a semantic token can't match: bg-accent-purple-500accent matches UTIL, purple matches a family, but purple is --preceded so the lookbehind rejects it. Traced by hand and it holds; genuine bg-purple-500 still counts.
  • No injection/exfil surface. The scanner has no eval/new Function/dynamic import; its one shell call is a fixed git rev-parse HEAD in a try/catch (only under --baseline). The reference HTML is fully self-contained — one inline animation demo, no external src/href, no fetch/localStorage/eval (the lone "fetch" grep hit is the word in prose). Since it's a static docs file (opened directly, not served by the app, no user input), XSS surface is nil.

Informational

[I1] The "ratchet" is measurement-only — there is no comparison/enforcement path (Confidence: 8/10)
The script's own header is honest: "Exit code is always 0 — this is a measurement tool; the future CI ratchet compares totals against the committed baseline." Its two modes are --baseline (WRITE a baseline) and --json/default (PRINT totals). There is no mode that reads the committed baseline and fails on an increase, and nothing in .github/workflows or package.json runs it (confirmed — neither is touched).

But CLAUDE.md states it as an active invariant: "Raw-color usage is ratcheted: node …scan… measures against …baseline.json — per-file counts may only shrink." A reader will run the command expecting a pass/fail and get a totals dump instead — the command as written doesn't compare against the baseline at all. Suggest one of:

  • soften the CLAUDE.md wording to "will be ratcheted (enforcement follow-up)", or
  • add the comparison the sentence implies — a --check mode that loads the baseline, diffs per-file, and exits non-zero on any increase — plus a CI job. The per-file data is already emitted under --json, so this is small.

Not blocking (v1 seed is a legitimate scope), but the doc currently promises enforcement the tooling doesn't provide.

[I2] Two hand-maintained lists must track tailwind.config.js (Confidence: 6/10)
PALETTE_FAMILIES and SEMANTIC_TOKENS are duplicated from the token config. Drift is low-impact — a new semantic family that's missing here is only under-counted (it's not a palette word, so it can't become a false raw violation) — but worth a comment pointing at tailwind.config.js/check-design-tokens.mjs as the source so the next token family gets mirrored.

[I3] Baseline path prefix is hardcoded (Confidence: 6/10)
baselineFiles['src/frontend/src/' + rel] assumes the scan runs against src/frontend; run elsewhere and the baseline keys are wrong. Fine for the documented usage, just coupling to note.

Clean categories

SQL / auth / credentials / concurrency — N/A (no backend; read-only script). Frontend/XSS — the HTML is static, self-contained, no user input. Docs staleness — this PR is the docs; CLAUDE.md gains rule #10 + a Memory-Files row, both coherent (modulo I1's wording).

Critical: 0 · Informational: 3 · Scope: clean. LGTM as a v1 seed; the one thing I'd change before merge is I1 — either the CLAUDE.md wording or a real --check mode, so "is ratcheted / may only shrink" isn't a promise the command can't keep.

@dolho
dolho enabled auto-merge July 31, 2026 12:26
@dolho
dolho merged commit a4eac44 into dev Jul 31, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants