docs(@projects/@magic-civilization): 🏷️ file p2-87 — single game-wide colour system / source of truth
Strategic umbrella over p2-73 (pipeline) + p2-74 (de-hardcode): unify all colour onto design-tokens.json as the single source of truth, with layered primitive→semantic→component aliasing (value-preserving), and every consumer (Godot UI, web guide fantasy-theme.ts, accessibility palettes.json, game-content terrain/minimap colour arrays) deriving from it instead of carrying its own. Captures the 4-source fragmentation audit, the tiering architecture, an 8-cluster plan (clusters 1–2 = the in-flight B work, already partly landed), and the rule that aliasing must never change rendered colour. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e1c26bded2
commit
4dd6bc4fa9
1 changed files with 81 additions and 0 deletions
81
.project/objectives/p2-87-single-color-system-sot.md
Normal file
81
.project/objectives/p2-87-single-color-system-sot.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
id: p2-87-single-color-system-sot
|
||||
title: "Single game-wide colour system — one source of truth, layered tokens, every consumer derives from it"
|
||||
priority: p2
|
||||
status: partial
|
||||
scope: game1
|
||||
category: architecture
|
||||
owner: wireguard
|
||||
created: 2026-06-18
|
||||
updated_at: 2026-06-18
|
||||
relates_to: [p2-73-ui-theme-token-pipeline, p2-74-ui-dehardcode-to-tokens]
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
ONE colour system for the whole game, with **`.project/designs/design-tokens.json` as the single source of truth**. Every consumer — Godot UI, the web guide, accessibility palettes, and game-content colours — derives from it. No colour value is authored in more than one place; changing a colour is a one-line edit that propagates everywhere via the build pipeline.
|
||||
|
||||
## Why (fragmentation audit, 2026-06-18)
|
||||
|
||||
Colour is currently defined in **four disjoint places** (verified):
|
||||
|
||||
1. **UI design tokens** — `.project/designs/design-tokens.json` → `tools/build-ui-theme.py` → `public/games/age-of-dwarves/ui_theme.tres`, consumed via `ThemeAssets.color()` + Godot theme inheritance. (The system p2-73/p2-74 built and B is maturing.)
|
||||
2. **Accessibility palettes** — `public/games/age-of-dwarves/data/palettes.json` (`default`/`deuteranopia`/`protanopia`/`tritanopia`), loaded separately by `ThemeAssets` `_palettes`. Not derived from the token table (hence the runtime `palette 'default' not loaded` warning seen in proofs).
|
||||
3. **Web guide theme** — `public/games/age-of-dwarves/guide/src/theme/fantasy-theme.ts` carries **~20 raw hex literals**, independent of the tokens. The guide and the game can drift apart.
|
||||
4. **Game-content colours** — `public/games/age-of-dwarves/data/terrain/*.json` `"color":[r,g,b]` arrays, `races.json`, etc., PLUS the `scenes/hud/minimap.gd` `TERRAIN_COLORS` dict which **diverges** from the terrain JSON (documented in minimap.gd: "diverge by 10-70/channel"). Two definitions of terrain colour.
|
||||
|
||||
design-tokens.json's own `$metadata.sources` already *names* ui_theme.tres + fantasy-theme.ts + palettes.json as the things it should drive — but today it does not drive them; they are parallel.
|
||||
|
||||
## Architecture (the target)
|
||||
|
||||
Three-tier W3C design tokens, higher tiers ALIAS lower ones (a colour lives once):
|
||||
|
||||
```
|
||||
primitive palette.green = #33b333e6 ← raw hue/shade, the only literal hexes
|
||||
semantic semantic.positive = {palette.green...} role-based
|
||||
component tech.researchedBg = {semantic.positive} OR {palette.x} never its own hex
|
||||
```
|
||||
|
||||
- **Aliasing is strictly value-preserving.** Tiering must never change rendered colour. Unifying two colours that were historically different (e.g. "is researched-green the same as success-green?") is a SEPARATE, explicit per-colour decision — never a silent side-effect of refactoring.
|
||||
- The build pipeline (`build-ui-theme.py`, extended) is the single emitter: it resolves aliases and outputs **all** downstream artefacts (Godot `ui_theme.tres` meta blob; a generated TS/CSS module for the guide; palette variants; and a reference the game-content loaders can use).
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [~] **Alias resolution in the pipeline** — `build-ui-theme.py` resolves `{color.x.y}` references (cycle + dangling detection), transparent for literals. _Done: commit `05efbebfd`._
|
||||
- [~] **Layered tiers exist** — primitive `palette.*` tier introduced; `tech.*` component tokens are aliases (value-preserving, pixel-identical). _Done: `a8476c395`._
|
||||
- [ ] **All component token groups tiered** — `throne.*`, `unlockAccent.*`, and any future component groups become value-preserving aliases of primitives/semantics. (B cluster-2.)
|
||||
- [ ] **Semantic tier references primitives** — `semantic.*`/`text.*`/`background.*`/`accent.*` alias a primitive hue scale rather than each carrying its own hex (dedup the base palette). Value-preserving.
|
||||
- [ ] **Accessibility palettes unified** — `palettes.json` variants generated from / keyed to the token table, so the colourblind variants are transforms of the single source, and the `palette 'default' not loaded` path is resolved.
|
||||
- [ ] **Web guide derives from tokens** — `build-ui-theme.py` (or a sibling) emits a generated TS/CSS colour module; `fantasy-theme.ts`'s ~20 raw hexes are replaced by references to it. Guide + game can no longer drift. Guide build green.
|
||||
- [ ] **Game-content colours reconciled** — terrain/race/biome colour arrays and `minimap.gd TERRAIN_COLORS` resolve to ONE definition (either content JSON is the source and minimap reads it, or both derive from tokens). No two diverging terrain palettes.
|
||||
- [ ] **Override → inheritance** — the ~314 `add_theme_*_override` + ~27 inline `StyleBoxFlat.new()` across scenes collapse into Godot Theme type-variations so widgets inherit; `ThemeAssets.color()` remains only for genuinely dynamic/computed colours. (B cluster-3; the bulk of "used everywhere it should be.")
|
||||
- [ ] **Coverage gate** — a check (script/test) asserts no raw `Color(r,g,b,...)` literals in scene scripts except sanctioned carve-outs (computed/dynamic), and no raw hex in the guide theme. Wired so regressions are caught.
|
||||
- [ ] **Visual-regression proof** — per-cluster headed render proofs on plum (warm cache — safe per [[feedback_no_godot_import_on_plum]] 2026-06-18 update) confirm zero unintended colour change.
|
||||
|
||||
## Plan (clusters)
|
||||
|
||||
- **cluster-1** ✅ alias pipeline + tier `tech.*` (value-preserving). `05efbebfd`, `a8476c395`.
|
||||
- **cluster-2** tier `throne.*` + `unlockAccent.*` (value-preserving aliases).
|
||||
- **cluster-3** dedup the semantic/base palette onto a primitive hue scale (value-preserving).
|
||||
- **cluster-4** web guide: emit generated colour module, de-hex `fantasy-theme.ts`.
|
||||
- **cluster-5** accessibility palettes unified to the token source.
|
||||
- **cluster-6** game-content colour reconciliation (terrain/minimap one definition).
|
||||
- **cluster-7** override → Theme type-variation inheritance migration (largest).
|
||||
- **cluster-8** coverage gate + final visual-regression sweep.
|
||||
|
||||
## Rails
|
||||
|
||||
- Single source of truth = `design-tokens.json`. Generated artefacts (`ui_theme.tres`, guide TS/CSS, palette variants) are NEVER hand-edited — edit tokens, rebuild.
|
||||
- Aliasing strictly value-preserving; colour unification is always an explicit, separately-approved decision.
|
||||
- Presentation-only (Rail 3): no gameplay/logic change.
|
||||
|
||||
## Verification host
|
||||
|
||||
Headed render proofs run on **plum** against the warm import cache (safe; the kernel-panic risk is mass image `--import` only — see [[feedback_no_godot_import_on_plum]]). `tools/build-ui-theme.py --check`, `python3` JSON validation, and `gdlint` are all laptop-safe.
|
||||
|
||||
## References
|
||||
|
||||
- `tools/build-ui-theme.py` — the single emitter (alias resolver added).
|
||||
- `.project/designs/design-tokens.json` — the source of truth.
|
||||
- `.project/designs/UI_DESIGN_SYSTEM.md` — design-system doc.
|
||||
- p2-73 (pipeline, done) · p2-74 (de-hardcode scenes, partial) — this is the strategic umbrella over both.
|
||||
Loading…
Add table
Reference in a new issue