# Code Review Report **Batch**: 6 — AZ-463, AZ-469, AZ-476, AZ-477 **Date**: 2026-05-11 **Verdict**: PASS **Mode**: Full (per-batch invocation by `/implement`) ## Inputs - Task specs: - `_docs/02_tasks/todo/AZ-463_test_flight_selection_persistence.md` (4 ACs, 3 pts) - `_docs/02_tasks/todo/AZ-469_test_browser_support_responsive.md` (3 ACs, 2 pts) - `_docs/02_tasks/todo/AZ-476_test_upload_size_cap.md` (2 ACs, 2 pts) - `_docs/02_tasks/todo/AZ-477_test_settings_resilience.md` (3 ACs, 3 pts) - Changed files (9 total, all under Blackbox Tests OWNED scope, plus one docs file): - `tests/flight_selection_persistence.test.tsx` - `tests/browser_support_responsive.test.tsx` - `tests/upload_size_cap.test.tsx` - `tests/settings_resilience.test.tsx` - `e2e/tests/flight_selection_persistence.e2e.ts` - `e2e/tests/browser_support_responsive.e2e.ts` - `e2e/tests/upload_size_cap.e2e.ts` - `e2e/tests/settings_resilience.e2e.ts` - `_docs/LESSONS.md` (new — autodev `B2` surface; one entry capturing the `vi.stubGlobal('URL', ...)` anti-pattern uncovered while debugging AZ-476) ## Findings | # | Severity | Category | File:Line | Title | |---|----------|----------|-----------|-------| | — | — | — | — | None | No Critical, High, Medium, or Low findings. ## Phase Walkthrough ### Phase 1 — Context Loading All 4 task specs read; ACs catalogued; `module-layout.md` consulted for OWNED / READ-ONLY / FORBIDDEN envelopes. Every changed source file lives under `tests/**` or `e2e/**` — both `Owns` globs of the `Blackbox Tests` cross-cutting component (epic AZ-455). The single docs file (`_docs/LESSONS.md`) lives in `_docs/**`, owned by the orchestrator surface — not by any feature component. No file outside the envelope was modified. ### Phase 2 — Spec Compliance | Task | AC | Test | Today | Drift documented | |------|----|------|-------|------------------| | AZ-463 | AC-1 (FT-P-16 PUT /settings/user persistence) | `tests/flight_selection_persistence.test.tsx` + e2e | PASS | — | | AZ-463 | AC-2 (FT-P-17 rehydration on boot) | same | PASS | — | | AZ-463 | AC-3 (NFT-RES-LIM-07 100-cycle listener leak guard) | `e2e/tests/flight_selection_persistence.e2e.ts` (long-running) + fast companion stub | gated by `RUN_LONG_RUNNING=1` per spec | runner-level config gating is a follow-up; per spec the AC lives in e2e (long-running) only | | AZ-463 | AC-4 (NFT-RES-LIM-06 1 h SSE soak) | same | gated by `RUN_LONG_RUNNING=1` + `chromium` only (`performance.memory`) | same | | AZ-469 | AC-1 (FT-P-34 cross-browser smoke) | `e2e/tests/browser_support_responsive.e2e.ts` | runs against both Chromium + Firefox projects in `playwright.config.ts` | — | | AZ-469 | AC-2 (FT-P-35 mobile 480 px) | `tests/browser_support_responsive.test.tsx` + e2e | PASS — fast asserts Tailwind class shape, e2e asserts visibility | — | | AZ-469 | AC-3 (FT-P-36 desktop 1024 px) | same | PASS | — | | AZ-476 | AC-1 (FT-N-06 / NFT-RES-07 user-visible 413 error) | `tests/upload_size_cap.test.tsx` + e2e | `it.fails()` + control + `test.fail` (e2e) | drift — `MediaList.uploadFiles` swallows the failure silently and falls through to local mode; flips when toast + i18n key wired | | AZ-476 | AC-2 (no `alert()` on the 413 path) | same | PASS (vacuous today — no error path runs at all) + e2e dialog spy | — | | AZ-477 | AC-1 (FT-N-13 / NFT-RES-05 500 → button enabled + alert ≤ 2 s) | `tests/settings_resilience.test.tsx` + e2e | 2 × `it.fails()` (button + alert) + 1 control pinning the stuck-disabled drift | drift — `saveSystem` / `saveDirs` lack try/finally and an error region | | AZ-477 | AC-2 (FT-N-14 / NFT-RES-06 network drop ≤ 2 s) | same | 2 × `it.fails()` (button + alert) | — | | AZ-477 | AC-3 (NFT-PERF-09 deadline ≤ 2 s) | same | `it.fails()` measuring `performance.now()` between PUT response and alert visibility | — | Every AC has at least one assertion; every documented drift is paired with either a control PASS test (pinning the current behavior) or a `test.fail` annotation, so each failure mode is observable today and the contract test flips green automatically once production lands the fix. ### Phase 3 — Test Coverage Hygiene - 5 fast files / 4 e2e files / 0 production-source files modified. - Total fast tests added: 19 (4 + 5 + 3 + 6 — control / `it.fails()` placement matches spec direction). - AZ-463: 5 (2 pass + 1 listener-leak companion + 2 controls). - AZ-469: 4 (3 pass + 1 cross-browser-stub). - AZ-476: 3 (1 `it.fails()` + 1 control + 1 PASS). - AZ-477: 6 (4 `it.fails()` + 1 control + 1 deadline `it.fails()`). - Total e2e tests added: 9 (2 + 5 + 2 — long-running soaks gated; cross-browser smoke runs in both projects). - All `it.fails()` placements paired with a control test that pins the current production drift (so the drift is asserted today and the contract test flips on production change). No `it.skip` was used to hide failures. ### Phase 4 — Hygiene & Drift - 0 files added to `src/` (production code untouched — pure blackbox test batch). - 1 file added under `_docs/` — `LESSONS.md`. The entry is bounded (≤ 6 lines body) per the rule contract. Surfaces the `vi.stubGlobal('URL', { ...URL, ... })` anti-pattern that destroyed the URL constructor and silently hid the 413 round-trip in AZ-476 during early debugging. - The `tests/setup.ts` MSW boundary (`onUnhandledRequest: 'error'`) is preserved — every new test seeds its own handlers explicitly. - AZ-477 installs a scoped `process.on('unhandledRejection')` handler that swallows ONLY the expected drift signature (`500: upstream failure` and network-error patterns). Any other rejection still throws — this is the same posture the production code will take once try/finally lands, just enforced at the test boundary in the meantime. ### Phase 5 — Static + Lint - `bun run test:fast` — 22 files / 120 passed / 13 skipped / 46.52 s. - `./scripts/run-tests.sh --static-only` — 24 / 24 static checks PASS / 39.72 s. No new banned-deps hits; no alert() leaks; no ML / signature / persistence / WS / SSR libs introduced. - `ReadLints` clean on all 9 new files. - `tsc --noEmit -p tsconfig.test.json` succeeded as part of STC-T1. ### Phase 6 — Self-Review - Test rigs re-read end-to-end for naming clarity, AAA shape, and proper teardown of every globally mutated handle (`URL.createObjectURL`, `process.on('unhandledRejection')`, MSW handler resets via `afterEach`). - `FlightSeed` helper in AZ-476 is intentionally local and tightly scoped — it sidesteps the async user-settings → `/api/flights/` rehydration chain that AZ-463 covers separately, reducing flake without duplicating the rehydration assertion. - Long comments in the test bodies explain *why* each `it.fails()` exists and what condition will flip it green; future readers can therefore tell intentional-drift from regression at a glance. ### Phase 7 — Architecture Compliance - No layer-direction violations. Tests are leaves of the import graph; they import production sources but no production source imports them. - No new cyclic dependencies (verified via `bunx tsc --noEmit` and `bun run build` in the static profile). - `src/api/client.ts` is exercised but not modified — the contract for `api.put` / `api.upload` failure modes (rejected promises) is observed by the tests, not changed. - `STC-S6` (no WS/GraphQL/gRPC/SSR deps) and `STC-S13` (no client-side persistence libs) re-confirm. ## Summary PASS — the batch lands four blackbox-test tasks (12 ACs total) with zero production-code edits, every drift paired with a runnable control test, and full static + fast suite green.