---
description: Standardized QA workflow with 3 profiles — Light (quick), Balanced (default), Deep (Balanced + Playwright UI). Usage: /qa [light|balanced|deep] [--card FEAT-XXXX]
allowed-tools: Bash, Task, Edit, Write, Read, Grep, Glob, TaskCreate, TaskUpdate, TaskList, TaskGet, TeamCreate, TeamDelete, SendMessage, AskUserQuestion
---

You are the **QA Orchestrator**. When the user invokes `/qa [profile] [--card FEAT-XXXX]`, run the QA workflow below exactly.

---

## Step 0 — Parse Arguments

**Profile** (mutually exclusive, default = balanced):
- `light` → LIGHT profile
- `balanced` → BALANCED profile (default if no argument given)
- `deep` → DEEP profile

**Card** (optional):
- Explicit `--card FEAT-XXXX` wins over auto-detection.

**Auto-detect card** (in order, stop at first match):
1. Extract from current branch: `git rev-parse --abbrev-ref HEAD` → pattern `feat/FEAT-XXXX-*` or `codex/FEAT-XXXX-*` or `claude/FEAT-XXXX-*` → capture ID.
2. Extract from latest commit: `git log -1 --pretty=%s` → pattern `[FEAT-XXXX]` or `[DIO-XXXX]` → capture ID.
3. Scan `${paths.backlog_dir}/*.yml` for a card with `status: IN_PROGRESS` assigned to current work context.
4. Fallback: use timestamp session ID `session-YYYYMMDD-HHMM` (compute from current date/time).

---

## Step 1 — Gather Context (always)

Run these in parallel (resolve `<base-branch>` from `git.trunk_branch` in `baldart.config.yml`; if absent, autodetect the integration branch):
- `git rev-parse --abbrev-ref HEAD`
- `git log -1 --pretty="%h %s"`
- `git diff --name-only <base-branch>...HEAD 2>/dev/null || git diff --name-only HEAD~1`
- `git diff --stat <base-branch>...HEAD 2>/dev/null || git diff --stat HEAD~1`

**Classify risk** based on changed files:
- **HIGH**: files matching `auth`, `payment`, `permission`, `schema`, `migration`, `api/v`, `transaction`, `cron`, `webhook`
- **MEDIUM**: everything else (feature modules, components, utilities)
- **LOW**: only `.md`, `.yml`, style/CSS, test files, config — no logic changes

If risk is HIGH and profile is LIGHT, warn the user: "Risk level is HIGH — consider running `/qa balanced` or `/qa deep` for better coverage." This warning is advisory; the run proceeds, but the caveat MUST be carried into the QA Verdict block (Step 7) so a HIGH-risk LIGHT pass is never silently equivalent to a full one. (For per-card test depth in `/new`, the card's `review_profile` value governs scope — `review_profile` is computed by prd-card-writer (Rule C); see prd-card-writer.md for the criteria.)

---

## Step 2 — Create Findings File (Balanced + Deep only)

**Skip for LIGHT.**

Create `/qa/` directory if it does not exist: `mkdir -p /qa`

Choose filename:
- If card known: `/qa/<CARD-ID>.md`
- Else: `/qa/session-YYYYMMDD-HHMM.md`

Write the initial file:

```markdown
# QA Session — <CARD or SESSION-ID>

**Date**: <ISO timestamp>
**Branch**: <branch name>
**Commit**: <short hash> <message>
**Profile**: <Light | Balanced | Deep>
**Risk Level**: <Low | Medium | High>

## Diff Summary

<paste git diff --stat output>

## Environment

- Package manager: <detect from lockfile>
- Test framework: <detect from config/package.json>
- E2E framework: <configured (config file exists) | not configured>

## Findings

<!-- Populated during testing. Format per finding:
### FIND-NNN — <Title>
- **Severity**: Blocker | Major | Minor
- **File**: <path:line if known>
- **Repro**: <steps or trigger>
- **Expected**: <correct behavior>
- **Actual**: <observed behavior>
- **Root cause**: <hypothesis>
- **Suggested fix**: <minimal fix description>
- **Regression test**: <what test to add>
-->

(none yet)

## Final Verdict

<!-- Populated at end of run -->
```

---

## Step 3 — Execute Profile

### LIGHT — Fast confidence (<3 min target [DESIGN-CHOICE: scoped to lint + type-check + related tests only; sufficient for low-risk or doc-only diffs])

Run directly in this session (no sub-agents):

1. Extract changed source files from the diff.
2. Lint check on changed files — if no changed files, skip with note.
3. Type check (e.g., `npx tsc --noEmit`)
4. Scoped tests — run only tests related to the changed files (related-tests / testPathPattern on touched modules). If no related tests are found, record `Tests: SKIP — no related tests` and cap confidence; do NOT fall through to the full suite.
5. Build check.

For each step: report PASS / FAIL. On FAIL, show the exact error output.

Stop on FAIL (do not run subsequent steps after a BLOCKER failure). Diagnose the failure before presenting the verdict.

No findings file required. Present final verdict immediately.

---

### BALANCED — Solid validation (default)

qa-sentinel is a **mechanical gate-runner** (lint / tsc / scoped-or-full tests / build / `npm audit`):
it returns PASS/FAIL + a gate table + confidence. It does NOT read source files, exercise flows, run
a dev server, or do collateral-impact analysis. Behavioral / collateral / dev-server work in BALANCED
belongs to the e2e and code-aware reviewers, not to qa-sentinel.

Invoke `qa-sentinel` via Task tool to run the gates:

```
Run the mechanical QA gates on the current changeset at the tier dictated by the QA profile below
(do NOT default to FULL).

Context:
- Branch: <branch>
- Latest commit: <hash> <message>
- Changed files: <list from git diff>
- Risk level: <Low/Medium/High>
- Card: <CARD-ID or "none">
- QA profile: <the profile this /qa was invoked with: balanced | deep>

Tier contract: balanced → SCOPED (related tests on touched modules); deep → FULL suite. Only
path-based risk drift (auth/permission/payment/schema/migration/API contract in the diff) may
escalate balanced→FULL.

Run lint, tsc, tests (per tier), build, and (deep) npm audit. Return PASS/FAIL + the gate table +
confidence. Do NOT read source files, start a dev server, or analyze collateral impact — those are
out of scope for this agent.
```

After `qa-sentinel` returns its PASS/FAIL + gate table:
- Read its output.
- Append the gate results to `/qa/<file>.md` under the `## Findings` section.

**Collateral / behavioral coverage (BALANCED):** if the diff touches user-facing flows and you need
behavioral confidence beyond the gates, use the parallel-agent path below (Step 4) — it routes
flow-exercising and collateral-impact analysis to the appropriate code-aware / e2e agents rather than
to qa-sentinel.

---

### DEEP — Maximum confidence

Run everything in BALANCED, plus:

**E2E pass:**
- Check if an e2e test config exists in the project root (e.g., `playwright.config.ts`, `cypress.config.ts`).
- If YES: invoke an agent to run the e2e smoke suite (smoke first, full suite if risk is MEDIUM/HIGH). Collect pass/fail and any test output. Append to findings file.
- If NO: log in findings file: "E2E framework not configured — recommend setting up e2e smoke suite. No e2e tests run."

**UI quality checks:**
- Use MCP Playwright (if available) to open key flows related to the diff and take screenshots, checking for console errors and visual regressions.
- Validate: login/auth flow, critical navigation, any flow directly touched by the diff.

Run the e2e pass in parallel with the `qa-sentinel` FULL-tier gate run (launch both as sub-agents simultaneously). This inline two-agent launch is the DEEP default; escalate to the team-based strategy (Step 4) ONLY when 3+ clearly independent risk tracks exist [DESIGN-CHOICE: below this threshold, TeamCreate overhead exceeds benefit; two inline Task spawns are sufficient]. A DEEP run with fewer than 3 tracks stays on this inline path and does NOT create a team.

---

## Step 4 — Parallel Agent Strategy (Balanced/Deep when warranted)

Use this when 3+ independent tracks exist [DESIGN-CHOICE: same threshold as DEEP inline gate — ensures consistent entry point for team-based parallelism].

Create a team: `TeamCreate` with name `qa-<CARD-or-timestamp>`.

Create tasks:
- **Task A**: Lint + TypeScript + scoped tests — `qa-sentinel` (gate run, SCOPED tier)
- **Task B**: Full tests + build + audit — `qa-sentinel` (gate run, FULL tier)
- **Task C** (Deep only): E2E + UI validation — `e2e-review` skill / Playwright
- **Task D**: Collateral-impact analysis on adjacent features not in the diff — `code-reviewer` (reads source, reasons about ripple)

Spawn agents in parallel (single message, multiple Task tool calls):
- Agent A: `qa-sentinel`, task A
- Agent B: `qa-sentinel`, task B
- Agent C (Deep only): run the `e2e-review` skill / Playwright pass for task C
- Agent D: `code-reviewer`, task D

qa-sentinel runs gates only (tasks A + B); it never receives Task D — collateral-impact analysis
requires reading source, which qa-sentinel is forbidden from doing. If a named specialist is
unavailable, surface `CAPABILITY_UNAVAILABLE: <agent>` and halt — never substitute a generic agent.

Each agent sends findings to orchestrator via `SendMessage`. Orchestrator consolidates ALL findings into `/qa/<file>.md`.

After all agents done: `SendMessage shutdown_request` to each → `TeamDelete`.

---

## Step 5 — Finalize Findings File (Balanced + Deep)

After all agents/checks complete, update `/qa/<file>.md` — replace the `## Final Verdict` placeholder:

```markdown
## Final Verdict

**QA Verdict**: PASS | FAIL
**Profile**: <Light | Balanced | Deep>
**Confidence**: <0–100>%
**Risk Level**: <Low | Medium | High>
**Findings**: <N blockers>, <N majors>, <N minors>
**Next Action**: <none | handoff to coder team | rerun subset | escalate>
```

---

## Step 6 — Handoff on Failure (Balanced + Deep only)

**Only if BLOCKER or MAJOR findings exist:**

1. Invoke the **coder** agent (subagent_type: `coder`). The coder has mandatory pre-conditions (it
   reads a backlog card at startup, sets it IN_PROGRESS, and reads the card's `git_strategy`) and is
   forbidden from switching branches — so it MUST be given the context it needs:
   - **Card ID** (the resolved `<CARD-ID>` from Step 0). If Step 0 fell back to a `session-…`
     timestamp (no card), do NOT auto-invoke the coder — there is no card for it to read. Instead,
     surface the findings to the user and ask whether to create a card or fix manually.
   - **Branch**: spawn the coder on the current branch (the one the diff lives on); it stays there.
   - **Findings file path** + instruction to fix all BLOCKERs, fix MAJORs unless they require
     architectural change, and add a regression test for every bug fix.
   - Do NOT ask the user about whether to fix — proceed directly once a card exists.

2. After coder completes, re-verify through proper subagent spawns (so results are written and
   tracked, never run loose in this orchestrator's context):
   - Re-invoke `qa-sentinel` (gate run, SCOPED tier) on the fixed files. It writes its
     PASS/FAIL + gate table to `/qa/<CARD-ID>.md` and returns the structured `QA DONE` signal; the
     orchestrator does NOT run gates in-session.
   - Invoke `code-reviewer` (read-only audit) to confirm the fixes are correct. Invoke `doc-reviewer`
     only if the fix touched documented behavior.
   - For DEEP: also re-run e2e smoke tests to verify UI still passes.

   > **Avoid double review when embedded in `/new`**: if this `/qa` run is part of `/new`'s pipeline,
   > `/new`'s `/codexreview` pre-merge gate already runs `code-reviewer` (and `doc-reviewer`) on the
   > same diff. Do NOT re-run them here in that case — let the `/codexreview` gate be the single
   > review pass and only re-run the qa-sentinel gates to confirm the fix.

3. Update `/qa/<file>.md` with post-fix results under a new section `## Post-Fix Verification`,
   including the re-run qa-sentinel verdict and any re-review findings.

---

## Step 7 — Console Output (always, at end)

Print this block regardless of profile:

```
─────────────────────────────────────────
QA Verdict:     PASS / FAIL
Profile:        Light / Balanced / Deep
Confidence:     <0–100>%
Risk Level:     Low / Medium / High
Card:           <FEAT-XXXX or session ID>
Findings File:  /qa/<file>.md  (or "N/A — Light profile")
─────────────────────────────────────────
Next Action:    <none | handoff to coder team | rerun subset | escalate>
─────────────────────────────────────────
```

---

## Constraints (non-negotiable)

- **Never fabricate results.** If a command fails to run, report it as an execution error, not a pass.
- **Never skip silently.** If a step is skipped, state why explicitly.
- **Stop on critical failure** — do not continue the suite after a BLOCKER. Diagnose first.
- **Every bug fix must produce a regression test** covering the exact failure scenario.
- **No PASS verdict** while any unresolved BLOCKER exists.
- **Findings file is the single source of truth** — all agents write there; do not split findings across multiple files for the same session.
