Files
familysync/.planning/phases/07-mobile-test-harness/07-REVIEW-FIX.md
T

7.1 KiB

phase, fixed_at, review_path, iteration, findings_in_scope, fixed, skipped, status
phase fixed_at review_path iteration findings_in_scope fixed skipped status
07-mobile-test-harness 2026-06-11T08:05:00Z .planning/phases/07-mobile-test-harness/07-REVIEW.md 1 12 6 6 partial

Phase 7: Code Review Fix Report

Fixed at: 2026-06-11T08:05:00Z Source review: .planning/phases/07-mobile-test-harness/07-REVIEW.md Iteration: 1

Summary:

  • Findings in scope (fix_scope=all): 12 open/actionable + info; CR-01/BL-01/BL-02 already resolved (left intact)
  • Fixed: 6 (WR-01, WR-02, WR-05, WR-06, WR-07 — and WR-02/WR-01 share one commit)
  • Skipped: 6 (WR-03, WR-04, IN-01..IN-05) — by-design / positive notes, no net-positive edit available

Verification evidence (all fixes):

  • Full E2E suite (both profiles, iphone/WebKit + pixel/Chromium): 58 passed (29.4s), suite exit 0.
  • pnpm --filter @familysync/pwa typecheck (both tsconfig.json and tsconfig.e2e.json): exit 0.
  • SW test (WR-07) confirmed passing on BOTH iphone(WebKit) and pixel(Chromium) — re-run in isolation: 2 passed.
  • Suite was run from the isolated worktree with .env sourced from the main repo (worktree .env is gitignored/absent) + DEV_AUTH_BYPASS=true DB_HOST=127.0.0.1 DB_PORT=3306.

Fixed Issues

WR-01: readiness gate accepts the SPA shell, not a working DEV_AUTH_BYPASS API

Files modified: apps/pwa/e2e/global-setup.ts Commit: 9c38dd3 (shared with WR-02) Applied fix: Added a Step 1b probe after the /health gate: fetch(baseURL + '/api/me', { redirect: 'manual' }) and throw with a clear, actionable message unless it returns 200. If the API was started without DEV_AUTH_BYPASS=true, /api/me redirects (302) to Authelia; the gate now fails loudly in setup instead of producing ~40 confusing spec failures. Verified: the seed ran and all 58 specs passed, proving the new gate does not false-positive against the correctly-configured dev stack.

WR-02: readiness-gate success misreported as timeout near the deadline

Files modified: apps/pwa/e2e/global-setup.ts Commit: 9c38dd3 (shared with WR-01) Applied fix: Replaced the post-loop if (Date.now() >= deadline) throw (which can misclassify a success that arrived in the final second as a timeout, because await fetch itself consumes time) with an explicit let ready = false flag set inside the loop on res.ok; throw only if (!ready). Removes the clock-inference race. Verified by full green suite (globalSetup executes once at suite start).

Note: WR-01 and WR-02 are committed together because both edits live in the same contiguous readiness-gate hunk in global-setup.ts (no gsd-tools / interactive hunk-split available to separate one hunk into two commits). Both are readiness-gate robustness changes.

WR-05: page.unroute not in finally — misleading dead cleanup

Files modified: apps/pwa/e2e/calendar.spec.ts, apps/pwa/e2e/lists.spec.ts Commit: 2b745ad Applied fix: Removed the 5 trailing page.unroute(...) calls (calendar: error-heading, retry-44px, error-overflow tests; lists: empty-state, empty-overflow tests) and replaced each with a one-line comment explaining that Playwright gives each test a fresh page/context, so route handlers do not leak across tests — and that a trailing unroute never runs anyway if an expect above throws. Chose "drop redundant calls" over "wrap in try/finally" per the reviewer's stated options; it is the lower-noise option and matches real per-test isolation. Verified: all route-mocked error/empty-state tests still pass on both profiles.

WR-06: self-validation "remove style by reload" comment is wrong

Files modified: apps/pwa/e2e/layout.spec.ts Commit: 5322cfc Applied fix: Corrected both misleading comments (Rule 1 proof ~L209, Rule 2 proof ~L250) that claimed the injected <style> is removed "by navigating / page.reload drops inline style tags". The code actually removes it via styleHandle.evaluate((el) => el.remove()) with no reload. Comment-only change. Tier-2 typecheck + full suite green.

WR-07: SW-controller assertion near-vacuous on WebKit (iPhone) profile

Files modified: apps/pwa/e2e/calendar.spec.ts Commit: c564fc6 Applied fix: Rewrote the test from asserting navigator.serviceWorker.controller === null (which passes for unrelated reasons: SW absent on WebKit/http, or null controller on any first uncontrolled load) to: (1) probe 'serviceWorker' in navigator; (2) test.skip(!swAvailable, ...) so an unavailable API does not masquerade as a passing block (does NOT throw on WebKit); (3) where available, assert navigator.serviceWorker.getRegistration() resolves to undefined, which actually proves serviceWorkers: 'block' prevented registration. Renamed the test to "no service-worker registration". Verified on BOTH profiles — re-ran in isolation: 2 passed (iphone + pixel); WebKit does not throw.

Skipped Issues

WR-03: webServer manages Vite only; proxied API not managed

File: apps/pwa/playwright.config.ts:59-64 Reason: skipped — by design (D-09/D-10: operator brings up the stack, harness waits via globalSetup /health gate). Reviewer itself states "No code defect; documentation-coupling risk." WR-01's /api/me gate already strengthens the deferred-failure path. No net-positive code change.

WR-04: page.route('/api/lists') exact match

File: apps/pwa/e2e/lists.spec.ts:74, 96 Reason: skipped — already DOWNGRADED to resolved-correct in the review. fetchLists() requests the bare /api/lists (no query string), and the exact matcher is intentionally narrow so it does not swallow /api/lists/:id/items. Converting to a glob would be a regression. No change needed.

IN-01: mysql2 as PWA devDependency

File: apps/pwa/package.json:38 Reason: skipped — placement is correct and acceptable (dev/test-only, never bundled; vitest excludes e2e/**). The only caveat is keeping the version pin in lockstep with apps/api; both are currently 3.22.4. Not a defect.

IN-02: tsconfig.e2e.json types: ["node"] narrows ambient types

File: apps/pwa/tsconfig.e2e.json:4-5 Reason: skipped — positive "this is sound, no action" note from the reviewer. DOM globals come from lib, @playwright/test types via direct import. Confirmed by typecheck exit 0.

IN-03: vitest exclude: ['e2e/**'] isolation

File: apps/pwa/vitest.config.ts:17 Reason: skipped — positive "no action" note; the two runners are cleanly partitioned.

IN-04: typecheck script covers the e2e tsconfig

File: apps/pwa/package.json:10 Reason: skipped — positive "good, no action" note; confirmed typecheck runs both tsconfigs (exit 0).

IN-05: CR-01 guard protects production, not "the wrong dev DB"

File: apps/pwa/e2e/global-setup.ts:34-44 Reason: skipped — by design (D-06 deterministic reseed; documented in README). The dev-DB-wipe is intended. Adding an E2E_ALLOW_TRUNCATE/*_test-name gate would contradict the locked deterministic-reseed design and add operator friction for no production-safety gain (production is already hard-blocked). Per scope guidance, not a net-positive change.


Fixed: 2026-06-11T08:05:00Z Fixer: Claude (gsd-code-fixer) Iteration: 1