# Independent UI fix verification — 6 September 2026

Reviewed branch `fix/review-20260906-verify-ui` in `/home/stevan/dev/compass-verify-ui` at `d6a057f9f`. Compared the original findings in `docs/reviews/2026-09-05-codebase-review/findings.json` and `fixes.md` with the implementation, then exercised the relevant real-browser and rendering tests. Read `CLAUDE.md` first.

**Verdict: all ten assigned original findings are closed. No additional defect reproduced; no repository changes or commits were needed.** The worktree is clean. No design changes, deployments, external extraction calls, pushes, or default/shared database use occurred.

## Results by original finding

| ID | Status | Independent evidence |
|---|---|---|
| #1 Back navigation erases account requirements | Verified fixed | Browser changes naming to Named Required, returns Back/Next, submits, and checks persisted JSON. Currency reconciliation tests preserve valid custom rows and remove affected defaults. An additional Turbo Back probe set default naming and UK domicile plus a custom sending row with Named Required; the complete serialized requirements remained identical after visiting Analytics and returning with browser Back. |
| #9 Lookup details are mouse-only | Verified fixed | Real Tab navigation reaches each named native disclosure button. Enter and Space expand its associated detail row; `aria-expanded` updates on keyboard, button, and row-click activation. Expand/collapse-all state also passes. Source confirms stable `aria-controls` IDs and hidden decorative chevrons. |
| #10 Rerun hides required forward fields | Verified fixed | Saved forward lookup renders its checked toggle and populated sell/buy currencies, tenor, and type visibly on Trade Details. A server-rejected tenor retains the populated visible fields and displays the specific error. Source applies the same visibility/disabled logic on controller connection. |
| #14 Account row controls have no names | Verified fixed | Browser checks every generated select has a contextual accessible name and ID; new custom row names update when direction changes; removal has a contextual name, hides its icon from accessibility APIs, and returns focus to Add Row. Turbo Back ID uniqueness passes. |
| #23 Phone overflow | Verified fixed | Browser tests at 390px show document width at most 390px on Analytics and Trade Details, including an added custom row. Analytics date fields, Filter, and Export CSV are within the viewport and Filter works. Both pages remain contained at 125% root text size. Account table uses its responsive scroller. |
| #25 Autocomplete semantics | Verified fixed | Browser confirms combobox/listbox and stable option association, expanded state, active-descendant and selected-option updates while retaining input focus. Filtering, Arrow Down/Up, Enter, Escape, and mouse selection pass. Additional probe confirms Tab closes the list and clears active-descendant, no-match filtering closes it without stale ARIA state, and typing a match reopens it for keyboard selection. |
| #28 Duplicate requirements fail without explanation | Verified fixed | Duplicate rows produce visible live-region text and associated `aria-invalid` controls, block submission, and focus the conflicting select while retaining edits. Correcting the direction clears the invalid state and allows submission. Direct submission bypassing client validation exercises real server rejection: Trade Details is visible, the field-specific error is rendered, values are restored, and error focus is applied. |
| #29 Polling can navigate after leaving page | Verified fixed | Extraction browser tests keep one request in flight beyond the normal interval, navigate via Cancel, verify the old request is aborted, and deliberately release an abort-ignoring response without navigation. Network failure retry and connected completion pass. Upload browser coverage confirms one request, cancellation, and no navigation after disconnect. Additional real DOM removal/reinsertion probes verify both controllers ignore stale completion/failure after the **same controller element reconnects**; current extraction completion still navigates, and upload HTTP failure retries serially before presenting the current failure with Retry. |
| #34 Breadcrumb landmark typo | Verified fixed | Shared helper rendering asserts `nav[aria-label="breadcrumb"]` and the current-page marker. Source no longer uses the misspelled attribute. |
| #35 Sign-in document language | Verified fixed | A real unauthenticated GET returns HTTP 200 and `html[lang="en"]`. Source declares English on the shared unauthenticated layout used by sign-in/password-reset pages. |

## Test evidence

Every Rails/RSpec command used:

```sh
env -u DATABASE_URL DISABLE_SPRING=1 RAILS_ENV=test TEST_ENV_NUMBER=100 DEVISE_SECRET_KEY=synthetic-verification-test-key bundle exec ...
```

Created and schema-loaded dedicated `currencytransfer_test100`; no shared/default database or Spring was used. Chromium runs through the repository's Capybara/Selenium configuration.

- Focused baseline: **32 examples, 0 failures**, seed **60231**, 67.09 seconds (plus 7.63 seconds load). Files: `lookup_wizard_spec.rb`, `lookup_results_spec.rb`, `analytics_mobile_spec.rb`, `participants_autocomplete_spec.rb`, `extraction_polling_spec.rb`, `upload_preview_spec.rb` under `spec/system/admins/compass/`, plus `spec/helpers/admins/layout_helper_spec.rb` and `spec/requests/sessions_spec.rb`.
- Stronger Turbo Back retention probe: **1 example, 0 failures**, seed **7133**, 6.28 seconds (plus 7.43 seconds load). Temporarily strengthened the existing wizard ID-restoration example, ran it, then restored the original tracked file. A copy of the strengthened spec is retained at `/tmp/compass-verify-20260906/lookup_wizard_retention_probe_spec.rb`; use `--example 'retains requirement values and unique IDs'` to select the additional probe. Its explicit `type: :system` permits execution outside the repository's `spec/system` path.
- Additional lifecycle/keyboard probes: **3 examples, 0 failures**, seed **60232**, 6.94 seconds (plus 7 seconds load). Executed `/tmp/compass-verify-20260906/ui_lifecycle_probe_spec.rb` against the real application server in Chromium. The poll test delays intentionally ignore abort so request identity and lifecycle guards must independently prevent stale effects; DOM removal/reinsertion triggers actual Stimulus disconnect/reconnect.
- Final `git status --short` and `git diff --check`: clean/no output.

## Limits

This verifies the ten original UI findings and the reasonable lifecycle/state edges above. No manual screen-reader session, live extraction provider, production traffic, device browser matrix, or mobile operating-system accessibility session was exercised. Phone text scaling was tested at 125%, not a general claim about every zoom level. Findings and the twelve deferred product/architecture opportunities outside this assigned subset were left to their respective owners.
