DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/cr-2026-126-color-tokenization-v0_1.md

Loomworks change request — Repo-wide color tokenization (every raw color in src/ → token; white + shadow as swappable tokens; the template-clean color guard goes repo-wide) — CR-2026-126 — v0.1

Version. 0.1 Date. 2026-06-26 Status. Change request — the repo-wide color sweep that follows the Companion-surface Phase 1 CR (CR-2026-125). Drafted from the inventory loomworks-css-tokenization-inventory-v0_1.md and governed by the standing note loomworks-standing-note-no-hardcoded-css-v0_1 (no hardcoded CSS; tokens are the tunable surface; toward a theme editor). Targets the loomworks frontend, main (base confirmed at Step 0). Markdown primary (technical consumer: Claude Code). Halt-before-push; per-step (per-surface) commits with Vitest green at each; explicit-path staging (never git add -A); per-push explicit Operator authorization.

Hard dependency. This CR must be built after CR-2026-125 is merged. CR-125 adds the two off-palette tokens this sweep reuses (--color-vellum-soft for #F0EADB; a gold token for rgba(181,140,40,0.10)) and tokenizes TopBar (excluded here). Step 0 confirms CR-125 is merged and those two tokens exist before any surface is converted. If CR-125 is not merged, halt at Step 0.

CR number caveat (drift-surface). Numbered CR-2026-126 assuming next free after 125. Step 0 confirms and renames if taken.

What this is, in one line. CR-125 cleaned one component (TopBar) and added the two new tokens the repo needs; this sweeps every other component's raw colors to tokens, so the repo has zero raw color outside tokens.css — the clean foundation a theme editor requires.

Decisions this CR rests on (settled; do not relitigate):

  1. Color tokenization is whole-repo, now (standing note). Every raw color in component files becomes a token.
  2. Distinct colors stay distinct tokens (standing note §3). No consolidation of near-duplicates; tunability preserved.
  3. White and shadow become swappable tokens (Operator, settled). #FFFFFF--color-white; rgba(0,0,0,0.28) → a shadow/scrim token. Not left as framework built-ins — a custom Companion may want a warm-white or a softer shadow.
  4. Typography/spacing is NOT in this CR (standing note §4, deferred). The 16 arbitrary font sizes and arbitrary-px spacing are named debt for a later design CR. This CR is color only.
  5. Static inline styles vs. computed are distinguished (inventory §2). A style={{}} carrying a literal color is tokenized; a style={{}} carrying a computed value (a state-driven width, a voice-waveform height, a transform) is left — a blanket "no style={{}}" rule would be wrong.

Source grounding. The inventory (loomworks-css-tokenization-inventory-v0_1.md, read-only on bafdb07) enumerated every raw color: ~59 occurrences across 13 files, 8 distinct base colors, of which 6 are existing tokens used at alpha (press-ink, iron-oxide, cartridge), plus the 2 off-palette one-offs CR-125 tokenizes, plus white and shadow. Re-confirmed at Step 0.


Plain-language summary

CR-2026-125 cleaned the top bar and added the two new paint cans the whole app needed. This finishes the job: every other screen's hardcoded colors get their paint-can labels too, so nothing in the app paints with a raw color anymore — it all refers to named tokens. After this, swapping the tokens re-skins the entire interface, which is exactly what a future theme editor needs.

The work is small and regular despite touching many files: there are only 8 distinct colors in the whole repo, and most are your existing colors used at reduced opacity (the "press-ink at 14%" kind of thing), which convert mechanically. Two are the off-palette shades CR-125 already turned into tokens (so this sweep just uses them). White and the one shadow become tokens too, so a custom Companion can tune them.

It is done carefully, one screen at a time — each screen's colors converted in its own commit, and each screen verified to look identical afterward — because the only risk in a color sweep is a token not exactly matching the color it replaced. Type sizes and spacing are not in this CR; that's a separate, later design job.


1. Scope

In scope.

Out of scope.


2. Step 0 — confirm dependency + re-ground the inventory (read-only)

  1. Dependency (decisive). Confirm CR-2026-125 is merged and --color-vellum-soft + the gold token exist in tokens.css. If not merged, halt.
  2. CR number + branch base + Vitest baseline + versions — confirm next free number; the live main SHA; the suite baseline; framework versions.
  3. Re-confirm the inventory against live main (it may have moved): the per-file raw-color counts, the 8 distinct base colors, and that the only off-palette one-offs are the two CR-125 tokenized. Report any new raw color introduced since bafdb07.
  4. Confirm the alpha-modifier convention (bg-press-ink/40 etc. already in repo) so press-ink/14, /28, /58, iron-oxide/10, cartridge/88 convert via Tailwind modifiers, not new tokens.
  5. Confirm white + shadow homes — add --color-white and a shadow token; confirm the shadow's exact use (scrim/overlay vs box-shadow) so the token is named right.
  6. Classify the inline style={{}} occurrences per file: which carry literal colors (tokenize) vs. computed values (leave). Report the split so the per-surface commits know what to touch.
  7. Confirm the guard extension — the CR-125 color guard goes repo-wide; confirm it scans all .tsx for hex/rgba(, excludes tokens.css/globals.css, and (after this sweep) needs no dirty-file allowlist.

Step 0 halt conditions. Halt if CR-125 isn't merged; if a raw color exists that maps to no token and is not one of the known off-palette two (a new off-palette shade would need an Operator token decision, like CR-125's); or if the inline-style classification is ambiguous for a given occurrence.

Step 0 archival commit. Archive this CR as branch base; record baseline. Do not push.


3. Steps (each a per-surface commit; Vitest green + render-unchanged at each; halt before push)

Branch: cr-2026-126-color-tokenization off the confirmed base. The sweep is sliced by surface (inventory §6) so each commit is small and independently verifiable. Each surface commit: convert its raw colors → tokens, run Vitest, and verify the surface renders identically (snapshot/class assertions + a noted visual check). The token additions (white, shadow) land in the first commit that needs them.

Step 1 — Token additions (one commit)

Add --color-white and the shadow/scrim token to tokens.css (and wire into Tailwind via globals.css if the convention requires). No component changes yet. Confirm the two CR-125 tokens (vellum-soft, gold) are present (merged). Vitest green (no behavior change).

Commit: CR-2026-126 step 1: add --color-white + shadow token to tokens.css. Do not push.

Step 2 — engagement-navigation surface (one commit)

Convert raw colors in the picker surface (inventory: PersonalSection, WorkspacesSection, CrossCuttingSection, EngagementList, VoiceListeningPanel, page.tsxnot TopBar, done by CR-125). Existing-token-at-alpha conversions and the reused CR-125 tokens; static inline-style colors tokenized; computed styles left. Verify the picker renders identically. Vitest green.

Commit: CR-2026-126 step 2: tokenize colors — engagement-navigation surface. Do not push.

Step 3 — in-engagement surface (one commit)

Convert CenterPane, RightRail, LeftRail, InEngagementSkeleton, NotFoundPanel. Same rules. Verify the in-engagement surface renders identically (it shares the color set and uses TopBar, already clean). Vitest green.

Commit: CR-2026-126 step 3: tokenize colors — in-engagement surface. Do not push.

Step 4 — chat + nav + misc components (one commit)

Convert the lighter files: components/chat/{ChatView,ChatTurn,DraftSpecification}, components/nav/UserMenu, components/workspaces/WorkspaceSelector, components/saved-filters/SavedFilterList. Verify each renders identically. Vitest green.

Commit: CR-2026-126 step 4: tokenize colors — chat, nav, and misc components. Do not push.

Step 5 — Repo-wide color guard (one commit)

Extend the template-clean color guard (from CR-125) to repo-wide: scan all .tsx under src/ for raw hex / rgba(, excluding tokens.css/globals.css. Remove any dirty-file allowlist (none should remain — the sweep cleaned them). The guard now passes because Steps 1–4 + CR-125's TopBar left zero raw color in components.

Tests. The guard runs green repo-wide. A deliberate temporary raw-color insertion (then removed) confirms the guard fails on a violation — proving it has teeth.

Commit: CR-2026-126 step 5: color guard goes repo-wide (zero raw color outside tokens.css). Do not push.

Step 6 — Full suite + render-parity verification (no commit)

Run the full Vitest suite (green). Verify every converted surface renders identically to pre-sweep — the engagement-navigation picker, the in-engagement surface, chat, nav. Confirm: zero raw color in components (guard green), the two CR-125 tokens + white + shadow are the only token additions across both CRs, no computed inline style was touched, no layout/behavior changed.

Halt and report. Verification-only — no commit.


4. What must not happen


5. Halt and report

After Step 6, halt before any push. Report: the dependency confirmation (CR-125 merged; vellum-soft + gold present); the token additions (white, shadow) and confirmation no other new tokens were needed; per-surface conversion results with render-parity confirmation for each; the inline-style classification (which tokenized, which left as computed); the repo-wide guard (green, teeth-tested); the full Vitest counts; and confirmation of zero raw color outside tokens.css. On the Operator's review and explicit authorisation, push CR-2026-126. After this, the repo's color is fully tokenized and swappable — the foundation for a theme editor's color knobs. Typography/spacing remains named debt for a later design CR.


6. Reversibility

Six commits (one token-add, four per-surface, one guard), each independently revertible to a green suite. Each surface commit is a self-contained color substitution verified render-identical, so a revert restores that surface's prior appearance exactly. The guard (Step 5) is additive. No Engine, schema, layout, or behavior change — color-to-token only.


DUNIN7 — Done In Seven LLC — Miami, Florida Repo-wide color tokenization — change request — CR-2026-126 — v0.1 — 2026-06-26