autonomous-exploration
Skill1 starsChanged 2 months agoMITView on GitHub
Drive the qa-supreme runner to click every reachable control of a web app, follow every link and tab, count each click on screen, and report dead buttons, broken states and click errors. Use when asked to "test the whole app", "click everything", "find dead buttons", "map the UI", or when there is no test suite at all and coverage must start somewhere.
- Installs packages
In this repository34 other files it gives its agents.
- a11y-auditSkill
- api-contract-testingSkill
- bug-reproSkill
- chaos-resilienceSkill
- ci-wiringSkill
- contract-testing-pactSkill
- coverage-ratchetSkill
- database-testingSkill
- e2e-authoringSkill
- environment-paritySkill
- exploratory-chartersSkill
- false-positive-hunterSkill
- flake-forensicsSkill
- i18n-l10n-testingSkill
- load-and-stressSkill
- mutation-proofSkill
- never-break-prodSkill
- payment-testingSkill
- perf-budgetSkill
- qa-triageSkill
- regression-curationSkill
- release-gateSkill
- responsive-mobile-testingSkill
- risk-mapSkill
- root-cause-protocolSkill
- security-regressionSkill
- smoke-and-sanitySkill
- state-machine-testingSkill
- test-data-managementSkill
- test-strategySkill
- tracking-testingSkill
- transactional-email-testingSkill
- unit-test-authoringSkill
- visual-regressionSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 68
Every control gets one verdict, decided from what the click actually caused:
- Distinctive: line 86
Before listing controls, the runner puts the page into the state a user would actually find: the consent banner is dismissed (recorded, …
- Distinctive: line 129
Use a seeded, disposable account.
- Very specific: line 131
Add data-qa-skip to any element the crawler must never touch.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Autonomous Exploration
The fastest way to learn what an app actually does is to click all of it. This skill drives
the bundled runner (runner/), which performs a breadth-first exploration of every reachable
UI state and produces an evidence report.
Run it
cd runner && npm install # first time only
node bin/qa-supreme.mjs here # detects the project, starts it, tests it, stops it
node bin/qa-supreme.mjs run --url https://app.example.com # full pipeline against a running app
node bin/qa-supreme.mjs watch --url http://localhost:3000 # real window, slowed down, video recordedhere reads the project in the current directory — Next, Vite, CRA, Nuxt, Astro, Remix, Angular,
Django, Rails, Laravel, or a plain static folder — starts it on its own port, waits for it to
answer, runs the pipeline and shuts it down. That is what makes this usable on any project
without configuring anything first.
The on-screen HUD counts every click as it happens, flashes the element being hit, and shows queue depth and error count — so a human watching, a screenshot, or a recorded video all carry the same proof.
Apps behind a login (most of them)
An unauthenticated run against a protected app explores the login page and reports an empty
product. The runner names that instead of pretending: smoke fails with authentication —
target is behind a login, and the run stops there rather than producing noise.
# log in once, keep the session
node bin/qa-supreme.mjs login --url https://app.example.com --login-url https://app.example.com/login \
--user qa@example.com --pass "$QA_PASSWORD"
# every later run reuses it
node bin/qa-supreme.mjs run --url https://app.example.com --storage .qa-supreme/auth.jsonThe login form is found automatically (username/email + password + submit). When the markup
defeats the heuristics, name the fields: --user-selector, --pass-selector,
--submit-selector, --success-selector. Success is judged by the login form being gone, not
by a URL change — SPAs authenticate without navigating.
While a session is active the crawler also refuses to click anything that ends it (log out, sign out), on top of the destructive-action guard. One stray click on "Sign out" would turn every remaining state into the login page.
What it produces
| Signal | Meaning | What you do with it |
clicks performed | interactions actually executed | the coverage number nobody else reports |
states discovered | distinct UI states reached | compare against the sitemap — gaps are unreachable UI |
transitions mapped | control → destination edges | the app's real navigation graph |
| button verdicts | every control judged, not just counted | the list of what is broken and what is dead |
click errors | control refused a click in 4s | overlay traps, disabled-but-visible, z-index bugs |
guarded skips | destructive and session-ending controls not clicked | verify the guard list matches your app |
clicks that needed a retry | control was transiently covered | a rising number means overlay/timing problems |
The button report
Every control gets one verdict, decided from what the click actually caused:
| Verdict | What happened | What it means |
works | navigation, new tab, reload, or a visible change | fine |
network only | nothing visible, but a request went out | probably fine — confirm the effect is real |
dead | no visible change, no request, no error | nobody wired this control |
suspect | a console error or a failed request | wired, but something under it is failing |
broken | an uncaught exception or a 5xx | a defect, with the exception as evidence |
unclickable | refused a click twice from a clean state | an overlay traps it, or it is disabled but looks enabled |
Effects are attributed to a control only when it owns them: errors thrown while a new page loads belong to that page, not to the link that led there. Blaming the link is exactly the false positive this repository exists to hunt, so navigations are judged by what they reached, not by what the destination logged.
What it can see (and what it still cannot)
Before listing controls, the runner puts the page into the state a user would actually find: the consent banner is dismissed (recorded, never counted as a test click), the page is scrolled to the bottom so lazy and virtualised content exists, it waits for the page to stop changing, and hover menus are opened. Then it discovers through the places a naive crawler stops:
| Obstacle | How it is handled |
| Consent / cookie wall | dismissed first, so it cannot swallow every click |
Content below the fold, infinite scroll, IntersectionObserver | scrolled through in steps, and controls found this way are marked as needing that scroll to be reachable again |
| Shadow DOM (web components, design systems) | open shadow roots are walked; the selector pierces them |
| Same-origin iframes | frames are discovered and clicked through a frame locator |
Hash routing (#/reports) | the hash is part of the address and of the state, so three routes are three screens |
| Hover-only menus | triggers are hovered before discovery; their items carry that requirement |
| A control covered by an overlay | reported as unclickable, naming what sits on top of it |
| Something still loading | it waits for the page to settle, then sweeps again — controls that appear late are clicked too |
Still out of reach, and honest about it: canvas and WebGL surfaces with no DOM behind them, drag-and-drop, cross-origin iframes, native OS dialogs, and anything gated behind a captcha.
Reading only one part of the app
node bin/qa-supreme.mjs crawl --url http://localhost:3000 --only "#settings-panel"--only <css> limits discovery to one region — a tab panel, a drawer, the screen you just
built. Everything else on the page is ignored, so the report is about your change and nothing
else. Frames are skipped while a scope is set, because a scope belongs to the host document.
Triaging dead buttons
A dead verdict is not automatically a bug — it may be a no-change tab, an already-active state, or
a control whose effect is server-side only. For each one, answer: what should a user expect
to happen? If the answer is "something", you found a defect before any user did. Record the
confirmed ones as bugs, and add the rest to denySelectors so the next run stays signal.
Safety
By default the crawler refuses to click anything whose label matches a destructive verb (delete, pay, logout, publish, transfer...). That guard is the difference between exploration and an incident.
- Point it at local, preview, or staging environments. Not production.
- Use a seeded, disposable account. Never a real customer's.
--full-sendremoves the guard. Only ever on a throwaway environment you can rebuild.- Add
data-qa-skipto any element the crawler must never touch.
Turning exploration into a suite
Exploration is reconnaissance, not regression protection. Feed what it found back into real
tests: the discovered journeys become e2e-authoring specs, the dead buttons become bug
reports through bug-repro, and the state graph becomes the input to risk-map.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

