diff --git a/docs/superpowers/plans/2026-06-11-p3-polish.md b/docs/superpowers/plans/2026-06-11-p3-polish.md new file mode 100644 index 0000000..f6d898a --- /dev/null +++ b/docs/superpowers/plans/2026-06-11-p3-polish.md @@ -0,0 +1,669 @@ +# P3 Polish Backlog Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Land the ten deliberately-deferred P3 items from the 2026-06-11 critique (`.impeccable/critique/2026-06-11T05-34-28Z__web-src.md`): orphaned asset cleanup, saved-rail typography/contrast, Edge-slots plain-words copy, status-page desktop layout, emoji→glyph swap, color swatches, mobile-bar occlusion, toolbar scope readout, and the two `$:` hidden-dep smells (only if cheap). + +**Architecture:** All work is in `web/` except one read-only grep already done (crates/ has zero asset-path references to the focus PNGs — confirmed). Every change is small and local; the one M-effort item (status desktop layout) is prepared as two screenshot-able treatments and decided at a single batched user CHECKPOINT together with the other visual items. `cd web && npm run check` is the regression rail after every task. + +**Tech Stack:** Svelte 5 (App.svelte and tuning panels are LEGACY `$:` mode — do not introduce runes there; SavedRail.svelte is already runes mode), Vite, Playwright (devDep). + +**Hard rules (user-enforced; violations failed prior reviews):** +- Never touch `web/src/lib/api/*`, `web/src/lib/mock/*`, `web/src/lib/types.ts` (the Edge-slots dev-voiced error string lives in `web/src/lib/api/controllers.ts` — map it in the VIEW, do not edit the api file). +- Copy law: no Device/HID/gamepad/plugin/backend/bus in user copy; "Everyday" always pairs with "Global Profile"; `/legacy/i` must not match anything in production source (source-audit enforces). +- Never commit to `main`. This plan's branch: `p3-polish` off `main`. +- No local Rust toolchain; nothing here touches `crates/`. +- Gates: `cd web && npm run check` green at every commit. +- Visual items (Tasks 2, 4, 5, 7, 8) get ONE batched user CHECKPOINT (Task 10) before the PR — the user reviews in dev:mock; commits before the checkpoint are fine (branch is unpushed and amendable). + +--- + +### Task 0: Branch + baseline + +**Files:** none (git + gates only) + +- [ ] **Step 0.1: Create the branch** + +```bash +cd /Users/kmcdowell/Documents/repos/dualsense-command +git checkout main && git pull +git checkout -b p3-polish +``` + +- [ ] **Step 0.2: Confirm the gate baseline** + +Run: `cd web && npm run check` +Expected: all gates green (typecheck, source-audit, button-map, snapshot-map, haptics-graph, build, release-size, visual-smoke). If anything is red, STOP and report. + +--- + +### Task 1: Delete the orphaned HUD-era focus PNGs (+ their dead CSS hook) + +20 PNGs (156KB) in `web/public/dualsense/focus/` have zero references anywhere in `web/` or `crates/` (verified by exhaustive grep: the only image lookups are `ButtonMappingView.svelte:316` → `/dualsense/controller_front.png` and `buttonMapping.ts:251` → `/dualsense/icons/iconid_controller_key_*.png`). The companion CSS class `.dm-controller-focus` (`web/src/styles/button-mapping/layout/controller-art.css:88-99`) is defined but never applied to any element. + +**Files:** +- Delete: `web/public/dualsense/focus/` (entire directory, 20 PNGs) +- Modify: `web/src/styles/button-mapping/layout/controller-art.css:88-99` + +- [ ] **Step 1.1: Re-verify zero references (cheap insurance)** + +```bash +cd /Users/kmcdowell/Documents/repos/dualsense-command +grep -rn "dualsense/focus\|focus_" web/src web/scripts web/index.html web/vite.config.ts crates/ || echo "ZERO REFS" +``` +Expected: `ZERO REFS` (or only hits that are clearly not asset paths, e.g. `focus-visible`, `focus_` absent). If a real asset reference appears, STOP and report. + +- [ ] **Step 1.2: Delete the directory and the dead CSS block** + +```bash +git rm -r web/public/dualsense/focus +``` + +Then in `web/src/styles/button-mapping/layout/controller-art.css` delete the entire `.dm-controller-focus { ... }` rule block (lines 88–99: opacity/filter/transition styling for a focus overlay image that is never rendered). Verify nothing else references the class first: + +```bash +grep -rn "dm-controller-focus" web/src || echo "only the css rule" +``` +Expected: only the rule being deleted (in controller-art.css). If a Svelte file uses it, STOP — leave the CSS and report. + +- [ ] **Step 1.3: Verify build + size gate** + +Run: `cd web && npm run build && npm run test:release-size && (grep -r "focus_" dist/ && echo "FAIL: focus refs in dist" || echo "clean")` +Expected: build green, release-size green (smaller), `clean`. + +- [ ] **Step 1.4: Commit** + +```bash +git add -A web/public/dualsense web/src/styles/button-mapping/layout/controller-art.css +git commit -m "p3-polish: delete 156KB of orphaned HUD-era focus PNGs and their dead CSS hook" +``` + +--- + +### Task 2: Saved rail typography + raised-surface contrast — **CHECKPOINT (batched, Task 10)** + +The rail title is 9px and rows are 11px; `--ink-muted` (#8b8b96) on `--surface-raised` (#26262c) computes ≈4.46:1 — a marginal AA fail. Raise rows to 12px, title to 10px, and add a one-step-brighter muted token for raised surfaces. + +**Files:** +- Modify: `web/src/styles/tokens.css` (after `--ink-muted`, line ~10) +- Modify: `web/src/styles/tuning.css` (`.saved-rail-title` ~505, `.saved-row` ~519, `.saved-row-saved`/`.saved-row-was` ~546) + +- [ ] **Step 2.1: Add the raised-surface muted token** + +In `tokens.css`, directly after the `--ink-muted: #8b8b96;` line, add: + +```css + /* Muted ink for raised surfaces: #8b8b96 on --surface-raised is ≈4.46:1 + (marginal AA fail); this lands ≈4.9:1. */ + --ink-muted-raised: #93939d; +``` + +- [ ] **Step 2.2: Apply in tuning.css** + +Change `.saved-rail-title` from: +```css +.saved-rail-title { + font-size: 9px; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--ink-muted); +} +``` +to: +```css +.saved-rail-title { + font-size: 10px; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--ink-muted-raised); +} +``` + +In `.saved-row`, change `font-size: 11px;` to `font-size: 12px;` (rest of the rule unchanged). + +Change: +```css +.saved-row-saved, +.saved-row-was { + color: var(--ink-muted); +} +``` +to: +```css +.saved-row-saved, +.saved-row-was { + color: var(--ink-muted-raised); +} +``` + +- [ ] **Step 2.3: Verify** + +Run: `cd web && npm run check` +Expected: green (visual-smoke covers 1366/1440/390; the rail is fixed-width furniture so +1px text must not break layout — if visual-smoke fails on rail overflow, report rather than shrinking the font back). + +- [ ] **Step 2.4: Commit** + +```bash +git add web/src/styles/tokens.css web/src/styles/tuning.css +git commit -m "p3-polish: saved rail 12px rows, 10px title, AA-passing muted ink on raised surfaces" +``` + +--- + +### Task 3: Edge onboard slots — plain words, teach Fn slots + +The error state renders the raw API message "DualSense Edge onboard profile read/write requires the real DSCC agent." (thrown in `web/src/lib/api/controllers.ts` — FORBIDDEN file, map in the view). The empty state says "No slot data / unavailable". Both are dev register. + +**Files:** +- Modify: `web/src/lib/features/controllers/EdgeSlotsView.svelte` (script + error note + empty-state block) + +- [ ] **Step 3.1: Map the dev-voiced error in the view's script** + +In the ` +{#snippet rowValue(value: string, isColor: boolean)} + {#if isColor && value.startsWith('#')}{/if}{value} +{/snippet} + {#snippet diffRows()} {#each rows as item (item.id)}