---
description: Use when UI changes span multiple components or pages, layout or navigation changed, a new user-facing feature was added, or comprehensive UX validation is needed.
---

## Config Override

If this command was invoked via a local config wrapper (you see a `## Repo Config` section earlier in the prompt), use that config to skip detection:
- **Browser Tool** specified? → Skip Step 1, use the declared tool directly (fall back to detection if unavailable)
- **Stack** declared? → Skip tech stack inference in Step 2
- **Dev Server Port** specified? → Use it in Step 3 URL construction (still check `lsof` as fallback)
- **Component Paths** listed? → Use as focus hints for which pages to prioritize in Step 3
- **Credential Hints** listed? → Use those variable names in Step 4 credential search
- **UX Focus Areas** listed? → Emphasize those aspects in your test plan across all agents

If the config overlay date is more than 90 days old, mention: "Your `/ux` config is over 90 days old — consider running `/jacked-setup ux` to refresh it."

If no `## Repo Config` section is present, run all detection steps normally.

You are the UX Check Dispatcher. You spawn parallel browser-testing agents, each focused on specific UX aspects on specific pages, to validate UI changes fast. This is the browser-testing equivalent of /dcr — multiple agents working simultaneously, each going deep on their assigned area.

> **Tip:** MCP-based browser tools (Playwright MCP, Claude-in-Chrome) require no bash approval and work instantly with the jacked gatekeeper. If using `agent-browser`, pre-approve it once via **Always Allow** in the jacked logs UI — this adds `Bash(npx agent-browser:*)` to your allowlist.

## UX CHECK ASPECTS (6 total)

| # | Aspect | What to Check |
|---|--------|---------------|
| 1 | **Visual & Layout** | Broken layouts, overlapping elements, spacing, alignment, text readability, color consistency, images/icons loading |
| 2 | **Responsive** | Mobile (375px), tablet (768px), desktop (1280px+) — layout integrity, touch targets, text wrapping, no horizontal scroll |
| 3 | **Interactions** | Buttons, forms, navigation, modals, dropdowns, toggles, hover states, loading states, error feedback |
| 4 | **Console & Network** | JS errors, unhandled rejections, 404s, failed API calls, slow requests, deprecation warnings |
| 5 | **Accessibility** | Semantic HTML, focus order, keyboard navigation, color contrast, ARIA labels, screen reader landmarks |
| 6 | **Discoverability** | New features only: entry points from related pages, navigation depth to reach feature, first-use clarity, return navigation back to origin |

## Step 1: Detect Browser Tools

Check which browser automation tools are available. Prefer MCP tools first — they require no bash permissions and work without gatekeeper prompts.

**Option A — Chrome DevTools MCP (preferred)**: Try calling `mcp__chrome-devtools__list_pages`. If it works, set `browser = "chrome-devtools"`. Use these tools:
- `mcp__chrome-devtools__navigate_page` → open pages
- `mcp__chrome-devtools__take_snapshot` → accessibility tree (preferred for element detection)
- `mcp__chrome-devtools__take_screenshot` → visual screenshot
- `mcp__chrome-devtools__click` → click element by ref from snapshot
- `mcp__chrome-devtools__fill` → fill input fields
- `mcp__chrome-devtools__evaluate_script` → run JavaScript on page
- `mcp__chrome-devtools__emulate` → change viewport size (mobile/tablet testing)
- `mcp__chrome-devtools__list_console_messages` → check for JS errors
- `mcp__chrome-devtools__list_network_requests` → check for failed requests

**If Chrome DevTools MCP fails** (tool call errors, connection refused, or no pages returned): Tell the user:
```
Chrome DevTools MCP is not responding. To fix:

1. Chrome version: You need Chrome 144 or newer.
   Check yours at chrome://version — update if needed.

2. Enable remote debugging (pick one):
   a) In Chrome: go to chrome://inspect/#remote-debugging and enable it
   b) Or launch Chrome with: --remote-debugging-port=9222
      macOS:  /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
      Linux:  google-chrome --remote-debugging-port=9222

3. If not installed: run `jacked install` (includes Chrome DevTools MCP setup)
   or manually: claude mcp add -s user chrome-devtools -- npx chrome-devtools-mcp@latest --autoConnect
```
Then continue to Option B as fallback.

**Option B — Playwright MCP**: Try using `mcp__plugin_playwright_playwright__browser_snapshot`. If it works, set `browser = "playwright"`. Note to user:
> Using Playwright MCP (Chrome DevTools MCP is preferred — see above). Playwright opens separate browser windows.

**Option C — Claude-in-Chrome**: Try using `mcp__claude-in-chrome__tabs_context_mcp`. If it works, set `browser = "chrome"`.

**Option D — agent-browser CLI**: Run `npx agent-browser --version` via Bash. If it succeeds, set `browser = "agent-browser"`. This reuses your existing browser session — no new windows.
> Note: `npx` requires a gatekeeper approval prompt unless pre-approved. Add `Bash(npx agent-browser:*)` via the jacked "Always Allow" button to avoid repeated prompts.

**If none are available**: Tell the user:
```
No browser tools detected. Recommended setup:

  jacked install    (configures Chrome DevTools MCP automatically)

Or install manually:
  claude mcp add -s user chrome-devtools -- npx chrome-devtools-mcp@latest --autoConnect
  (requires Chrome 144+ with remote debugging enabled — see chrome://inspect/#remote-debugging)

Alternatives:
- Playwright MCP: Add to .mcp.json with --headless flag
- Claude-in-Chrome: Install the Chrome extension from https://chromewebstore.google.com
- agent-browser: npm i -g agent-browser (requires npx pre-approval)
```
Then stop.

## Step 2: Identify What Changed

Run `git diff --name-only HEAD` to find UI-relevant files:
- `.js`, `.jsx`, `.ts`, `.tsx`, `.css`, `.scss`, `.less`, `.html`
- `.vue`, `.svelte`, `.erb`, `.jinja`, `.jinja2`
- Ignore: `node_modules/`, `dist/`, `build/`, `__pycache__/`, test files (`*.test.*`, `*.spec.*`)

Map changed files to affected pages/flows using file paths and conversation context.

If no UI files changed, tell the user and ask if they still want to proceed.

### Detect New Features (Discoverability trigger)

Also run both commands — the first catches staged new files, the second catches untracked (created but not yet staged) new files:
```bash
git diff --name-status HEAD | grep "^A" | grep -iE '\.(js|jsx|ts|tsx|css|scss|html|vue|svelte)$'
git ls-files --others --exclude-standard 2>/dev/null | grep -iE '\.(js|jsx|ts|tsx|css|scss|html|vue|svelte)$'
```

**Filter out utility/infrastructure files** before concluding a new feature exists. Files where the path contains `utils/`, `helpers/`, `hooks/`, `lib/`, `shared/`, `services/`, or where the filename matches `*.util.*`, `*.helper.*`, `*.service.*`, `*.store.*` are likely support code — not new navigable features. These do NOT trigger `new_feature_detected`.

If any remaining UI files appear (pages, views, components in feature directories) → set `new_feature_detected = true`.

When true, use the file paths and conversation context to:
- Describe what the new feature IS (e.g., "new Account Details page at `/accounts/:id`")
- Identify which **existing pages** a user would logically navigate FROM to reach it (e.g., Accounts list, Dashboard, any page that references accounts)
- Store these as **entry point pages** — the Discoverability agent will check them

**If entry points cannot be identified** from file paths or conversation context, default to checking the app's root/home page and any top-level navigation section most semantically related to the new feature (e.g., for an "Account Details" page, default entry points = Accounts list + Dashboard).

**$ARGUMENTS override:** If `$ARGUMENTS` contains `discoverability` or `disc`, force `new_feature_detected = true` even if git detection found no new files. Useful when testing a feature added in a previous session.

Announce:
```
**New feature detected:** [description]
**Expected entry points:** [list of existing pages that should link to the new feature]
**Discoverability check:** ENABLED
```

## Step 3: Detect Cross-Page Impact

After identifying changed files, classify each by impact scope using **filename and path heuristics** to determine if additional pages need testing beyond the ones directly mapped from file paths.

### Tier 1 — Likely affects all pages (test every route/page)
- Global state management (stores, contexts, reducers, `window.*State` globals)
- Router/navigation configuration files
- Global CSS or theme files (not component-scoped CSS modules)
- API client/HTTP utilities shared across pages
- WebSocket/event bus infrastructure
- Layout shells, headers, footers, navbars shared across all routes

**Path signals:** `shared/`, `common/`, `utils/`, `lib/`, `helpers/`, `layouts/`, `hooks/`, `services/`, `core/`
**Filename signals:** `app.*`, `main.*`, `router.*`, `store.*`, `state.*`, `theme.*`, `websocket.*`
**Exclude from signals:** `index.*` (module re-exports), `*.stories.*` (Storybook), `*.module.css` (CSS modules), `*.d.ts` (type declarations) — these are not shared infrastructure even when they match a signal name like `app.*`.

### Tier 2 — Likely affects a group of related pages
- Shared utility functions (date formatting, validation, HTML escaping)
- Shared sub-components used by multiple but not all pages
- Shared state/filters within a feature group (e.g., log filter state affects all log sub-tabs)

**Path signals:** `components/shared/`, `components/common/`
**Default:** If uncertain whether a file is Tier 2 or Tier 3, default to Tier 3 — Tier 1 coverage catches most cross-page regressions anyway.

### Tier 3 — Likely isolated to one page
- Page-specific components, event handlers, page-scoped CSS
- Everything not matching Tier 1 or 2 patterns

**Important:** When Tier 1 expands the page list to "all pages," the existing agent cap (4 max) and prioritization rules from the Build Test Matrix step still apply. Group pages intelligently and prioritize those most affected by the changes.

### Announce Cross-Page Analysis

If no changed files were detected at all:
```
**Cross-page impact:** Could not analyze — no changed files detected by git diff.
```

If files changed but none match shared patterns:
```
**Cross-page impact:** None detected — changed files appear page-isolated.
**Pages to test:** [original list from file mapping]
```

If cross-page impact detected:
```
**Cross-page impact detected:**
- style.css changed (global CSS) → testing ALL pages for visual consistency
- utils.js changed (shared utilities) → adding accounts, analytics, logs pages
- logs-server.js changed → isolated to Logs > Server sub-tab
**Pages to test:** [expanded list]
```

## Step 4: Select UX Personas

Select 2-3 personas that match the project's target users. These personas shape HOW agents evaluate their assigned aspects — they don't replace the 6 aspects, they add evaluative bias.

### Persona Pool

| Persona | Mindset | Evaluation Bias |
|---------|---------|-----------------|
| **Novice User** | "Can I figure this out without docs?" | Label clarity, discoverability, forgiveness, onboarding, help text |
| **Power User** | "Can I do this fast?" | Keyboard shortcuts, info density, bulk operations, workflow efficiency |
| **Design Consultant** | "Does this look professional?" | Visual hierarchy, typography, color harmony, whitespace, polish |
| **Accessibility User** | "Can I use this with a screen reader?" | Screen reader flow, keyboard-only operation, contrast, ARIA, focus management |

### Selection Logic

Infer the project type from context (`README.md`, `package.json`, `CLAUDE.md`, conversation history). Use these signals to classify:

| Project Signal | Classification | Personas |
|----------------|---------------|----------|
| Marketing pages, no auth, public content | Consumer/public app | Novice + Design Consultant |
| Auth-gated, data tables, CRUD, internal users | Admin dashboard | Power User + Novice |
| CLI references, API docs, code editors, dev-facing | Developer tool | Power User + Accessibility |
| Product listings, cart, checkout, payments | E-commerce/SaaS | Novice + Design Consultant + Power User |
| Compliance refs (HIPAA, ADA, 508), .gov domains | Government/healthcare | Accessibility + Novice |
| No clear signals | Unknown/ambiguous | Novice + Design Consultant |

**$ARGUMENTS handling:** If `$ARGUMENTS` mentions a persona name, match loosely against pool names (e.g., "power" -> Power User, "a11y" -> Accessibility User). If no pool match, treat the text as a custom persona with the user's description as its evaluation bias. Always select at least 2, maximum 3.

### How Personas Apply

Each agent evaluates their assigned aspects THROUGH the lens of ALL selected personas. Tag persona-specific issues:
- `**[MEDIUM] [Novice]** Submit button label "POST" is jargon — unclear to non-technical users`
- `**[LOW] [Power User]** No keyboard shortcut for the primary action`

## Step 5: Detect Mobile Context

Determine whether the project targets mobile users using **weighted signals**:

**Strong signals (any one -> `mobile_deep_dive = true`):**
- PWA manifest (`manifest.json` / `manifest.webmanifest` with `display: standalone`)
- Mobile-specific libraries in `package.json` (`react-native`, `capacitor`, `ionic`, `@angular/pwa`)
- Conversation context explicitly mentioning mobile usage

**Moderate signals (need 2+ to trigger):**
- Custom responsive breakpoints below 480px in project CSS (not in `node_modules/`)
- Touch-specific CSS/JS (`@media (hover: none)`, `touchstart` handlers)
- Mobile-specific meta tags beyond basic viewport (`apple-mobile-web-app-capable`, `theme-color`)

**Ignored (too universal to be meaningful):**
- `<meta name="viewport">` alone — present in virtually all modern web projects
- Framework-default `@media` queries from CSS frameworks

**Override:** If the Select UX Personas step classified the project as "admin dashboard" or "developer tool", set `mobile_deep_dive = false` regardless of signals.

**Default:** If zero signals found and no override applies, `mobile_deep_dive = false`.

### Announce Personas & Mobile

```
**UX Personas — [N] selected**
- [Persona 1] — [reason]
- [Persona 2] — [reason]
**Mobile deep dive:** Yes ([signal]) / No ([reason])
```

## Step 6: Determine App URL

**If `$ARGUMENTS` contains a URL**: Use that URL directly.

**Otherwise**, try to detect a running dev server:
1. Check conversation context for recently mentioned URLs
2. Run `lsof -i -P -sTCP:LISTEN | grep -E ':(3000|3001|4200|5000|5173|5174|8000|8080|8765|8888) '`

If found, use it. If multiple, ask the user. If none, ask for the URL.

## Step 7: Check for Login Credentials

If the app requires authentication to access the areas being tested, search for credentials in `.env` files before asking the user.

**Find the repo root** (`git rev-parse` is auto-approved by the gatekeeper):
```bash
git rev-parse --show-toplevel 2>/dev/null || pwd
```

**Scan env files** in priority order — run each grep separately (all are auto-approved, stop at first file with results):
```bash
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env.local
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env.development
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env.test
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env
```
Run from the repo root. **Skip any variable whose name starts with `DB_`, `DATABASE_`, `POSTGRES_`, `REDIS_`, `MONGO_`, `S3_`, or `AWS_`** — those are infrastructure credentials, not app login credentials.

**Announce what was found** (variable names only, never values):
- ✓ Found: `TEST_USER_EMAIL` + `TEST_USER_PASSWORD` in `.env.local` — "Using these for login."
- ✗ Not found: "No login credentials found in env files." → Ask the user for credentials.

**If login with found credentials fails:** Warn the user ("Credentials from `.env.local` were rejected") and ask for correct credentials. Do not retry silently.

**Security note:** If credentials were found in `.env.local`, `.env.development`, or `.env.test` in a repo you just cloned, verify this is an expected dev credentials file before using it.

**Screenshot setup** (agent-browser and Playwright only — Chrome does not support file-based screenshots):
```bash
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
rm -rf "$REPO_ROOT/tmp/ux_screenshots"
mkdir -p "$REPO_ROOT/tmp/ux_screenshots"
```
Save all screenshots to `$REPO_ROOT/tmp/ux_screenshots/<agent-letter>-<descriptive-name>.png`.
*Add `tmp/` to your project's `.gitignore` if it isn't already there.*

Pass the resolved `REPO_ROOT` path as a **literal string** to each agent's Task prompt — not as a shell variable reference like `$REPO_ROOT`.

## Step 8: Build Test Matrix

Select which aspects are relevant based on what changed:
- CSS/styling changes → weight **Visual & Layout** + **Responsive**
- JS logic/component changes → weight **Interactions** + **Console & Network**
- HTML structure changes → weight **Accessibility** + **Visual & Layout**
- New UI files added (`new_feature_detected = true`) → include **Discoverability** — assign the entry point pages list to the agent handling this aspect
- When in doubt, include the aspect.

Build a matrix of (aspect, page) and assign to 2-4 agents:

**1 page (modified only):**
- Agent A: Visual & Layout + Responsive
- Agent B: Interactions + Console & Network
- Agent C: Accessibility

**1 page (new feature — new_feature_detected = true):**
- Agent A: Visual & Layout + Responsive
- Agent B: Interactions + Console & Network
- Agent C: Accessibility + Discoverability

**2 pages (modified only):**
- Agent A: Page 1 — Visual & Layout + Responsive
- Agent B: Page 1 — Interactions + Console & Network + Accessibility
- Agent C: Page 2 — Visual & Layout + Responsive
- Agent D: Page 2 — Interactions + Console & Network + Accessibility

**2 pages (new feature — new_feature_detected = true):**
- Agent A: Page 1 — Visual & Layout + Responsive
- Agent B: Page 1 — Interactions + Console & Network
- Agent C: Page 2 — Visual & Layout + Accessibility
- Agent D: Page 2 — Interactions + Discoverability (receives the entry point pages list)

**3+ pages:** Group intelligently, cap at 4 agents. Prioritize pages most affected by changes. When `new_feature_detected = true`, assign Discoverability to whichever agent tests the new feature's page — pass them the full entry point pages list so they can navigate to those pages during checks.

Use your judgment — adjust grouping based on what changed. Skip aspects that clearly don't apply (e.g., skip Responsive for a purely server-rendered admin page that's never used on mobile).

**Announce the matrix:**
```
**UX Check Matrix — [N] aspects across [M] agents**
**Personas:** [Persona 1] + [Persona 2] (inferred: [classification])
**Mobile deep dive:** Yes ([signal]) / No ([reason])
- Agent A: [Page URL] — Visual & Layout + Responsive
- Agent B: [Page URL] — Interactions + Console & Network
- Agent C: [Page URL] — Accessibility
```

## Step 9: Spawn Parallel Agents

Spawn ALL agents in ONE message using parallel Task tool calls. Each agent is `subagent_type: "general-purpose"`.

### Agent Prompt Template

Include ALL of the following in each agent's Task prompt:

```
You are a UX tester performing focused browser-based checks.

## BROWSER TOOL: [chrome-devtools / agent-browser / chrome / playwright]

[If chrome-devtools]:
Use tools prefixed with `mcp__chrome-devtools__*`:
- `navigate_page` — open pages (use page selector or create new page)
- `take_snapshot` — accessibility tree with refs (preferred for element detection)
- `take_screenshot` — visual screenshot
- `click` — click element by ref from snapshot
- `fill` — fill input fields
- `evaluate_script` — run JavaScript on page
- `emulate` — change viewport size (mobile/tablet testing)
- `list_console_messages` — check for JS errors
- `list_network_requests` — check for failed requests
- `new_page` — create a new tab

[If agent-browser]:
Use the Bash tool with `npx agent-browser` commands:
- `npx agent-browser open <url>` — navigate to a URL
- `npx agent-browser snapshot` — accessibility tree with refs (preferred for element detection)
- `npx agent-browser screenshot <path>` — save screenshot to file
- `npx agent-browser click <ref>` — click element by @ref from snapshot
- `npx agent-browser type <ref> <text>` — type text into element
- `npx agent-browser fill <ref> <text>` — clear and fill element
- `npx agent-browser eval <js>` — run JavaScript on page
- `npx agent-browser scroll <dir> [px]` — scroll up/down/left/right
- `npx agent-browser wait <sel|ms>` — wait for element or time

Note: agent-browser reuses your existing browser — no tab isolation needed.

[If Chrome]:
Use tools prefixed with `mcp__claude-in-chrome__*`:
- `tabs_create_mcp` — create your own tab FIRST
- `navigate` — go to a URL (use your tab ID)
- `read_page` — accessibility tree
- `computer` action "screenshot" — visual screenshot
- `computer` action "left_click" — click at coordinates
- `find` — natural language element search
- `read_console_messages` — console output
- `read_network_requests` — network activity
- `resize_window` — change viewport size

[If Playwright]:
Use tools prefixed with `mcp__plugin_playwright_playwright__browser_*`:
- `browser_tabs` action "new" — create your own tab FIRST
- `browser_navigate` — go to a URL
- `browser_snapshot` — accessibility tree (preferred for element detection)
- `browser_take_screenshot` — visual screenshot
- `browser_click` — click element by ref
- `browser_type` — type text
- `browser_console_messages` — read console output
- `browser_network_requests` — inspect network
- `browser_resize` — change viewport size

## SCREENSHOT PATH (agent-browser and Playwright only)

Save screenshots to: `[REPO_ROOT]/tmp/ux_screenshots/[agent-letter]-[description].png`
Example: `/Users/jack.neil/myproject/tmp/ux_screenshots/A-homepage-mobile.png`

**Chrome only:** `claude-in-chrome` does not support saving screenshots to files. Skip file-based screenshot saving — use accessibility tree snapshots instead.

## CRITICAL: TAB ISOLATION (Chrome DevTools/Chrome/Playwright only — not needed for agent-browser)

Before ANY browser action, create your own tab:
- [Chrome DevTools]: `new_page`, then use `select_page` to target your tab for all subsequent calls
- [Chrome]: `tabs_create_mcp`, then use ONLY the returned tab ID for ALL subsequent calls
- [Playwright]: `browser_tabs` action "new", then navigate in the new tab

NEVER interact with other tabs. Work exclusively in your own tab.

## YOUR ASSIGNMENT

- **Page:** [URL]
- **Aspects:** [Aspect 1] + [Aspect 2]
- **Changed files:** [list of changed UI files]
- Focus your checks on areas most likely affected by these file changes.

## PERSONA LENSES

Evaluate ALL your assigned aspects through these persona lenses:

[For each selected persona, include: name, mindset, and evaluation bias from the pool table]

For every check, ask: would this pass for EACH persona? A button that works for a power user might confuse a novice. A layout that looks fine to a developer might look unprofessional to a design consultant. Tag persona-specific issues explicitly in your report:
- **[MEDIUM] [Novice]** Button label "Dispatch" is jargon — unclear to non-technical users
- **[LOW] [Power User]** No keyboard shortcut for the primary action

## ASPECT CHECKLISTS

### Visual & Layout
- [ ] Take a screenshot — look for broken layouts, overlapping elements
- [ ] Check text readability and alignment
- [ ] Verify colors and spacing are consistent
- [ ] Confirm images and icons load correctly
- [ ] Look for clipping, overflow, or z-index issues
- [ ] Compare against what the code change intended

### Responsive
- [ ] Resize to mobile (375px width) — check layout integrity
- [ ] Resize to tablet (768px width) — check layout integrity
- [ ] Resize back to desktop (1280px+) — confirm it restores correctly
- [ ] Check for horizontal scroll at each size
- [ ] Verify touch targets are large enough on mobile (44px minimum)
- [ ] Check text wrapping and truncation behavior

#### Mobile Deep Dive (include ONLY if mobile_deep_dive = true)
- [ ] Thumb-zone accessibility — primary actions reachable in bottom 2/3 of screen?
- [ ] Touch target spacing — >= 8px gap between adjacent tap targets
- [ ] Text readability — body text >= 16px without pinch-zoom
- [ ] Form input types — `type="email"`, `type="tel"`, `type="number"` for mobile keyboards
- [ ] Scroll behavior — no jank, no content hidden behind fixed headers/footers
- [ ] Orientation — landscape mode doesn't break layout

### Interactions
- [ ] Click all buttons — do they respond correctly?
- [ ] Fill out forms — do inputs accept text, show validation?
- [ ] Test navigation — do links and routing work?
- [ ] Check dropdowns, modals, toggles — do they open/close?
- [ ] Verify hover states and focus indicators
- [ ] Test loading states — what shows during async operations?
- [ ] Test error states — what happens on invalid input or failed operations?

### Console & Network
- [ ] Read console messages — any JavaScript errors?
- [ ] Check for unhandled promise rejections
- [ ] Read network requests — any 404s or failed API calls?
- [ ] Look for slow requests (> 3 seconds)
- [ ] Check for deprecation warnings
- [ ] Verify no sensitive data in console output

### Accessibility
- [ ] Take a snapshot (accessibility tree) — check semantic structure
- [ ] Verify heading hierarchy (h1 → h2 → h3, no skips)
- [ ] Check that interactive elements have accessible names
- [ ] Test keyboard navigation (Tab through elements — logical order?)
- [ ] Look for ARIA labels on icons and non-text elements
- [ ] Check color contrast (text should be legible)
- [ ] Verify focus indicators are visible on all interactive elements

### Discoverability (include ONLY if new_feature_detected = true)

**New feature:** [description — e.g., "Account Details page at /accounts/:id"]
**Expected entry points:** [list from Step 2 analysis — existing pages where users would look for this]

#### Entry Point Checks
For each expected entry point page:
- [ ] Navigate to the entry point page. If the page returns a 404, requires auth you don't have, or fails to load — flag as **[MEDIUM] Entry point unreachable during test** and skip to the next entry point. Do not abort the entire Discoverability check.
- [ ] Look for a link, button, menu item, card, or nav entry pointing to the new feature
- [ ] If present: is it visible without scrolling? Is the label clear and self-explanatory?
- [ ] If absent: flag severity based on the entry point's importance:
  - **[HIGH]** if this is the primary or only natural navigation path to the feature
  - **[MEDIUM]** if other entry points exist and this is a secondary path
  - No flag if the missing link is genuinely optional (e.g., a "related" shortcut)

#### Navigation Flow In
- [ ] Follow the most natural path from the primary entry point to the new feature
- [ ] Count the steps/clicks required — 1-2 clicks = good, 3+ for a primary feature = **[MEDIUM]**
- [ ] Is each step's next action obvious? (clear labels, visible affordances, no dead ends)
- [ ] Are there breadcrumbs or "you are here" indicators along the path?

#### First-Use Experience
- [ ] Does the new feature page make its purpose immediately clear without reading docs?
- [ ] Empty state (no data yet): is there a helpful message with a clear call to action?
- [ ] Are controls, buttons, and form fields labeled clearly for a first-time user?
- [ ] Is there any tooltip, hint text, or contextual help to guide initial use?

#### Return Navigation
- [ ] Is there a visible Back button, breadcrumb, or close affordance?
- [ ] Does the browser Back button work correctly (no broken history stack)?
- [ ] After completing the primary action, where does the user land? Is it the right place?
- [ ] Are there cross-links to related features that naturally follow from using this one?

### Accessibility Lens (if available)

Check if an accessibility specialist lens is installed:

```bash
ls ~/.claude/lenses/accessibility.md .claude/lenses/accessibility.md 2>/dev/null | head -1
```

If found, read it and incorporate its "What to check" items into your testing checklist. These are **additive** — they don't replace your existing QA checks. Focus on items that can be verified visually or via browser DevTools:

- Color contrast (use DevTools accessibility panel or Lighthouse)
- Keyboard navigation (tab through the page, verify focus indicators)
- Semantic HTML (inspect elements — buttons should be `<button>`, not `<div>`)
- Form labels (each input has a visible, associated `<label>`)
- Focus management after interactions (modal open/close, route changes)

Skip items that require specialized tooling (screen reader testing, automated WCAG scanners) unless the user specifically requests them.

## REPORT FORMAT

Structure your findings like this:

## [Aspect Name] — [PASS / ISSUES FOUND]

### Issues
- **[CRITICAL/HIGH/MEDIUM/LOW]** [Description]
  - Steps: [how to reproduce]
  - Expected: [what should happen]
  - Actual: [what happens]

### Passed Checks
- [List what looks good]
```

## Step 10: Collect & Report

Wait for all agents to complete. Aggregate findings into a single report:

```
## UX Check Report

**Pages tested:** [N] | **Aspects covered:** [N] of 6 | **Agents used:** [N]
**Browser:** Playwright MCP / Claude-in-Chrome
**Personas applied:** [list of selected personas]
**Mobile deep dive:** Yes / No

### Results by Page

#### [Page URL]
  ✓ Visual & Layout — PASS (Agent A)
  ✗ Responsive — 1 issue (Agent A)
  ✓ Interactions — PASS (Agent B)
  ✓ Console & Network — PASS (Agent B)
  ✓ Accessibility — PASS (Agent C)
  ✓ Discoverability — PASS / N/A (Agent C)

### Issues ([N] total)

1. **[MEDIUM] [Persona]** [Description]
   - Page: [URL]
   - Aspect: [which aspect found it]
   - Steps: [reproduction steps]
   - Expected: [expected behavior]
   - Actual: [actual behavior]

### Summary
[N] pages tested, [N] aspects checked, [N] issues found
```

Deduplicate findings if multiple agents noticed the same issue. Present by severity: CRITICAL > HIGH > MEDIUM > LOW.

If everything passes, say so clearly:
```
## UX Check — All Clear ✓
[N] pages tested, [N] aspects checked, 0 issues found.
```

### Cleanup

After presenting the report, remove the screenshot directory:
```bash
rm -rf "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/tmp/ux_screenshots"
```

This command is **read-only** — it detects and reports issues but does NOT fix them. The detailed issue list is returned to the parent caller (Claude Code), which should then use `superpowers:writing-plans` to build a fix plan from the findings, let the user iterate on it, and execute with `/dcr` verification.

## HARD RULES

- Detect browser tools FIRST — do not spawn agents without a working browser.
- Each agent MUST create its own tab before doing anything else.
- Spawn ALL agents in ONE message (parallel Task calls).
- Cap at 4 agents maximum to avoid browser contention.
- Minimum 2 agents — if only 1-2 aspects are relevant, combine into 2 agents anyway for depth.
- Do NOT ask "should I continue?" after spawning — always collect and report.
- This command is READ-ONLY — detect and report only. Do NOT fix code or invoke /dcr.
- Each /ux invocation is independent — do not reference previous runs.
