Skip to content

Plan — phased execution

State: open/active · Genre: plan

Phases are ordered by leverage. Phase 1 items are independent, small, and individually PR-able. Later phases depend on Phase 0’s law being in place. Drift numbers reference SURVEY.md §3.

  • Rewrite packages/ts/ui/docs/design-system.md in place to match shipped tokens.css: both tiers, all 94 tokens, the 25-token contract, five themes, all axes, bridge direction --ui-* ← --d-* (drift 1, 15).
  • Mint D-DLNG-design-language recording identity, the four planes, and the six laws (PROPOSAL.md §4).
  • Mint S-0010-design-language-consumption — applies_to the live app/product rings; names the allowed escape hatches (frozen apps, Obsidian plugin, shell-less static surfaces).
  • Answer PROPOSAL.md §6 open questions and record the answers in D-DLNG.

Phase 1 — Close the wiring gaps (inside the system)

Section titled “Phase 1 — Close the wiring gaps (inside the system)”
  • shell.css: body font becomes var(--d-font-sans); size becomes var(--d-density-font); delete the hard-coded stack (drift 2, 3).
  • Define or fix the four undefined token references: add --d-status-danger as an alias of --d-status-error (or fix call sites), and resolve --d-bg-secondary / --d-bg-primary / --d-border-primary in the agent-pants experience (drift 4).
  • Retire the shell.css alias vocabulary; migrate the 12 call sites to --d-* (drift 5).
  • Icon policy: replace the 2 shipped heroicons uses (DSidebar, app-frame layout theme toggle); add @iconify-json/lucide to @determined/ui’s own manifest; sweep stories (drift 9).
  • Graph experience: theme from useDTheme() instead of matchMedia; stop stamping data-theme="light|dark" (rename the attribute or pass the prop) (drift 6, 7).
  • json-canvas-vue + obsidian-md + panes: document the --d-* bridge as the canonical theming path in-shell; leave standalone fallbacks (drift 6).
  • suspenders product: add @determined/ui to its extends (drift 12).
  • dataVizPalette: either derive from the active theme (accent-anchored, per the dataviz projection below) or delete it until needed; reconcile with pumice’s sibling when pumice adopts (drift 8).
  • Update app.config.ts comment/values and explorations.css idiom to the post-bridge world (drift 10).
  • Record the Windows radius/density detachment as intended or fix it (drift 14).
  • The layer declares no ssr. Rendering mode is the app’s decision, so a consumer that states no ssr of its own is no longer flipped to SPA by the layer merge.
  • The layer stops imposing itself on consumers: its stories and tests no longer land in a consumer’s type program, and it no longer pushes its own CSS at one.
  • @determined/ui has an exports map: named subpaths for the config, semantics, components/*, composables/* and css/*. It ends with a "./*": "./*" catch-all, so deep imports still resolve rather than failing — the codebase currently uses none. The map documents the intended surface; it does not yet enforce it. T-XIFP-design-language-ui-subpath-exports.
  • Generalize vault-hue → product-hue: a product declares a hue and its chrome takes the tint, the way a focused vault does. The identity family is --d-hue and its siblings; the vault tokens remain as aliases.
  • Theme-authoring guide: how a solution registers a preset, with the sdf recipe written down as the public path.
  • The theme set: platinum-ii, instrument and carbide become built-ins, joining the existing presets — eight themes in the picker.
  • Rail appearance axis — flat, washed, chassis — with a rail row in the lab’s Live Controls.
  • Status grounds: --d-status-*-wash and --d-status-*-edge, so a callout or an error strip has a themed ground and not a fixed pale hex. The absence of these is what stranded an adopting app in light mode.
  • Platinum refinement pass — the “modern update” against the OmniGraffle stance. Platinum II is the modern update and is now the default, which the layer expresses by absence: the :root and .dark seeds carry its values. Platinum keeps its own complete seed blocks and becomes an opt-in preset, the classic. Validated against the screenshot corpus, recaptured in place so the diff is the before and after. One seam is unverified: the sunken main pane in dark renders only in the app-frame shell, so it is checked by the cascade test and has never been seen.
  • The UButton soft/ghost boundary is drawn as an explicit written allowance in the spec, not as a new covering DButton intent (drift 13). At a call site variant="ghost" and neutral variant="soft" are violations; a non-neutral status colour combined with soft or ghost is the one allowance. Recorded as debt to withdraw when DButton grows an emphasis axis.
  • One styling idiom per layer, written down (drift 11): the ui layer uses Tailwind arbitrary-value token utilities, app-frame uses BEM with scoped CSS reading var(--d-*). Code moved between layers is restyled to the destination idiom in the same change, so a move is deliberate.

Phase 3 — Adoption, ring by ring (live surfaces only)

Section titled “Phase 3 — Adoption, ring by ring (live surfaces only)”

Order: stack-closest first. Each adoption is the same mechanical recipe: extend @determined/ui → the --ui-* ← --d-* bridge restyles stock U* components for free → replace raw palette literals with tokens/D* opportunistically.

  • apps/zoo: upgrade Nuxt UI v3 → v4, extend the layer.
  • apps/agentpants: extends the layer; dead theme.css deleted, useTheme collapsed into useDTheme. Its palette-class debt burns down separately under T-APNC-design-language-agentpants-palette-burndown; run bun scripts/guard-raw-palette.ts --counts for the current figure.
  • apps/pumice: extends the layer.
  • solutions/augmented/learn_web + vimit_prototype.
  • solutions/augmented/apps/augmented_web: bespoke variables.css rewritten as a one-way alias bridge onto the layer, then its 964 hex literals burned down to --d-* and the colour-mode preference flipped to 'system' (T-AM3S-design-language-augmented-web-hex-burndown). Largest single migration in the ring.

The ring is closed: every live surface extends the layer. augmented_web has now been looked at in both modes, once a toolchain pin made it build again, and the two defects that first look found are fixed. agentpants still carries its palette-class debt.

  • pumice palette classes and dark: variants burned down to 7 survivors (from 1051). Functional colours at enforce(0). The inverted chips moved onto the layer’s new --d-bg-inverted / --d-text-inverted pair, and the pomodoro pips onto --p-phase-*, pumice’s own phase projection. The 7 left are domain amber: the rating-star ladder owned by uiSemantics’ ratingAccent, and the streak counter, held raw so a streak is not given --d-status-warning’s meaning. T-APNC-design-language-agentpants-palette-burndown covers agentpants debt; the guard baseline is the count’s source of truth.
  • Version convergence rides along: Nuxt UI ~4.10, vue-router 5, bun everywhere (ontological-legacy exempt as frozen donor). Queued: T-JDUB-design-language-version-convergence. Partly done: Nuxt UI ~4.10 and vue-router 5 shipped. Every app now pins the layer’s ~4.10.0, and zoo and pumice pin bun to 1.4.2. augmented_web and learn_web do not yet declare bun in package.json. A repo-level guard holds the Nuxt UI and vue-router lines.

Phase 4 — Projections (the family face beyond Nuxt)

Section titled “Phase 4 — Projections (the family face beyond Nuxt)”
  • Starlight skin: a customCss file projects the default seed tokens (light + dark, not a named theme) onto sites/df-docs and the library doc sites, through the site-template seam (D-0010). T-DUEF-design-language-starlight-skin.
  • Report templates (eta review reports) render with a palette projected from the default seed tokens. T-J8MT-design-language-report-palette.
  • Legacy INDEX_HTML dashboard: dies with D-0018; no investment.
  • Marketing/static (augmented_dot_com): optional, lowest priority — a small tokens CSS if/when touched.
  • Data-viz projection: a generated categorical/ramp palette per theme (feeds dataVizPalette, echarts themes, graph-canvas palettes). Queued: T-B48W-design-language-dataviz-projection. Partly done: the per-theme categorical and ramp tokens ship, useVizPalette() reads them, graph-canvas derives its palette from them, and pumice’s local dataVizPalette is gone. No echarts theme is generated yet — one pumice chart calls the composable directly, and the polish experience’s three charts still map colours by hand.
  • Every visual change verified in-browser with the existing screenshot convention (<area>-<state>-<light|dark>.png); the lab page and Storybook are the living reference.
  • Every PR that changes pixels carries before/after screenshot pairs (light + dark) in its description, captured from the affected surface. Docs-only PRs are exempt. The repo is private, so raw.githubusercontent.com URLs neither render nor open in PR bodies — reference committed screenshots as github.com/…/blob/<branch>/<path> links, lean on the Files-changed rich image diffs (update committed screenshots in place so the diff IS the before/after), and use web-editor attachment uploads for inline images.
  • The visual pass is a standing step on any change that moves colour, not a one-off. A static check cannot see a semantic colour error: the token resolves, nothing is undefined, the suite is green, and the colour is still wrong. Three classes of defect have been caught only by looking. Ink tokens painted as background fills — --d-text-muted and --d-text-secondary hold near-identical values in both modes, so they read opposite ways against opposite grounds, and a secondary button that receded in light became the loudest thing on screen in dark. Decorative tints mapped onto semantic status tokens — cards tinted only to tell two rows apart landed on --d-status-warning-wash, so a folder card claimed to be warning about something and rendered brown on a dark ground. And an accent hardcoded to one value in both themes, beside three routes rendering their list below the fold so the pane painted empty.
  • A capture driver per ring. zoo, pumice and agentpants carry capture-appearance.e2e.ts; augmented_web carries capture-adoption.e2e.ts. pumice works and covers multiple areas with light/dark variants. zoo and augmented_web have stale corpora — environmental colour drift means neither can show a genuine design change.
  • scripts/guard-raw-palette.ts — repo tooling, per root CLAUDE.md, not an solutions/ontological gate. It carries all four shapes the task named (hex, keyword, functional-colour, palette-class) plus undeclared-token, and runs on a per-ring ratchet baseline; run it with --counts for the current ring and file totals. Token composition such as oklch(… var(--d-hue)) is not flagged. T-J04U-design-language-no-raw-palette-check.
  • bun install --frozen-lockfile succeeds in zoo, pumice and agentpants. Each is still its own bun workspace root with its own lockfile, so the failure mode can return the next time a manifest moves without its lockfile; the lockfiles are currently in step with their manifests.
  • root:check and root:test declare the inputs they actually read, so the affected-task query covers a change confined to solutions/ontological. The blind spot was task-level selection only — GitHub’s ci.yml selects by PROJECT, and root’s source is ., so CI always covered that tree; just ci and hand-typed moon run --affected did not. solutions/ontological still declares no check/test task of its own, which is why the root tasks have to carry it.
  • LIBRARIES.md entry for @determined/ui names it the design-language home (D-DLNG-design-language).

← Back to Notes