Using qa.
From the first run to a CI gate: the session, the exit-code contract, and your agent. Routes are read from Next.js, React Router, TanStack Router, Remix, SvelteKit, Astro and Nuxt apps; the static rules read React and TypeScript.
Quick start: one session.
$ qa verify . --preflight base http://localhost:3000 reachable personas owner, staff, viewer 3 launchers ok rust qa-agent 1.0 prebuilt ready exit 0
Readiness first. Every blocker is named with its fix before anything is measured.
$ qa run . --base http://localhost:3000 --once sweep 41/48 routes × 3 personas × light·dark·390 ✕ P1 overlay menu left open /orders brief .verify/lanes/overlay/brief.md exit 1 7 findings · 7 unmeasured
One command measures, ranks and hands over exactly one brief.
# .verify/lanes/overlay/brief.md cause FilterMenu never unmounts (C1) affects F1 /orders light · F2 /orders dark repro owner → /orders → Filter → Status → row action evidence 2 screenshots · trace.zip · selector div[role=menu] jev 0.91 lead · verified at file:line
Your agent fixes the cause once. Both symptoms close because they share one causal identity.
$ qa run . --base http://localhost:3000 --once ratchet F1, F2 fixed (measured again and gone) scope 41/48 routes · 7 unmeasured, unchanged exit 0 clean within the measured scope
Exit 0 always prints its scope. Seven routes are still unmeasured and still counted.
$ qa init . --workflow wrote .github/workflows/qa.yml (SARIF upload) $ qa show report . --format sarif --out results.sarif $ qa show report . --format github $ qa show report . --format junit --out junit.xml
The same contract gates every PR. Each export keeps the archived gate's exit code, and a crash is exit 2, which never passes.
Session output uses synthetic example data. It is not a measured application run.
Three exit codes. One of them is never a pass.
Clean within the measured scope
It says "within the measured scope" because that is what it means. The scope is printed beside it.
Gating findings, or a regression
Evidence for each finding is archived under .verify/. It exports to SARIF, GitHub annotations and JUnit for your CI.
Could not run
A crash, a missing server, invalid input. A tool that cannot measure has not measured, so 2 never counts as a pass in any gate qa ships.
Built for the agent already in your editor.
Copy the prompt, paste it into your agent, and it knows what qa is and what to run first. The skills behind it are listed on Skills.
- Claude Codeskill + slash commands
- Codexskill
- Cursorskill
- Any MCP clientqa-mcp · 5 tools
- CIGitHub workflow · SARIF · JUnit
qa checks a web frontend by running it. It runs on this machine and never edits source. Exit codes: 0 clean within the measured scope, 1 findings or a regression, 2 could not run (never a pass). Read the frontend-verify skill (SKILL.md) first. If the qa command is not on PATH, stop and tell me. From the app's directory, start with the static run, no browser needed: qa verify . qa show . Then, with the dev server running: Use frontend-verify in this host worktree. Run `qa run <repo> --base URL --once`, read the generated `.verify/lanes/<class>/brief.md`, own the source fixes and commits, then rerun the same command to recheck. Replace <repo> with this app's path and URL with the dev server address. Report the exit code and what was measured.
Code enumerates. Jev screens. Your agent proves.
The qa skill's HUNT, REVIEW and PLAN modes, and the backend-edges pass, send each surface or endpoint to Jev, TypeSafe's System One model, in one batched request. Every flag is a lead, never a finding. A flag becomes a finding only after code confirms the cited file:line and the evidence supports it. How the probability band works →
Only the skill's Jev modes need a key: TYPESAFE_API_KEY or TYPESAFE_JEV_KEY. The qa CLI itself, with every static rule and browser probe, makes no call to Jev.
Any MCP client
A narrow local stdio bridge with five tools: preflight, run, status, next and report. It is pinned to one trusted app at startup and accepts no per-call paths, shell commands or credentials.
$ QA_MCP_REPO=/abs/path/to/app QA_MCP_BASE=http://127.0.0.1:3000 qa-mcp