Exploratory end-to-end QA with a team of agents that drive a real browser like human testers — they click through the whole app, create/fill/submit, screenshot and visually judge rendering + data correctness, capture trace/HAR/console/video evidence, adversarially verify each finding, learn from rejected findings, and codify confirmed bugs (and working flows) as real regression/smoke tests. Use when asked to "test the whole app", "explore for bugs", "QA this web app", "find anything broken on...
Scanned 9/6/2026
Install to Claude Code
npx -y skills add victoraguilarsantamariadev/qa-explore --skill qa-explore --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Qa Explore?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/victoraguilarsantamariadev-qa-explore)More formats (shields.io, HTML) on the badges page.
---
name: qa-explore
description: Exploratory end-to-end QA with a team of agents that drive a real browser like human testers — they click through the whole app, create/fill/submit, screenshot and visually judge rendering + data correctness, capture trace/HAR/console/video evidence, adversarially verify each finding, learn from rejected findings, and codify confirmed bugs (and working flows) as real regression/smoke tests. Use when asked to "test the whole app", "explore for bugs", "QA this web app", "find anything broken on <url>", "test as a user", or to set up/grow an agent-based exploratory E2E suite for any web project. Works cold (no tests yet) or warm (existing Playwright/Cypress suite).
---
# qa-explore
A reusable harness that tests any web app the way a human QA team would, then turns what it learns into a self-growing deterministic E2E suite.
## The loop
```
Step 0 RUN EXISTING SUITE (deterministic, full, cheap) — regression net; AUTO-run by the engine's first phase (skipped on a cold project)
1. EXPLORE one human-tester agent per area: navigate, create, fill, submit, screenshot, judge, capture evidence
2. VERIFY independent skeptics re-run each serious finding (flaky / false-positive killer)
3. REPORT file each verify-confirmed finding as a tracker issue (GitLab/GitHub), idempotently [if tracker configured]
4. TRIAGE a human marks the genuine bugs with the fix label — in the tracker (the gate moved there); LEARN from the rest
5. CODIFY write + self-validate specs: RED regression test per confirmed bug, GREEN smoke per working flow
→ those specs become Step 0 next time. The suite grows itself.
```
Then `/qa-fix` closes the loop: it picks up the labelled issues, fixes them in isolated worktrees, and opens a merge request per bug for human review. (No tracker configured → REPORT is skipped and TRIAGE happens in-chat as before.)
Cold start (no tests): Step 0 is empty and skipped; agents explore first to discover real routes/flows/selectors, then Codify writes the FIRST suite. Never write tests blind from source — exploration is what makes good (non-brittle) tests possible.
## Engine files (invoke via the Workflow tool; do not inline)
- `${CLAUDE_PLUGIN_ROOT}/skills/qa-explore/engine/explore-verify.workflow.js`
- `${CLAUDE_PLUGIN_ROOT}/skills/qa-explore/engine/report-issues.workflow.js` (files findings as tracker issues)
- `${CLAUDE_PLUGIN_ROOT}/skills/qa-explore/engine/codify.workflow.js`
- `${CLAUDE_PLUGIN_ROOT}/skills/qa-explore/qa.config.example.jsonc` (config template)
- Fixing half lives in the sibling `qa-fix` skill (`${CLAUDE_PLUGIN_ROOT}/skills/qa-fix/`).
(If `$CLAUDE_PLUGIN_ROOT` is unset, the skill is at `~/.claude/skills/qa-explore` — resolve the engine paths relative to this SKILL.md.)
## Safety (read before running)
This drives a **real browser as a real user against a live target**. `mode` controls behaviour and is independent of the environment — writing against real production is the user's call. The dials, most→least powerful:
- **`explore` (default)** — create / edit / submit / **delete** (prefixed `qa-…`, best-effort cleanup, not guaranteed). Best for staging / pre-prod.
- **`no-delete`** — write but never delete; the safe middle ground for a sensitive/production target.
- **`read-only`** — zero writes; the cautious choice for real production.
Rules regardless of mode:
- It runs with **your machine's network access** and is confined to `allowedHosts` (defaults to the `baseUrl` host): it never follows links/redirects off-host and never scans other machines — it only goes where the config points it.
- Before any **write-enabled** run (`explore` or `no-delete`), **state the resolved target URL + mode and get a go-ahead**, especially the first time against a new target, and louder if it looks like production. Treat that confirmation as the authorization. Recommend a **dedicated QA account with segregated data** for write runs against production.
## How to run
1. **Resolve config.** Find `qa.config.json` in the project (cwd or its E2E dir). If missing, copy the example and fill `baseUrl`, `appPath`, `login`, `e2eDir`, `framework`, and `domainNotes`. Ask the user only for what you can't infer (base URL, credentials). Read `mode` (`explore` default / `read-only`) and `allowedHosts`, and apply the Safety step above. Also read the **coverage axes**: `viewports` (first = primary full pass, extras = responsive sweeps — mobile/desktop), `roles` (first = primary; extras trigger an **access-control** pass that hunts broken authorization), and `projectType` (`web-spa`/`web-ssr` → Chromium; `electron` → Playwright Electron; `api`/`cli` → HTTP/CLI instead of a browser). Also read `a11y` (default on for web): a free extra pass that runs **axe-core** (WCAG 2 A/AA) on each area's key screens and reports only critical/serious violations — set `a11y: false` to skip. And read `appStates` — the app's operational **modes** (simulation/demo, a feature flag, offline, theme, plan tier, tenant…): the whole suite re-runs in each (first = primary; extras declare an `enter`/`exit` recipe an agent runs + an `expect` note), so the app is tested in **every mode**, not just the active one (findings tagged `[<state>]`). Note whether a `tracker` block is set (`type` = `gitlab`/`github`) — it switches steps 6–7 from in-chat triage to the file-issue → human-mark → `/qa-fix` loop.
2. **Decide scope (cost control — never downgrade the model, scope instead).**
- **full** (default cold start, or a scheduled crawl): cover all areas (recon-discovered or from config). Cache the discovered `areas` back into the config so future runs skip recon.
- **diff** (per-PR): run `git diff --name-only <base>..HEAD`, map changed files → affected areas, and PULL IN any area that depends on changed **shared code or API endpoints** (not just literally-changed files) **plus** any area that has no smoke coverage yet. Pass that subset as `args.areas`. Areas that are stable (green smoke + untouched) are skipped by the agents — but see step 3.
2b. **Coverage mode (`coverage.mode`).** `sample` (default) = one agent per functional area (≤ `maxAreas`): a thorough human-style pass, broad but not guaranteed-complete. `exhaustive` = recon builds a full **inventory** (every route, entity, and enumerable variant — e.g. *every* widget type) and fans out **one unit of work per item** (a separate "create a `<X>` widget" per type, full CRUD per entity, a visit per route), then a **completeness-critic loops** over the inventory covering any gap until none remain (or `maxRounds`/`maxUnits` — drops are **logged, never silent**). Use `exhaustive` when the user wants "test absolutely everything"; expect more tokens (the cost lever is scope, not model). For `exhaustive`, point `sourceHints` at the routes + the widget/component registry + API.
3. **Step 0 — existing suite (the regression net).** This is **automated: the `explore-verify` engine runs it as its FIRST phase** — no manual step. If a deterministic suite EXISTS in `e2eDir` (warm project) it runs the full suite (`npx playwright test --reporter=line,json`, targeting the config `baseUrl`, ~10-min cap); if NONE exists (cold project) it logs "cold start, skipping Step 0". The pass/fail summary is returned as a `step0` entry in the results. Reminder: failing baseline tests are often **stale selectors**, not app bugs — the explore pass adjudicates which, so Step-0 failures are surfaced but NOT auto-counted as confirmed findings. (The agent scope is cheap-cut; the deterministic net is never cut.)
4. **Explore + Verify.** `Workflow({ scriptPath: "<engine>/explore-verify.workflow.js", args: <config-with-scoped-areas> })`. Agents reuse one login session (`storageState.json`) and capture trace/HAR/console/video per finding. It returns confirmed findings per area.
5. **Synthesize + dedup.** Build `<shotsDir>/INFORME.md` + keep the evidence dir. **Dedupe findings that repeat across areas** (e.g. a shared broken component) into one entry. Group by **confidence** (`hard-evidence` vs `judgement`) then severity. Hard-evidence = concrete HTTP status / console error / API mismatch; judgement = a "looks wrong" visual call (provisional — where false positives hide). Link each finding's trace.zip / video for the dev.
6. **Report → tracker (if `tracker.type` is `gitlab`/`github`).** Decide which findings to file: the default policy is `tracker.fileSeverities` (blocker/major/data-sense) **plus** any `hard-evidence` finding, and — for serious findings — only those the Verify pass **confirmed**. **Set `verified` on every finding you file** (`true`/`false` from its Verify verdict; leave it unset when there is none). Only blocker/major are re-run, so a filed `hard-evidence` minor — which includes *every* a11y hit, minor by construction — carries no verdict and the issue will read "not assessed". Never let an unverified finding reach the tracker looking like a confirmed one. Confirm the token env var (`tracker.tokenEnv`) is set without printing it. Then `Workflow({ scriptPath: "<engine>/report-issues.workflow.js", args: { tracker, findings: <chosen>, shotsDir, baseUrl } })`. It dedupes against open issues (by an embedded `qa-fp` fingerprint) so re-runs don't pile up duplicates, and files the rest with the `issueLabels` (it deliberately does **not** apply the human `fixLabel`). Report the issue links. **The triage gate now lives in the tracker:** a human adds `fixLabel` to the genuine bugs; those flow to `/qa-fix`. (No tracker → present findings + `worksWell` in chat and let the user mark each real / not-a-bug, as before.)
**LEARN (always).** For every finding rejected as not-a-bug (in chat, or an issue a human closes as invalid), append a one-line rule to `qa.config.json` `domainNotes` capturing *what looked wrong and why it is actually correct* (e.g. "Status widget is websocket → empty preview is expected"). The harness stops re-flagging that false positive on future runs.
7. **Codify (smokes + cold start).** `Workflow({ scriptPath: "<engine>/codify.workflow.js", args: { ...config, bugs: <approved>, smokes: <chosen working flows> } })`. Each writer agent writes ONE spec into `e2eDir` (matching local conventions) and **self-validates** it. Note: when the tracker loop is active, the **red regression test per bug is written by `/qa-fix`** inside the fix MR (so the MR carries its own proof) — here, focus Codify on GREEN smokes for the `worksWell` flows. On a cold project, generating those smokes bootstraps the regression net so future diff-scoped runs are safe. Those specs become Step 0 next time.
## Cadence (recommended)
- **Per PR:** full deterministic suite (Step 0) + diff-scoped agents → codify new confirmed issues.
- **Nightly/weekly:** full agent crawl as a backstop for anything the diff-scope + smoke coverage missed.
## Notes
- Generalizes best to web/UI apps (the agents' "hands" are a browser). For pure APIs/CLIs the same explore→verify→codify loop applies with HTTP/CLI calls instead of Playwright.
- `domainNotes` is the single biggest lever against false positives and it auto-grows via step 6 — keep it in the repo so the whole team benefits.
- **Stateful-SPA heuristics (auto-applied by the explore engine).** Single-op, reload-between passes miss whole classes of bug. The agents now: **sequence-test** each entity (create AND delete 2-3 in a row WITHOUT reloading); flag **stale-state leaks** (a success/error toast that re-fires just from navigating, or a form that self-redirects on mount — a shared singleton/store holding a terminal state); enforce **notification hygiene** (plain navigation must fire no toast; no duplicate toasts per action); and check **cross-entity parity** (a shared flow — bulk-select+delete, create-form, save-toast, row confirm-modal — must behave identically on EVERY entity; a divergence like "bulk-delete works on installations but does nothing on devices" is the finding). These catch the singleton/DI-state bugs that a full reload masks.
- **Run a second pass against a DEV build** (e.g. `baseUrl: http://localhost:5173`) when the app has one. React StrictMode (dev only) double-invokes effects and surfaces "fires twice / missing cleanup" side-effect bugs (duplicate toasts, double requests) that the production build hides. Model it as an extra `appStates` entry or just a second run with the dev `baseUrl`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!