.claude/skills/browser-verification/SKILL.md
Verify browser-based acceptance criteria using ExecuteAutomation Playwright MCP with multi-tool fallback chain. Invoked by verify-task and phase-checkpoint for BROWSER:* criteria.
npx skillsauth add benjaminshoemaker/ai_coding_project_base browser-verificationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Verify UI-related acceptance criteria using MCP browser tooling with evidence (snapshots, logs, or screenshots).
For each criterion, use metadata from Verify::
/login)[data-testid="login-form"])Copy this checklist and track progress:
Browser Verification Progress:
- [ ] Step 1: Load configuration
- [ ] Step 1.5: Resolve base URL (preview or localhost)
- [ ] Step 1.6: HTTP-first evaluation (skip browser if possible)
- [ ] Step 2: Select browser tool (with fallback chain)
- [ ] Step 3: Authenticate (if required)
- [ ] Step 4: Navigate and validate
- [ ] Step 5: Capture evidence
- [ ] Step 6: Handle errors and recover
- [ ] Step 7: Report results
Read .claude/verification-config.json for:
Dev Server:
devServer.commanddevServer.urldevServer.startupSecondsAuthentication:
auth.strategy — none, env, or storage-stateauth.loginRoute — URL path for login formauth.credentials.usernameVar — Env var name for usernameauth.credentials.passwordVar — Env var name for passwordauth.storageState — Path to save/load session stateBrowser:
browser.tool — auto, executeautomation, browsermcp, playwright, chromedevtoolsbrowser.headless — Run headless (default: true)browser.timeout — Default timeout in ms (default: 30000)browser.navigationTimeout — Navigation timeout in ms (default: 60000)Deployment:
deployment.enabled — Whether to use preview deploymentsdeployment.useForBrowserVerification — Use preview URL for browser testsdeployment.fallbackToLocal — Fall back to localhost if no previewdeployment.waitForDeployment — Wait for deployment to be readydeployment.deploymentTimeout — Max seconds to waitIf config is missing or incomplete, ask the human to run /configure-verification.
Verify the config file was read successfully by confirming all required fields are present. If any field is null or missing, log which fields are absent before proceeding.
Determine the base URL for browser verification based on deployment configuration.
IF deployment.enabled AND deployment.useForBrowserVerification:
1. Invoke vercel-preview skill to get preview URL
2. IF URL found:
BASE_URL = preview URL
Skip dev server startup (not needed)
Log: "Using Vercel preview: {URL}"
3. ELSE IF fallbackToLocal:
BASE_URL = devServer.url
Log: "WARNING: No preview URL found, falling back to localhost"
Ensure dev server is running
4. ELSE (no fallback):
BLOCK with error: "No preview deployment and fallback disabled"
ELSE:
BASE_URL = devServer.url (current behavior)
Ensure dev server is running
When deployment is enabled, invoke the vercel-preview skill:
waitForDeployment enabled and deployment building, wait up to timeoutcurl -sf {URL} -o /dev/null before proceeding. If unreachable, log a warning and fall back to localhost.BASE URL RESOLUTION
===================
Mode: Vercel Preview | Local Dev Server | Fallback to Local
URL: {resolved URL}
Branch: {git branch} (if preview)
Status: Ready | Building | Not Found (if preview)
All subsequent steps use BASE_URL instead of hardcoded devServer.url:
BASE_URL for curl checksBASE_URL + routeBASE_URL in all generated URLsIMPORTANT: When browser verification falls back to manual, all URLs in the generated instructions MUST use BASE_URL. This ensures manual verification guides point to the correct environment (preview URL when deployment enabled).
Before launching browser tools, evaluate if the criterion can be satisfied with HTTP. This optimization skips browser overhead for criteria that don't require DOM inspection.
| Criterion Pattern | HTTP Check | Skip Browser If... |
|-------------------|------------|-------------------|
| "Page loads at {url}" | curl -sf {url} | HTTP 200 returned |
| "API returns {status}" | curl -o /dev/null -w "%{http_code}" {url} | Status matches |
| "Endpoint responds with {data}" | curl -s {url} \| jq/grep | Data found |
| "Service health check" | curl -sf {url}/health | Health endpoint OK |
| "Redirect to {url}" | curl -sI {url} \| grep Location | Location header matches |
# Generic page accessibility check
curl -sf "{BASE_URL}{route}" -o /dev/null && echo "HTTP_PASS" || echo "HTTP_FAIL"
# Response content check
curl -s "{BASE_URL}{route}" | grep -q "{expected_text}" && echo "HTTP_PASS" || echo "HTTP_FAIL"
# Status code check
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "{url}")
[ "$HTTP_CODE" = "{expected}" ] && echo "HTTP_PASS" || echo "HTTP_FAIL"
If HTTP_PASS and criterion does NOT require:
selector, data-testid, visible)screenshot, layout, style)click, type, hover)console, errors, warnings)performance, timing)Then:
Otherwise:
Automatically detect and use the best available browser tool. Try tools in order until one responds:
1. ExecuteAutomation Playwright MCP (primary)
- Package: @executeautomation/playwright-mcp-server
- Test: Check for mcp__playwright__* or mcp__executeautomation__* tools
- Why primary: Most stable, actively maintained (312+ commits), 143 device presets
- Avoids @playwright/mcp@latest beta instability issues
2. Browser MCP (if extension installed)
- Source: browsermcp.io browser extension
- Test: Check for mcp__browsermcp__* tools
- Advantage: Uses existing browser profile (stays logged in, avoids bot detection)
- Requires: User has Browser MCP extension installed
3. Microsoft Playwright MCP (pinned version)
- Package: @anthropic-ai/mcp-server-playwright (pinned, NOT @latest)
- Test: Check for mcp__playwright__* tools (if not already found)
- Why fallback: Official but @latest includes unstable betas
- Use pinned version only
4. Chrome DevTools MCP (basic fallback)
- Test: Call mcp__chrome-devtools__list_pages
- Often pre-installed with Claude Code
- Limited: Not designed for automation, less stable for complex workflows
- Use for: Simple navigation, screenshots, basic interactions
5. Manual Verification (last resort) — SOFT BLOCK
- If all tools fail, do NOT silently continue
- Display warning and prompt user:
```
⚠️ NO BROWSER TOOLS AVAILABLE
Attempted to detect browser MCP tools but none responded:
- ExecuteAutomation Playwright: {status}
- Browser MCP: {status}
- Microsoft Playwright: {status}
- Chrome DevTools: {status}
Browser criteria cannot be verified automatically.
Options:
1. Continue anyway (criteria become manual verification)
2. Stop and configure browser tools first
To enable automated browser verification, add to ~/.mcp.json:
{
"mcpServers": {
"executeautomation-playwright": {
"command": "npx",
"args": ["-y", "@executeautomation/playwright-mcp-server"]
}
}
}
```
- Use AskUserQuestion to let user choose:
- "Continue with manual verification" → Mark criteria as BLOCKED, list for human
- "Stop to configure tools" → Halt and provide detailed setup instructions
Log tool selection:
Browser Tool: ExecuteAutomation Playwright MCP (auto-detected)
Fallback chain: Browser MCP → Microsoft Playwright → Chrome DevTools → Manual (soft block)
Verify the selected tool responds by issuing a lightweight probe (e.g., browser_snapshot or list_pages). If the probe fails, move to the next tool in the chain immediately.
Skip if auth.strategy is none.
storage-stateauth.storageState file exists and is recent (< 24h)env (or storage-state with invalid session)auth.loginRouteauth.storageState for reuseIf login fails after 2 attempts:
For each browser criterion:
BASE_URL — preview or localhost per Step 1.5)browser.navigationTimeoutCapture evidence appropriate to the criterion type using the selected browser MCP tool (not Bash commands):
| Type | Evidence | |------|----------| | DOM | Accessibility snapshot, selector details | | VISUAL | Screenshot | | CONSOLE | Console log excerpt | | NETWORK | Request/response summary | | PERFORMANCE | Timing metrics (if supported) | | ACCESSIBILITY | ARIA/semantic checks and notes |
Save evidence under .claude/verification/ with stable names:
browser-{task-id}-{criterion-id}.pngbrowser-{task-id}-{criterion-id}.jsonAfter saving each evidence file, verify it was written by checking that the file exists and is non-empty (e.g., ls -la .claude/verification/browser-{task-id}-{criterion-id}.*). If the file is missing or zero-length, retry the capture once before marking evidence as unavailable.
Detect failures:
Recovery procedure:
1. Log the error with context:
"Tool {name} returned: {error}"
2. If transient error (timeout, connection):
- Wait 2 seconds
- Retry current operation (max 2 retries)
3. If persistent error or tool unavailable:
- Attempt tool restart (kill and re-init MCP)
- If restart succeeds, retry current criterion
4. If restart fails:
- Try next tool in fallback chain
- Log: "Switching from {current} to {fallback}"
5. If all tools exhausted:
- Mark remaining criteria as BLOCKED
- Report: "Browser tools unavailable after trying:
- ExecuteAutomation Playwright: {error}
- Browser MCP: {error or 'not installed'}
- Microsoft Playwright: {error}
- Chrome DevTools: {error}
Manual verification required."
Session degradation detection:
Some tools work initially then fail after extended use. Monitor for:
If detected, proactively switch to fallback before complete failure.
Return a structured result for each criterion:
BROWSER VERIFICATION RESULT
---------------------------
Instruction ID: [ID]
Status: PASS | FAIL | BLOCKED
Type: DOM | VISUAL | CONSOLE | NETWORK | PERFORMANCE | ACCESSIBILITY
Target: Vercel Preview (https://...) | Local Dev Server (http://localhost:...)
URL: [full URL tested] | Viewport: [width]x[height]
Finding: [What was observed]
Expected: [What was expected]
Evidence:
- {path}
Suggested Fix: [If FAIL]
| Condition | Action | Status | |-----------|--------|--------| | Dev server unreachable | Report failing command | BLOCKED | | Selector missing | Capture screenshot | FAIL | | Auth fails | Check credentials | BLOCKED | | Tool unavailable | Try fallback chain | Continue or BLOCKED | | Tool returns undefined | Retry then switch | Continue or BLOCKED | | All tools fail | Require manual verification | BLOCKED |
| Situation | Action |
|-----------|--------|
| Config file .claude/verification-config.json missing or unparseable | Ask the user to run /configure-verification and halt verification |
| Dev server unreachable after startup timeout | Report the failing command and its stderr output; mark criteria as BLOCKED |
| Browser MCP tool returns "undefined" or connection error | Retry once after 2 seconds, then fall to the next tool in the fallback chain |
| Authentication fails after 2 login attempts | Mark criteria as BLOCKED with message; do NOT expose credential values |
| Evidence file write produces zero-byte file | Retry capture once; if still empty, note "evidence unavailable" in report |
See TOOL_NOTES.md for detailed information on each browser MCP tool option:
REMINDER: All URLs in manual fallback instructions MUST use BASE_URL variable, not hardcoded URLs.
testing
Audit project alignment with VISION.md, identify SDLC gaps, and generate feature proposals. Use when reviewing strategic direction or planning new features.
development
Run code-verification on a specific task. Use to verify a single task's acceptance criteria after implementation.
testing
Resolve Vercel preview deployment URL for the current git branch. Invoked by browser-verification when deployment.enabled is true, or directly to check deployment status. Use to check deployment status or when browser verification needs a URL.
tools
Discover and sync all toolkit-using projects with the latest skills. Use when skills are modified, after the post-commit hook reminds you, or to batch-sync multiple projects.