plugins/workflow/skills/browser-qa/SKILL.md
QA web applications using Chrome DevTools MCP. Use when testing running apps, verifying acceptance criteria against a live UI, checking for console errors, evaluating UI behavior, or running regression checks. Requires the chrome-devtools MCP server to be connected. Complements dm-work:review (code-level) with runtime verification.
npx skillsauth add rbergman/dark-matter-marketplace browser-qaInstall 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.
Test running web applications by actually navigating, clicking, and asserting — not just reading code.
This skill covers standard web applications testable via Chrome DevTools. It is NOT suitable for:
When the evaluator encounters projects outside browser-qa's scope, it should mark runtime criteria as UNTESTABLE and note the recommended verification method.
Find testable criteria from (in priority order):
bd show <id> → check the design field for acceptance criteriadocs/ or history/ for the spec that spawned this worknavigate_page(url: "http://localhost:<port>/<path>")
take_snapshot()
The snapshot returns a text representation of the page's accessibility tree. Each interactive element has a UID you can target with click, fill, etc.
Always snapshot before interacting — UIDs are ephemeral and change on navigation.
For each acceptance criterion, drive the corresponding user flow.
Navigate and verify content:
navigate_page(url: "<target URL>")
wait_for(text: ["<expected content>"])
take_snapshot() # confirm element is present in a11y tree
Fill and submit a form:
take_snapshot() # get current UIDs
fill(uid: "<input-uid>", value: "<test value>") # type into field
click(uid: "<submit-uid>", includeSnapshot: true) # submit + get new state
wait_for(text: ["<success indicator>"]) # wait for result
Multi-field forms (more efficient):
fill_form(elements: [
{ uid: "<email-uid>", value: "[email protected]" },
{ uid: "<name-uid>", value: "Test User" },
{ uid: "<role-uid>", value: "admin" }
])
click(uid: "<save-uid>", includeSnapshot: true)
Keyboard interaction:
press_key(key: "Enter") # submit
press_key(key: "Escape") # dismiss modal
press_key(key: "Tab") # focus next
press_key(key: "Control+A") # select all
Drag and drop:
drag(from_uid: "<source>", to_uid: "<target>", includeSnapshot: true)
After each flow step, verify using the cheapest sufficient method:
Text/element presence (cheapest — prefer this):
take_snapshot()
# Scan the a11y tree for expected text, roles, states
Visual verification (use when layout/styling matters):
take_screenshot()
# Review for correct layout, colors, typography, spacing
Console errors (always check):
list_console_messages(types: ["error"])
# Should be empty. Warnings are informational, errors are failures.
Network request success:
list_network_requests(resourceTypes: ["fetch", "xhr"])
# Verify status codes (200, 201, 204). Flag 4xx/5xx.
Custom JS assertions (for state that isn't visible in the a11y tree):
evaluate_script(expression: "document.querySelector('.toast.success') !== null")
evaluate_script(expression: "window.__APP_STATE__.user.role === 'admin'")
Beyond the specific acceptance criteria, check for collateral damage:
list_console_messages(types: ["error"]) on every page visitedlist_network_requests()emulate(viewport: "375x667,mobile,touch") then re-check key elementsemulate(colorScheme: "dark") then screenshotlighthouse_audit(mode: "snapshot") for quick a11y scoreStructure the report as pass/fail per acceptance criterion:
## QA Report: <bead-id or description>
### Acceptance Criteria Results
| # | Criterion | Result | Notes |
|---|-----------|--------|-------|
| 1 | User can navigate to /settings | PASS | |
| 2 | Form validates email client-side | PASS | Shows red border + message |
| 3 | Save button disabled during submit | FAIL | Button stays enabled |
| 4 | Success toast after save | PASS | |
| 5 | No console errors | PASS | 0 errors |
### Regression Checks
- Console errors: 0
- Network failures: 0
- Mobile responsive: PASS
- Lighthouse accessibility: 92
### Verdict: FAIL (1/5 criteria failed)
Failing criteria:
- #3: Save button not disabled during form submission. The button remains
clickable, allowing duplicate submissions.
Integration with beads: If a criterion fails, create a linked bead:
bd create --title="Save button not disabled during submission" --type=bug --priority=2 --deps discovered-from:<parent-bead>
| Tool | Purpose | When to use |
|------|---------|-------------|
| navigate_page | Go to URL, back/forward/reload | Start of each flow |
| take_snapshot | A11y tree with element UIDs | Before any interaction; for text/structure assertions |
| take_screenshot | Visual capture (PNG) | Layout/styling verification; design quality checks |
| click | Click element by UID | Buttons, links, toggles |
| fill | Input/textarea/select by UID | Single form fields |
| fill_form | Multiple fields at once | Multi-field forms (more efficient) |
| type_text | Raw keystrokes (no targeting) | When you need to type into the focused element |
| press_key | Key/combo (Enter, Escape, Ctrl+A) | Submit, dismiss, shortcuts |
| wait_for | Wait for text to appear | After navigation or async operations |
| drag | Drag element to element | Drag-and-drop UIs |
| list_console_messages | Console output (filter by type) | Error checking — always run |
| list_network_requests | Network activity (filter by type) | API call verification |
| get_network_request | Single request details + body | Deep API response inspection |
| get_console_message | Single console message details | Investigating specific errors |
| lighthouse_audit | A11y, SEO, best practices scores | Quick accessibility check |
| evaluate_script | Run JS in page context | Custom assertions on app state |
| emulate | Viewport, dark mode, network, geo | Responsive/a11y/offline testing |
| upload_file | File input interaction | Upload flows |
take_snapshot over take_screenshot — text is far cheaper than images in contexttake_screenshot only when you need to verify visual appearance (layout, colors, styling)wait_for before asserting — async UI needs time to settle after interactionslist_console_messages(types: ["error"]) is the cheapest smoke test — run it on every pagewait_for expected content after navigation — don't assume instant renderincludeSnapshot: true on click/fill to get the post-action state in one call instead of twofilePath) when running multiple checks to avoid bloating contextlighthouse_audit(mode: "snapshot") is faster than mode: "navigation" (no reload)Cheapest possible verification — use when you just need to know the page works:
navigate_page(url: "<url>")
wait_for(text: ["<any expected text>"])
list_console_messages(types: ["error"]) # should be empty
navigate_page(url: "<form page>")
take_snapshot()
fill_form(elements: [<fields>])
click(uid: "<submit>", includeSnapshot: true)
wait_for(text: ["<success message>"])
list_console_messages(types: ["error"])
list_network_requests(resourceTypes: ["fetch"]) # verify API call
navigate_page(url: "<page>")
wait_for(text: ["<loaded indicator>"])
take_screenshot(filePath: "qa-screenshots/desktop.png")
emulate(viewport: "375x667,mobile,touch")
take_screenshot(filePath: "qa-screenshots/mobile.png")
emulate(colorScheme: "dark")
take_screenshot(filePath: "qa-screenshots/dark-mobile.png")
navigate_page(url: "<page>")
take_screenshot(fullPage: true, filePath: "qa-screenshots/full-page.png")
# Review screenshot for AI slop patterns:
# - Generic purple/blue gradients over white cards
# - Template-default typography and spacing
# - Identical component styling across unrelated sections
# - Over-reliance on rounded corners + drop shadows + blur
# - No distinct identity or mood — looks like every other AI-generated site
development
Initialize a new repository with standard scaffolding - git, gitignore, AGENTS.md, justfile, mise, beads, and timbers. Use when starting a new project or setting up an existing repo for Claude Code workflows.
data-ai
Activate at session start when using Agent Teams for complex multi-agent work. Establishes team lead role with delegation protocols, teammate spawning, model selection, and beads integration. You coordinate the team; teammates implement.
data-ai
Use when creating a worktree, setting up a worktree, starting feature work that needs isolation, or before executing implementation plans. Covers git worktree creation under .worktrees/, gitignore setup, beads integration, and merge guardrails.
data-ai
Activate when you are a delegated subagent (not the orchestrator). Establishes subagent protocol with terse returns, details to history/, file ownership boundaries, and escalation rules. You implement; orchestrator reviews and commits.