Files

173 lines
11 KiB
Markdown
Raw Permalink 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.
---
phase: 01-design-tokens-rams-foundation
plan: 04
type: execute
wave: 4
depends_on: ["01-02", "01-03"]
files_modified:
- theme/scripts/audit.mjs
- theme/scripts/screenshot.mjs
- theme/gallery.html
- theme/package.json
- package.json
autonomous: false
requirements: [DSGN-02]
user_setup: []
must_haves:
decisions: [D-12, D-13, D-14]
truths:
- "The automated audit sweep scans the built CSS and flags every color/spacing/typography/radius value not in the token set — zero off-token values is evidence, not an eyeball claim (D-13)"
- "A static side-by-side gallery page renders implementation components against all four mockup screens' rendered output (D-12)"
- "Gallery captures are produced by a committed Playwright real-browser screenshot script (D-14)"
- "User has viewed the gallery and basemap preview and explicitly approved (DSGN-02 approval artifact)"
artifacts:
- path: "theme/scripts/audit.mjs"
provides: "Automated off-token audit (D-13): parses tokens.css allowlist, scans built dist CSS"
- path: "theme/scripts/screenshot.mjs"
provides: "Playwright capture script committed for reuse by later UI phases (D-14)"
- path: "theme/gallery.html"
provides: "DSGN-02 mockup-vs-implementation gallery — same pattern every later UI phase extends (D-12)"
min_lines: 80
- path: "theme/package.json"
provides: "Wires `audit` and `capture` scripts"
contains: "audit"
key_links:
- from: "theme/scripts/audit.mjs"
to: "theme/src/tokens.css"
via: "parse @theme/`:root` token values as the allowlist"
pattern: "tokens\\.css"
- from: "theme/scripts/audit.mjs"
to: "theme/dist/rams.css"
via: "scan built CSS for off-token literals; exit 1 on any"
pattern: "rams\\.css"
- from: "theme/scripts/screenshot.mjs"
to: "theme/screenshots/"
via: "Playwright chromium captures of sheet.html, 4 mockups, basemap preview"
pattern: "screenshots"
- from: "theme/gallery.html"
to: "theme/screenshots/*"
via: "<img> side-by-side comparison rows"
pattern: "screenshots/"
---
<objective>
Prove token fidelity by script and by the user's eyes: wire the automated off-token audit (D-13 — "zero off-token values" becomes evidence, not an assertion), build the Playwright capture toolchain (D-14), assemble the side-by-side mockup-vs-implementation gallery (D-12), and run the DSGN-02 approval checkpoint — the fidelity-bar gate every later UI phase reuses.
Purpose: DSGN-02's approval-artifact mechanism is born here; no product screen (Phase 2+) is built before the user approves this gallery.
Output: audit script + capture script + gallery page + approved DSGN-02 record.
</objective>
<execution_context>
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
@$HOME/.config/opencode/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/ROADMAP.md
@.planning/phases/01-design-tokens-rams-foundation/01-CONTEXT.md
<interfaces>
From plan 01-01: `theme/src/tokens.css` (@theme colors/spacing/fonts + `:root` `--type-*` entries), `theme/dist/rams.css` via `npm run build --workspace theme`. Root package.json already defines workspace delegates `build`, `sheet`, `gallery`, `audit`, `capture` (created in 01-01).
From plan 01-02: `theme/src/sheet.html` renders all 7 mockup-derived component families; `theme/src/components.css` uses only `var(--*)` references.
From plan 01-03: `theme/basemap/index.html` renders the Rams Liberty fork over KL (basemap at `theme/basemap/liberty-rams.json`).
Mockups: `stitch_minimalist_route_navigator/<screen>/code.html` (CDN Tailwind — needs network) with committed `screen.png` fallbacks per screen; read-only per D-06 — screenshot them via `file://`, never edit.
</interfaces>
</context>
<tasks>
<task type="auto" tdd="true">
<name>task 1: Off-token audit script (D-13)</name>
<files>theme/scripts/audit.mjs, theme/package.json</files>
<behavior>
- Test: a scratch stylesheet using ONLY token values → audit exits 0
- Test: a scratch stylesheet containing `color: #00ff00; border-radius: 12px; font-family: Arial; box-shadow: ...` → audit exits 1 and lists each offending declaration file:line
- Test: audit of `theme/dist/rams.css` (real build from the sheet) → exit 0
</behavior>
<action>
1. `theme/scripts/audit.mjs` — Node ESM, zero runtime deps:
a. Parse `theme/src/tokens.css` to extract the allowlist: `--color-*` hex values, `--spacing-*` values, `--type-*` names/families, `--radius-*` (must all be 0). Fail loud (exit 2) with a clear message if tokens.css parses to < 40 color tokens (drift guard).
b. Scan inputs (default `theme/dist/rams.css`; accept extra file args): flag any `#hex` literal not in the allowlist, any `font-family:` not in {Geist, Space Grotesk, ui-monospace/system fallbacks from tokens}, any `border-radius` other than 0, any `box-shadow:` or `filter: blur` / `backdrop-filter` presence (Rams Shapes: no shadows/blur/glass).
c. Print each violation as `file:line: declaration`. Exit 1 if any, 0 if none.
2. Wire in `theme/package.json`: `"audit": "node ./scripts/audit.mjs ./dist/rams.css"`. Root `audit` delegate already exists — verify it resolves.
Grep-gate hygiene: use exit-code based verification, never `grep -c X == 0` over unfiltered files.
</action>
<verify>
<automated>npm run build --workspace theme && npm run audit && echo AUDIT-CLEAN</automated>
</verify>
<done>Audit REJECTS an injected off-token stylesheet (proven during TDD RED) and passes clean against the real sheet build (DSGN-01 evidence, automated per D-13)</done>
</task>
<task type="auto">
<name>task 2: Playwright capture script + gallery page (D-14, D-12)</name>
<files>theme/scripts/screenshot.mjs, theme/gallery.html, theme/package.json, .gitignore</files>
<action>
1. `npm i playwright --workspace theme` + `npx playwright install chromium` (playwright dep already declared in 01-01's theme/package.json).
2. `theme/scripts/screenshot.mjs` (wired as root+theme `capture` script):
- Serve `theme/` via its own tiny static server (node http) so `./dist/rams.css` resolves; capture `theme/src/sheet.html` → `theme/screenshots/sheet-full.png` (390 viewport, fullPage).
- Capture each of the 4 mockups via `file://` with network enabled, viewport 390×844, wait networkidle + 800ms settle → `theme/screenshots/mockup-<screen>.png`. If a mockup shot fails (CDN hiccup), fall back to tracking that screen's committed `screen.png` in the gallery instead — never edit mockups (D-06).
- Capture `theme/basemap/index.html` → `theme/screenshots/basemap-kl.png` (1280×800, wait for `map.on('idle')` or first render + 2s).
3. `.gitignore`: ensure `theme/screenshots/` is excluded (regenerated artifacts). Wire `"capture": "node ./scripts/screenshot.mjs"`; root delegate `capture` already exists.
4. `theme/gallery.html` — static page, CDN-free, built from tokens only. Record in a leading HTML comment that this page is the DSGN-02 template mechanism every later UI phase extends:
- Header: "DSGN-02 Approval Gallery — Rams implementation vs mockups"
- Comparison rows, one per mockup screen: left = mockup capture, right = `sheet-full.png` (or per-section crops); final row = `basemap-kl.png`.
- Token ledger: table listing the typography scale + hero color token NAMES with rendered swatches/specimens only — no numeric restatement (D-07: docs never restate values).
- Approval strip stating scope: fidelity bar + basemap direction; interactive flows out of scope (per CONTEXT deferred).
</action>
<verify>
<automated>npm run capture && for f in theme/screenshots/*.png; do [ "$(stat -c%s "$f")" -lt 10240 ] && exit 1; done && test -f theme/gallery.html && grep -q "screenshots/" theme/gallery.html && npm run audit && echo GALLERY-TOOLS-OK</automated>
</verify>
<done>≥6 non-blank captures (sheet, 4 mockups, basemap); gallery references them; audit still clean</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>task 3: DSGN-02 approval checkpoint</name>
<what-built>
- Centralized Tailwind v4 token package (D-01/D-02), rendered component sheet (D-03/D-11), automated off-token audit — clean (D-13), Rams Liberty basemap over KL (D-08/D-09/D-10), Playwright captures (D-14), and the side-by-side approval gallery at `theme/gallery.html` (D-12).
</what-built>
<action>Present the completed gallery and basemap preview to the user per the how-to-verify steps below; record the decision and wait for the resume signal before any later-phase work relies on DSGN-02.</action>
<how-to-verify>
1. In your shell: `npx http-server theme -p 4444` (from repo root; gallery needs a static server for fonts + relative CSS).
2. Browse `http://localhost:4444/gallery.html` — side-by-side comparisons; judge fidelity of sheet vs mockups token-by-token.
3. Browse `http://localhost:4444/basemap/index.html` — Rams Liberty over KL; check grayscale/muted land + water, desaturated roads, no orange anywhere (route accent reserved per D-08, rendered in Phase 5).
4. Optionally compare against originals: `stitch_minimalist_route_navigator/<screen>/screen.png`.
5. Confirm the automated ground for "zero off-token values": `npm run audit` (executed during this plan; output shown in the summary).
</how-to-verify>
<resume-signal>Type "approved" (fidelity bar met, basemap direction good) — or list specific screens/components/basemap aspects to fix and iterate before DSGN-02 is recorded.</resume-signal>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| workstation browser → CDN Tailwind (mockup pages only) | Mockup screenshots fetch CDN scripts; all new design artifacts are CDN-free |
| audit.mjs → local files | Dev-only script reads repo files only |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-1-05 | I/T | screenshot.mjs CDN fetches | accept | Only the captured mockup pages (read-only per D-06) use CDN; captures are local gitignored artifacts. Gallery itself is CDN-free per D-16. |
| T-1-06 | D | approval artifact provenance | mitigate | theme/gallery.html committed as the durable DSGN-02 mechanism — later UI phases extend the same file; approval decision recorded in phase summary |
| T-1-07 | T | audit.mjs tampering | mitigate | Audit fails loud (exit 2) if token allowlist shrinks below 40 colors; violations exit 1 — no silent passes |
</threat_model>
<verification>
- `npm run audit` clean from a clean checkout after `npm run build --workspace theme`
- `npm run capture` produces ≥6 non-blank screenshots
- `theme/gallery.html` renders side-by-side with ≥4 captures referenced
- User approval recorded (checkpoint passed)
</verification>
<success_criteria>
- DSGN-01 audit sweep is automated and passing (D-13)
- DSGN-02 approval artifact exists; mechanism template documented for reuse (D-12)
- Playwright capture script committed and working (D-14)
- Design source of truth singular: package owns every numeric value (D-07)
</success_criteria>
<output>
After completion, create `.planning/phases/01-design-tokens-rams-foundation/01-04-SUMMARY.md`
</output>