diff --git a/.planning/phases/17-ui-optimization-polish/17-VALIDATION.md b/.planning/phases/17-ui-optimization-polish/17-VALIDATION.md new file mode 100644 index 0000000..ca41b56 --- /dev/null +++ b/.planning/phases/17-ui-optimization-polish/17-VALIDATION.md @@ -0,0 +1,110 @@ +--- +phase: 17 +slug: ui-optimization-polish +status: draft +nyquist_compliant: false +wave_0_complete: false +created: 2026-06-18 +--- + +# Phase 17 — Validation Strategy + +> Per-phase validation contract for feedback sampling during execution. +> Source: `17-RESEARCH.md` §Validation Architecture. Requirement IDs are TBD for this +> phase (UI/UX polish + branding) — decisions D-01…D-10 (CONTEXT.md) and workstreams +> A–D (UI-SPEC.md) stand in for REQ-IDs until promoted in plan-phase. + +--- + +## Test Infrastructure + +| Property | Value | +|----------|-------| +| **E2E Framework** | Playwright 1.60.0 | +| **Unit Framework** | Vitest ^4.1.8 | +| **E2E config file** | `apps/pwa/playwright.config.ts` (profiles: `iphone` 390×844 WebKit, `pixel` 412×915 Chromium, `desktop` 1280×720) | +| **Unit config file** | `apps/pwa/vitest.config.ts` | +| **Quick run command** | `pnpm --filter @familysync/pwa exec playwright test --project=pixel layout.spec.ts` | +| **Full suite command** | `pnpm --filter @familysync/pwa test:e2e` | +| **Build gate** | `pnpm --filter @familysync/pwa build` | +| **Estimated runtime** | ~45–90 seconds (quick: ~15s; full 3-profile suite: ~60–90s) | +| **Browser-verification skill** | `playwright-cli` (desktop/Chromium UI checks the spec suite cannot cover) | + +--- + +## Sampling Rate + +- **After every task commit:** Run `pnpm --filter @familysync/pwa exec playwright test --project=pixel layout.spec.ts` (phone profile covers the primary fix geometry) +- **After every plan wave:** Run `pnpm --filter @familysync/pwa test:e2e` (full 3-profile suite) + `pnpm --filter @familysync/pwa build` +- **Before `/gsd-verify-work`:** Full Playwright suite green + playwright-cli visual sweeps passed + **human logo approval received** (Workstream B checkpoint) +- **Max feedback latency:** ~90 seconds + +--- + +## Per-Task Verification Map + +> Task IDs are assigned by the planner. This map is workstream/decision-keyed; the executor +> binds each task ID to the matching row's automated command during execution. + +| Decision | Workstream | Behavior | Test Type | Automated Command / Method | Automated? | Status | +|----------|-----------|----------|-----------|----------------------------|------------|--------| +| D-01/D-02 | A | FAB bottom edge ≤ BottomTabBar top edge on iphone/pixel | Playwright geometry assertion | **New** assertion in `apps/pwa/e2e/layout.spec.ts` (skipped on desktop) | CI (iphone + pixel) | ⬜ pending | +| D-01 | A | Color-legend chips visible; content scrollable above bar | Playwright + playwright-cli sweep | `layout.spec.ts` full suite + manual scroll | Partial | ⬜ pending | +| D-01 | A | No horizontal overflow after fix (`scrollWidth ≤ clientWidth`) | Playwright Rule 2 | Existing `layout.spec.ts` Rule 2 | CI (all profiles) | ⬜ pending | +| D-01 | A | Tap targets preserved (≥44px / ≥56px) | Playwright Rule 1 | Existing `layout.spec.ts` Rule 1 | CI (all profiles) | ⬜ pending | +| D-03/D-04 | B | All 7 asset files present in `apps/pwa/public/` | Shell existence check | `ls apps/pwa/public/{logo.svg,favicon.svg,favicon.ico,icon-192.png,icon-512.png,icon-maskable-512.png,apple-touch-icon.png}` | CI gate / Wave 0 | ⬜ pending | +| D-04 | B | `favicon.ico` is multi-size & non-trivial (>100 bytes) | Shell | `test $(wc -c < apps/pwa/public/favicon.ico) -gt 100` | CI gate | ⬜ pending | +| D-04 | B | `icon-maskable-512.png` is exactly 512×512 (real safe-zone) | Node + sharp metadata | `node -e "require('sharp')('apps/pwa/public/icon-maskable-512.png').metadata().then(m=>console.log(m.width,m.height))"` | Scripted | ⬜ pending | +| D-04 | B | PWA manifest + index.html icon links resolve (no 404) | Playwright | `page.goto('/')`, devtools manifest / network check | playwright-cli | ⬜ pending | +| D-03 | B | Logo meets warm/rounded/at-home brief | Human review | playwright-cli screenshot + operator approval | **Human checkpoint** | ⬜ pending | +| D-05 | B | BrandSlot swap: no LoginPage layout shift; `

` retains name; img `alt=""` | Playwright + playwright-cli | login route render + a11y name check | playwright-cli | ⬜ pending | +| D-06 | C | No hard-coded hex/px literals in component files | `grep` | `grep -rnE '#[0-9a-fA-F]{3,6}\|[0-9]+px' apps/pwa/src/components/ apps/pwa/src/routes/` (expect token refs only) | CI gate | ⬜ pending | +| D-06 | C | Schedule-X `--sx-color-*` overrides still apply post-restructure | playwright-cli | visual sweep of `/calendar` | playwright-cli | ⬜ pending | +| D-06 | C | TypeScript + Vite build exits 0 | Build | `pnpm --filter @familysync/pwa build` | CI | ⬜ pending | +| D-07 | D | "Sign out" control renders in SettingsSheet | Playwright + playwright-cli | open settings sheet, confirm button + aria-label | playwright-cli | ⬜ pending | +| D-07 | D | Logout calls `fetchLocalLogout()` then navigates to `/login` | Playwright interaction | click Sign out, confirm redirect | playwright-cli | ⬜ pending | +| D-08 | D | "Member added." toast on create success | Playwright interaction | admin: create member, confirm toast (role=status) | playwright-cli (admin) | ⬜ pending | +| D-08 | D | "Password reset." toast on reset success | Playwright interaction | admin: reset password, confirm toast | playwright-cli (admin) | ⬜ pending | +| D-08 | D | Toast auto-dismisses after ~3s | Playwright interaction | wait 3.5s, confirm gone | playwright-cli | ⬜ pending | +| D-09 | D | Sheet centered on desktop (`top/left 50%`, transform) | Playwright geometry | playwright-cli @1280×720 SettingsSheet geometry | playwright-cli (desktop) | ⬜ pending | +| D-09 | D | Sheet renders as bottom-sheet on phone | Playwright geometry | playwright-cli @390×844 geometry | playwright-cli (phone) | ⬜ pending | +| D-10 | D | Admin two-tab strip renders with correct labels | Playwright | `/admin`: confirm "Members & Accounts" + "Settings" | playwright-cli (admin) | ⬜ pending | +| D-10 | D | ArrowLeft/ArrowRight switches tabs (roving tabindex) | Playwright keyboard | focus tab, ArrowRight, confirm active | playwright-cli | ⬜ pending | +| D-10 | D | Admin tab ARIA roles present (`tablist`/`tab`/`aria-selected`/`tabpanel`) | Playwright | **New** assertion in `admin.spec.ts` or `layout.spec.ts` via `getByRole` | CI | ⬜ pending | + +*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* + +--- + +## Wave 0 Requirements + +- [ ] **Overlap regression assertion** — add the FAB↔BottomTabBar geometry test to `apps/pwa/e2e/layout.spec.ts` (Workstream A; runs on iphone + pixel, skipped on desktop). Contract in UI-SPEC §"Regression guard". +- [ ] **Admin tab ARIA assertion** — add `role="tablist"`/`role="tab"`/`aria-selected`/`role="tabpanel"` checks to `apps/pwa/e2e/admin.spec.ts` (or append to `layout.spec.ts`) (Workstream D-10). +- [ ] **Asset existence check** — Wave 0 npm script or inline CI step asserting all 7 `apps/pwa/public/` assets exist with valid format (ICO size, maskable dimensions). +- [ ] **`@vite-pwa/assets-generator` devDependency** — install in `apps/pwa` (pulls `sharp` + `sharp-ico`; the only new package) before Workstream B asset derivation runs. + +*Existing infrastructure (Playwright 3-profile config + `layout.spec.ts` Rules 1–4 + Vitest) covers the bulk of the structural assertions.* + +--- + +## Manual-Only Verifications + +| Behavior | Decision | Why Manual | Test Instructions | +|----------|----------|------------|-------------------| +| Logo / icon set meets warm/rounded/at-home brief | D-03 | Aesthetic judgment; AI-generated art needs operator sign-off | playwright-cli screenshot of BrandSlot on `/login` + favicon in tab; operator approves at checkpoint before wiring is committed | +| Brand accent selection (cool-blue vs warm rose/amber) | UI-SPEC Q1 | Subjective brand decision | Present both variants (one-line token swap); operator selects at logo checkpoint | +| Maskable adaptive-icon render on a real device | D-04 | iOS/Android home-screen mask is device-only (cannot be driven by playwright-cli) | Install PWA on a device, confirm logo within safe-zone (optional spot-check; format validated automatically) | +| Schedule-X calendar colors visually unchanged post-restructure | D-06 | Visual regression of third-party calendar theme | playwright-cli sweep of `/calendar` before/after the tokens.css restructure | + +--- + +## Validation Sign-Off + +- [ ] All tasks have an automated verify command or a Wave 0 dependency +- [ ] Sampling continuity: no 3 consecutive tasks without automated verify +- [ ] Wave 0 covers all MISSING references (overlap assertion, admin ARIA assertion, asset-existence check, assets-generator install) +- [ ] No watch-mode flags (`playwright test` / `vitest run` are one-shot) +- [ ] Feedback latency < 90s +- [ ] `nyquist_compliant: true` set in frontmatter + +**Approval:** pending