# QA Full

> Comprehensive per-feature QA gate. Runs the full multi-dimensional quality fan-out (tests, correctness, security, DB, frontend perf, browser QA, coverage) scoped to the current branch's diff, then emits a pass/fail ship-readiness verdict. Run it when a feature is finished, before /finish-branch and /ship. Use when asked to "run full QA", "qa-full", "feature done — check it", "is this ready to ship", "pre-ship check", or "full quality gate".

- Skill: `bg-szy/qa-full` (Agent Skill)
- Install (CLI): `npx skillmds@latest add bg-szy/qa-full`
- Raw SKILL.md: https://api.skillmd.com/api/skills/bg-szy/qa-full/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: bg-szy (https://skillmd.com/u/bg-szy)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/bg-szy/qa-full

---


# /qa-full

The per-feature QA gate. Where `/daily-qa` is the unattended, repo-wide,
time-windowed **background** sweep, `/qa-full` is the **present-human,
branch-scoped, pass/fail** gate you run the moment a feature is done — before
`/finish-branch` and `/ship`.

```
implement → /qa-full → /finish-branch → /ship
            (this gate)
```

It reuses `/daily-qa`'s trigger matrix (which checks to run based on what
changed) with three deliberate differences:

- **Scope is the branch diff** (`base..HEAD` + working tree), not a time window.
- **Output is a pass/fail verdict**, not an advisory report. CRITICAL/HIGH
  findings **block**.
- **Interactive checks auto-run.** Because a human is present, the checks
  `/daily-qa` only *recommends* (`/web-perf`, browser QA) are run here when
  their triggers fire.

## Hard rules

- **The bar is the superskills quality standard** — TDD/DRY/SOLID/YAGNI plus the
  hard-gate list, both spelled out in full in this skill (Step 10), so you do
  **not** need to open any external file. The canonical written copy is
  `ENGINEERING_STANDARDS.md` in the superskills install (a plugin install exposes
  it at `${CLAUDE_PLUGIN_ROOT}/ENGINEERING_STANDARDS.md`); it is **not** expected
  to exist in the project you're reviewing, so don't flag it as missing. Step 10's
  verdict is exactly "does the diff meet those standards."
- **This is a gate, not a fixer.** Detect and report blockers with the
  smallest viable fix; do **not** mutate source, open PRs, or push. The user
  fixes, then re-runs `/qa-full`. (For an auto-fixing flow, that's a future
  `--fix` mode — not this command.)
- **Ground every finding in concrete evidence**: file:line, failing test name,
  log snippet, severity as the underlying tool produced it. No speculation.
- **Separate blockers from warnings.** Only test/build failures and
  CRITICAL/HIGH findings block. Everything else is a warning that ships with a
  follow-up note.
- **Scope stays on the diff.** Run every sub-check against the changed files,
  not the whole repo — keep it fast and signal-dense.
- **Never claim SHIP-READY without receipts.** The verdict must cite the exact
  checks that ran, what passed, and what was skipped (and why).
- **No silent skips — mandatory accounting.** Every Phase-4 check (security +
  performance, Steps 4–8) must resolve to exactly one of: **RAN** (with evidence),
  **SKIPPED** (with a stated reason — e.g. "no reachable dev server", "scanner
  not authorized in this env"), or **NOT-TRIGGERED** (its diff trigger didn't
  fire). A check whose trigger fired but that neither ran nor was explicitly
  skipped-with-reason is an **unaccounted check ⇒ NOT READY**. "Recommend-only"
  is not an allowed resting state for a *triggered* check — it must become RAN or
  SKIPPED(reason). Projects may mark specific checks **MANDATORY** in `CLAUDE.md`
  (e.g. `/pentest` on a payments service), and for those, SKIPPED is itself a
  blocker — only RAN with evidence passes.

## Project configuration (`CLAUDE.md`)

This gate reads the project's root `CLAUDE.md` for a few optional settings. They
are plain prose (CLAUDE.md is agent instructions, not a config file) — look for a
`## qa-full` section and honor whatever it states. A project that wants to *force*
specific checks to actually run writes something like:

```markdown
## qa-full

- Mandatory checks (must RUN with evidence — a skip is a blocker): `/pentest`, `/defense`
- Hard perf gate: LCP ≤ 2.5s and INP ≤ 200ms on `/` and `/checkout` (breach blocks)
- Design is a gate: run `/design-audit` on any UI change, don't just recommend it
- Dev URL: http://localhost:3000   (for `/web-perf`)
- Test/build: `pnpm test` and `pnpm build`
```

Recognized settings (all optional; absence = the defaults in the steps below):
- **Mandatory checks** — listed commands must read RAN in the ledger; SKIPPED is a
  blocker (Step 4/10). Use for compliance-critical surfaces (payments, auth, PII).
- **Hard perf gate** — turns a `/web-perf` budget breach from a warning into a
  blocker (Step 6).
- **Design is a gate** — auto-runs `/design-audit` (read-only) and blocks on its
  findings instead of recommending (Step 8).
- **Dev URL / Test+build commands** — feed Steps 6 and 2 so they don't have to
  guess.

If there is no `## qa-full` section, run with the built-in defaults — nothing here
is required.

## Step 1: Establish the diff scope

1. Detect the base branch: `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`,
   else `git symbolic-ref refs/remotes/origin/HEAD`, else fall back to `main`/`master`.
2. If `$ARGUMENTS` names a base branch or `--scope <paths>`, use it.
3. Compute the changed-file set: `git diff --name-only <base>...HEAD` plus
   uncommitted changes (`git status --porcelain`). This set drives every
   trigger below.
4. Record at the top of the report: base branch, commit range, changed-file
   count, and whether the working tree is dirty.

If there is no diff against base, stop and say so — there is nothing to gate.

## Step 2: Tests & build (always — hard blocker)

1. Find the project's test/build commands from `CLAUDE.md`; if absent, infer
   from `package.json` scripts, `Makefile`, `pyproject.toml`, etc. If you
   cannot determine them, **ask** rather than guess.
2. Run the test suite and the build. Capture exact failures (test name +
   verbatim error in a code block).
3. **Any failing test or broken build is a hard blocker** — the gate cannot be
   SHIP-READY. Recommend `/verify` to confirm a fix, or `/debug` /
   `/investigate` to root-cause.

## Step 3: Correctness — `/code-review` (always, auto-run)

Run `/code-review` scoped to the diff (`base..HEAD`). Because this is a
pre-ship gate, default to a **higher local tier** (`high`) than the daily pass.
`/code-review` reads the diff only — no fix mode here (gate, not fixer).

- Fold correctness findings into the report. **CRITICAL/HIGH block.**
- The `ultra` tier (deep multi-agent cloud review, billed) is **recommend-only**
  — surface the exact command when a finding is high-stakes; the user launches it.

## Step 4: Security — `/defense` (always, auto-run)

Run `/defense` scoped to the changed files (OWASP Top 10 / secrets / auth /
crypto / data-protection). Diff-only, no external tools, no auth prompt.

- **CRITICAL/HIGH block.** MEDIUM/LOW are warnings.
- `/pentest` is an external scanner (needs auth confirmation), so it is **not**
  auto-run — but when `/defense` flags CRITICAL/HIGH or auth/crypto/session/
  token/deserialization/file-upload paths changed in the diff, it becomes a
  **triggered, mandatory-accounting check**: either run it (record evidence) or
  record it SKIPPED with a reason (e.g. "scanner unavailable in CI"). Leaving it
  as a bare "recommend" when its trigger fired ⇒ unaccounted ⇒ NOT READY. If
  `CLAUDE.md` marks `/pentest` MANDATORY, SKIPPED is a blocker.
- `/fuzz` needs a running target (like `/web-perf`), so it is **not** auto-run —
  but when the diff adds or changes **new endpoints, input parsing, file-upload
  handling, or deserialization paths**, it becomes a **triggered,
  mandatory-accounting check** exactly like `/pentest`: either run it against a
  reachable dev server (record evidence) or record it SKIPPED with a reason
  (e.g. "no reachable dev server"). Leaving it as a bare "recommend" when its
  trigger fired ⇒ unaccounted ⇒ NOT READY. CRITICAL/HIGH fuzz findings (crash,
  injection, auth bypass surfaced by fuzzing) **block**. If `CLAUDE.md` marks
  `/fuzz` MANDATORY, SKIPPED is a blocker.
- **Infra/deploy config — `/iac-scan`.** When the diff changes infrastructure
  (`Dockerfile`, `docker-compose*`, `*.tf`/`*.tfvars`, k8s/Helm manifests,
  `.github/workflows/**`, `.gitlab-ci.yml`, `Jenkinsfile`, nginx/cloud config —
  see `/iac-scan`'s trigger section for the authoritative list), run `/iac-scan`
  (auto-run path uses **local static linters only**, no network/auth — safe in a
  gate) scoped to those files. CRITICAL/HIGH misconfigs (root container,
  `0.0.0.0/0` ingress, wildcard IAM, privileged pod, untrusted CI trigger, baked-in
  secret) **block**. It's the infra counterpart to `/defense`'s app-code sweep.

## Step 5: Database — `/db-optimize` (auto-run if triggered)

Trigger when changed files match ORM models, migrations, query builders
(`**/models/**`, `**/migrations/**`, `**/queries/**`, `**/*repository*`,
`**/*.sql`), raw SQL in the diff, or new ORM calls (`.find`, `.where`,
`.includes`, `.join`, `.preload`). Run `/db-optimize` scoped to matched files.

- N+1s and missing indexes on hot paths are **blockers**; other suggestions are
  warnings. If no trigger matched, record it **NOT-TRIGGERED** (no DB/ORM/SQL in
  the diff) in the ledger rather than dropping it.

## Step 6: Frontend perf — `/web-perf` (auto-run if triggered)

> This is a key difference from `/daily-qa`, which only *recommends* `/web-perf`.
> Here a human is present and a dev server can be started, so **run it**.

Trigger when the diff includes frontend code (`**/*.tsx`, `**/*.jsx`,
`**/*.vue`, `**/*.svelte`, `**/components/**`, `**/pages/**`, `**/styles/**`,
`**/*.css`, `**/*.scss`), new images/fonts/assets, or bundler config
(`next.config.*`, `vite.config.*`, `webpack.config.*`).

1. Find the dev URL (`CLAUDE.md`, or the `dev` script in `package.json`).
   If no running app and none can be started, record the check as
   **SKIPPED with the reason** ("no reachable dev server") in the accounting
   ledger — do not block on an environment you can't reach, but do **not** let it
   vanish silently. (A bare "recommend-only" with no reason for a *triggered*
   frontend diff is unaccounted ⇒ NOT READY.)
2. Run `/web-perf` against the affected routes. Report Core Web Vitals (LCP,
   INP, CLS) vs. any known budget.
- A measured regression past budget is a **warning** by default (perf is rarely
  a hard ship-blocker) unless `CLAUDE.md` defines a hard perf gate, in which
  case treat a breach as a blocker.
- **Recommend `/perf-profile`** (do not auto-run — it needs a representative
  workload, not a diff) when the diff touches hot server-side paths, the change
  is pre-launch, or `/db-optimize`/`/web-perf` point at a bottleneck that needs
  application-level execution timing to localize. This is the app-layer
  counterpart to `/web-perf` (frontend) and `/db-optimize` (DB).

## Step 7: Browser QA — `/qa-only` (auto-run if UI changed)

> Use `/qa-only` (report-only), **not** `/qa`. A gate must not mutate source.

Trigger when the diff includes UI/frontend code or route handlers serving HTML.
Run `/qa-only` scoped to the affected surface; fold its health score and repro
steps into the report.

- Broken user-facing flows (CRITICAL/HIGH bugs in the QA report) are **blockers**.
- If the user wants the test→fix→re-verify loop instead, recommend `/qa`
  (interactive, mutates code) as a follow-up — outside this gate.

## Step 8: Design audit — recommend (auto-run optional)

When the diff includes UI changes, **recommend `/design-audit`** for visual
consistency, hierarchy, accessibility, and AI-slop tells. `/design-audit` is
**read-only** — it audits and produces a design plan, so it's the gate-correct
visual counterpart to `/qa-only` (Step 7): together they cover *does it work* +
*does it look right* on a frontend change without mutating source. This is a
quality warning layer, not a blocker. Auto-run it only if the project treats
design as a gate (per `CLAUDE.md`); otherwise output the command.

- **Do NOT auto-run `/design-review`** here — it *fixes and commits* code, which
  a gate must not do. Recommend it as a **follow-up** to fix what `/design-audit`
  flags, run by the user after the gate.
- **Accessibility — `/a11y`.** When the UI change is *heavy and likely to affect
  assistive tech* — new/changed interactive components, forms, ARIA/`role`/
  `tabindex`, focus/keyboard handling, images, color/contrast, or motion/animation
  (not a pure spacing/copy tweak — see `/a11y`'s trigger section for the
  authoritative list) — run `/a11y`'s **static** pass (read-only, diff-scoped, safe
  in a gate) and fold its CRITICAL/SERIOUS findings into the ledger. A control no
  screen-reader or keyboard user can operate is a **blocker**. Recommend `/a11y`'s
  dynamic axe pass when a dev URL is reachable.
  - **Scope split with `/design-audit`:** `/design-audit` owns *visual* quality
    (consistency, hierarchy, AI-slop); `/a11y` owns *WCAG / assistive-tech
    correctness* (screen-reader, keyboard, contrast ratios). They overlap on
    contrast only — treat `/a11y`'s measured contrast finding as authoritative.

## Step 9: Coverage — untested paths

For each changed file, locate its test (sibling `*.test.*`, parallel `tests/`).
Use coverage data if present (`coverage/`, `lcov.info`, `.coverage`); else do a
structural check for new exported functions / new branches / new error paths
without a corresponding assertion.

- New **public** surface with zero tests is a **blocker** for a feature
  completion gate. Draft one focused failing-then-passing test per gap (output
  as a code block — do not apply). Internal helpers without tests are warnings.
- This step is a **gate check only** — draft-and-report, never apply (gates
  don't mutate source). To actually **close** the gaps found here — including
  edge/corner cases and past-regression coverage beyond just "new public
  surface" — recommend `/test-coverage`, which writes and applies the missing
  tests and enforces Google's Testing on the Toilet best practices on them.
- Recommend `/tdd` when a gap is large enough to warrant test-first follow-up.
- Recommend `/playwright` when the untested surface is a **user-facing flow**:
  `/tdd` covers the unit gap and `/qa-only` observes the flow once, but neither
  leaves an e2e regression test behind — `/playwright` does.

## Step 10: Accounting ledger + ship-readiness verdict

First build the **accounting ledger** — a row per Phase-4/Phase-5 check, each
resolved to RAN (evidence) / SKIPPED (reason) / NOT-TRIGGERED / MANDATORY-FAIL.
**The verdict cannot be SHIP-READY while any triggered check is unaccounted.**

**Phase-4 accounting (security + performance — what this gate enforces "was done"):**
- Steps 4–8 each get a ledger row. A triggered check with no RAN evidence and no
  SKIPPED reason is an **unaccounted-check blocker**.
- `/pentest`, `/fuzz`, `/perf-profile` are accounted the same way once their trigger fires.
- Any check `CLAUDE.md` marks MANDATORY must be RAN with evidence — SKIPPED ⇒ blocker.

**Phase-5 accounting (honest scope):** `/qa-full` *is* the entry to Phase 5, so it
can only enforce the **pre-ship** half. It **cannot** verify `/finish-branch`,
`/ship`, or `/land-and-deploy` — those run *after* this gate, so do not claim
they're done. What it does enforce:
- Tests + build were **freshly run this invocation** (Step 2) — no stale results
  (the `/verify` discipline). Stale/absent fresh evidence ⇒ NOT READY.
- A passing verdict is the **hard precondition** for ship: only on SHIP-READY do
  you hand off *"Proceed to `/finish-branch` then `/ship`."*

Then the verdict:

- **SHIP-READY** — zero blockers **and** every triggered check accounted for.
  List warnings + follow-ups, then hand off to `/finish-branch` → `/ship`.
- **NOT READY** — one or more blockers (including any unaccounted/MANDATORY-FAIL
  check). List each with its file:line/test-name/missing-check evidence and the
  smallest fix. Tell the user to fix and re-run `/qa-full`.

Blocker set (any one ⇒ NOT READY — this is the authoritative list for the gate;
it mirrors the superskills `ENGINEERING_STANDARDS.md`, kept in sync by the
maintainer — you do not need to read that file to run this gate):
- failing test or broken build, or test/build not freshly run this invocation (Step 2)
- `/code-review` CRITICAL/HIGH correctness finding (Step 3)
- `/defense` CRITICAL/HIGH security finding (Step 4)
- `/fuzz` CRITICAL/HIGH finding — crash, injection, or auth bypass surfaced by fuzzing (Step 4)
- `/pentest` CRITICAL/HIGH vulnerability, when it ran (Step 4)
- N+1 / missing index on a hot path (Step 5)
- CRITICAL/HIGH browser-QA bug in a user-facing flow (Step 7)
- `/a11y` CRITICAL finding — a control unusable by screen-reader/keyboard (Step 8)
- `/iac-scan` CRITICAL/HIGH infra misconfig (Step 4)
- new public surface with zero tests (Step 9)
- a hard perf gate breach, only if `CLAUDE.md` defines one (Step 6)
- **a triggered Phase-4 check left unaccounted** — neither RAN with evidence nor
  SKIPPED with a stated reason (Steps 4–8)
- **a `CLAUDE.md`-MANDATORY check that was SKIPPED** rather than run

## Report format

Write to `qa-full-reports/<branch>-<YYYY-MM-DD>.md` (create dir; add to
`.gitignore`). Structure:

```markdown
# QA-Full — <branch> @ <YYYY-MM-DD>

Base: <base>  Range: <base>..HEAD  Changed files: N  Working tree: clean|dirty

## VERDICT: SHIP-READY ✅ | NOT READY ⛔

### Blockers (must fix before /finish-branch)
1. <file:line> — <evidence> — <minimal fix>
- (or) None.

### Warnings (ship with a follow-up note)
- …

## Accounting ledger (every triggered check must be RAN or SKIPPED-with-reason)
| Check | Phase | Status | Evidence / reason |
|-------|-------|--------|-------------------|
| Tests & build (Step 2)  | 5-pre | RAN (fresh) / FAIL | exact command + result |
| /code-review (Step 3)   | 3     | RAN | tier used, N findings |
| /defense (Step 4)       | 4     | RAN | N findings |
| /iac-scan (Step 4)      | 4     | RAN / NOT-TRIGGERED | infra/deploy files changed? |
| /pentest (Step 4)       | 4     | RAN / SKIPPED(reason) / NOT-TRIGGERED | sensitive paths? |
| /fuzz (Step 4)          | 4     | RAN / SKIPPED(reason) / NOT-TRIGGERED | new endpoints / input parsing? |
| /db-optimize (Step 5)   | 4     | RAN / NOT-TRIGGERED | DB/ORM/SQL in diff? |
| /web-perf (Step 6)      | 4     | RAN / SKIPPED(reason) / NOT-TRIGGERED | dev URL / "no server" |
| /perf-profile (Step 6)  | 4     | RAN / SKIPPED(reason) / NOT-TRIGGERED | pre-launch / hot path? |
| /qa-only (Step 7)       | 4     | RAN / NOT-TRIGGERED | health score |
| /design-audit (Step 8)  | 4     | RAN / SKIPPED(reason) / NOT-TRIGGERED | UI changed? |
| /a11y (Step 8)          | 4     | RAN / SKIPPED(reason) / NOT-TRIGGERED | heavy UI / a11y-affecting? |
| Coverage (Step 9)       | 5-pre | RAN | N gaps, drafted tests |

> No row may be blank or "recommend" for a check whose trigger fired — that is an
> unaccounted-check blocker. `CLAUDE.md`-MANDATORY checks must read RAN.

## Recommended follow-up commands
- `/code-review ultra` — (only if a high-stakes correctness concern)
- `/review` — (heavier staff-level production-readiness pass; distinct from the
  diff-bug focus of `/code-review` — recommend when the change is architecturally
  significant or touches a critical path)
- `/cso` — (**backstop**: only if the diff crosses a new trust boundary — new
  auth/endpoint/external-input/deserialization — and there's no evidence threat
  modeling happened at plan time; threat modeling belongs in `/write-plan`, this
  is the late catch)
- `/pentest` — (only if /defense found CRITICAL/HIGH or sensitive paths changed)
- `/fuzz` — (only if the diff added endpoints / input parsing / uploads /
  deserialization and it was SKIPPED in the ledger — needs a running target)
- `/perf-profile` — (app-level execution profiling; pre-launch or when a
  hot path / measured bottleneck needs localizing)
- `/qa` — (interactive test→fix loop, if Step 7 found user-facing bugs)
- `/design-audit` — (if UI changed; read-only visual/a11y audit, alongside `/qa`)
- `/a11y` — (if heavy UI likely to affect screen-reader/keyboard/contrast; dynamic axe pass needs a dev URL)
- `/iac-scan` — (if infra/deploy config changed; static, plus `/pentest` if HIGH/CRITICAL)
- `/playwright` — (if Step 9 found untested user-facing flows; leaves e2e
  regression tests behind)
- `/simplify` — (reuse/simplification/efficiency cleanups; mutates code, so it
  runs after the gate, not during it)
- `/design-review` — (to *fix* what `/design-audit` flags; mutates + commits, so
  it runs after the gate, not during it)
- `/finish-branch` → `/ship` — (only if VERDICT is SHIP-READY)
```

Print the verdict + a 5-line summary to the chat.

## Anti-patterns (do not do)

- Mutating source, opening PRs, or pushing — this is a gate, not a fixer.
- Declaring SHIP-READY while a check was skipped without saying which and why.
- Running any sub-check against the whole repo instead of the diff.
- Auto-running `/qa` (mutates) instead of `/qa-only` (reports).
- Blocking on `/web-perf` when no dev server is reachable — downgrade to
  recommend and note it.
- Treating MEDIUM/LOW findings as blockers (noise) or hiding CRITICAL/HIGH in
  the warnings list.

## Related commands

Reuses the trigger matrix from `/daily-qa` (see `skills/daily-qa/SKILL.md`
Step 7 for the canonical globs). Differences: branch-scoped, gate semantics,
interactive checks auto-run.

Auto-run (diff-scoped, non-mutating):
- `/code-review` — correctness (Step 3); local tiers only.
- `/defense` — OWASP/secrets/auth/crypto (Step 4).
- `/iac-scan` — when infra/deploy config changed; static infra misconfig scan (Step 4).
- `/db-optimize` — when DB/ORM/SQL changed (Step 5).
- `/web-perf` — when frontend changed and a dev URL is reachable (Step 6).
- `/qa-only` — when UI changed; report-only (Step 7).
- `/a11y` — static pass when a heavy/a11y-affecting UI change landed (Step 8).
- `/design-audit` — read-only visual/a11y audit when UI changed (Step 8).

Recommend-only:
- `/code-review ultra` — deep multi-agent cloud review; billed + user-triggered.
- `/review` — staff-level production-readiness review; heavier, architectural —
  recommend for significant or critical-path changes (not a substitute for the
  Step 3 `/code-review` pass).
- `/cso` — OWASP+STRIDE **threat modeling**. Design-time by nature, so its real
  home is `/write-plan`; here it's only a **backstop** when a trust-boundary
  change reaches the gate without a threat model.
- `/pentest` — external scanner needing auth confirmation.
- `/fuzz` — web fuzzing against a running target; triggered-accounting like
  `/pentest` when the diff adds endpoints/input parsing (Step 4).
- `/perf-profile` — app-level execution profiling; needs a representative
  workload, so it's a pre-launch / bottleneck-localizing follow-up, not a gate.
- `/qa` — interactive test→fix→re-verify loop (mutates code).
- `/design-audit` — read-only visual/a11y audit → design plan; the gate-correct
  design check, paired with `/qa-only` on any UI change.
- `/design-review` — *fixes and commits* visual issues (mutates); a post-gate
  follow-up to apply what `/design-audit` found, never run inside the gate.
- `/playwright` — e2e regression tests for untested user-facing flows (Step 9).
- `/test-coverage` — *writes and applies* the missing unit/integration/e2e
  tests that Step 9 only drafts as a gate check; the fixer counterpart.
- `/simplify` — post-gate quality cleanups on the diff (mutates code); the
  read-only equivalent already runs inside Step 3's `/code-review`.
- `/verify`, `/debug`, `/investigate`, `/tdd` — per-issue follow-ups.

Hand-off (only when SHIP-READY):
- `/finish-branch` — choose how to integrate the work.
- `/ship` — sync, bump VERSION, changelog, PR.

