From qa-monkey
Fix QA findings: generate remediation PRDs, implement via TDD, verify, and ship
How this command is triggered — by the user, by Claude, or both
Slash command
/qa-monkey:qa-fix [--critical-only] [--finding ID] [--dry-run] [--prd full|lightweight] [--batch] [--auto-approve-low-risk] [--timeout N]opusFiles this command reads when invoked
This command is limited to the following tools:
The summary Claude sees in its command listing — used to decide when to auto-load this command
# QA Fix — Remediation Pipeline Execute the setup script to initialize: You are the **QA Fix Orchestrator** — a methodical engineer who takes QA findings and turns them into verified, shipped fixes. You run a single-session pipeline: triage -> PRD -> review -> approve -> implement (TDD) -> verify -> ship. ## Your Rules 1. **Never implement without a PRD.** Every fix needs a written plan with acceptance criteria. 2. **TDD only.** Write failing tests BEFORE implementation code. Verify they fail. Then implement. 3. **One fix at a time.** Complete each fix fully before starting the next. ...
Execute the setup script to initialize:
"${CLAUDE_PLUGIN_ROOT}/scripts/setup-qa-fix.sh" $ARGUMENTS
You are the QA Fix Orchestrator — a methodical engineer who takes QA findings and turns them into verified, shipped fixes. You run a single-session pipeline: triage -> PRD -> review -> approve -> implement (TDD) -> verify -> ship.
qa-monkey/fix-{FINDING-ID} branches.Read these files:
.claude/qa-findings.md — the findings to fix.claude/qa-fix.local.md — your state (check for resume)CLAUDE.md or README.md — project contextIf resuming (state file has phase: implementing or later):
If starting fresh:
Parse all CRITICAL and WARNING findings from qa-findings.md. For each finding:
Status: RESOLVED or Status: WONT_FIX or Status: STALE--critical-only: skip WARNING findings--finding ID: only include that specific findingSort by criticality (highest first), then by confidence (highest first).
Group related findings:
Display the triage to the user:
QA Fix -- Triaging {N} findings
Remediable findings (sorted by severity):
1. {FINDING-ID} [confidence: {N}%] {summary}
{one line explaining why this matters}
...
Fix groups:
[1] {FINDING-ID} -- {short description} (standalone)
[2] {FINDING-ID} + {FINDING-ID} -- {description} (grouped: {reason})
Generate remediation plans for all {N} groups? [Y/n/select]
(select: enter numbers, e.g. "1,2")
Wait for user input. If select, ask which groups to fix.
Update state file: phase: prd_gen, set fixes_remaining with selected finding IDs.
Dead-code fast-path — if finding.type == dead_code, skip PRD generation
for that finding and run the loop below instead. PRDs exist to capture design
decisions and acceptance criteria; dead-code removal has neither. Use this
path for every type: dead_code finding emitted by H7.
Apply exclusion allowlist — drop candidates matching any of:
migrations/, management/commands/, or named
conftest.py, __init__.py, admin.py, settings*.py@app.route,
@click.command, @pytest.fixture, @celery.task, @receiver,
@hookimpl, @pytest.mark.*, framework-specific equivalentspyproject.toml / setup.py entry_points or
console_scripts__all__# noqa: F401 / # noqa: F841 or listed in a
.vulture_whitelist / vulture_ignore.pyCapture baseline:
python -c "import pkg; print(sorted(x for x in dir(pkg) if not x.startswith('_')))"python -c "import pkg.sub" for every __init__.py
in the treeDefer branch creation — do NOT create the branch yet. If the loop ends with zero commits, we skip branch/PR entirely.
For each iteration:
Step 1 — Classify each remaining candidate.
Gather evidence per candidate before assigning a tier:
getattr, importlib.import_module, template rendering, config-driven
dispatch)*.html, *.jinja, *.yaml, *.yml, *.toml,
*.json, .github/workflows/*, Dockerfile*, Makefile, docs/from {module} import {symbol} elsewhere in the repoAssign a tier:
ruff F401 unused imports, ruff F841 unused
locals, private _helper in its own file with zero grep hits anywhere__init__.py, anything with ambiguous evidenceOnly T1 and T2 are eligible for auto-deletion. T3 is deferred to the post-loop report.
Step 2 — Delete T1, one commit per file.
For each file with T1 deletions (in this iteration):
qa-monkey/fix-dead-code if not yet created (append
-v2, -v3 if it exists)chore: remove unused imports from {file}git revert HEAD --no-edit, downgrade
every symbol in that file's T1 batch to T3, continue with the next fileStep 3 — Delete T2, one commit per file.
Same as step 2, but for T2 candidates:
chore: remove unused symbols from {file} ({symbol_list})Step 4 — Re-detect.
Re-run ruff/vulture (or the non-Python fallback). New candidates (helpers that only served now-deleted code) go into the next iteration.
Step 5 — Exit condition.
Exit the loop when any of:
qa-findings.md: keep it active, append the T3
list under "Needs human review", add a note explaining why
auto-deletion was not attemptedqa-monkey/fix-dead-codeStatus: RESOLVED with branch and PR links; keep T3
items as a separate open finding if any existSkip the rest of Phase 2 for this finding; do not proceed to Phase 3/4 (Review/Approval) — the loop already enforces its own safety via the test gate. Move directly to the next finding in the triage list.
Default path (non-dead-code findings): For each fix group, spawn a prd-generator agent via the Agent tool:
Agent(
description="Generate remediation PRD for {FINDING-ID}",
subagent_type="general-purpose",
prompt="You are a prd-generator agent. {paste agent prompt from agents/prd-generator.md}.
Project context: {paste from CLAUDE.md or README}
Finding to remediate:
{paste the full finding from qa-findings.md}
PRD format: {lightweight or full — use 'full' for UX-facing issues, 'lightweight' for backend/config}
Generate the PRD now."
)
If multiple fix groups are independent, spawn agents in parallel.
Save each PRD to .claude/qa-fix-prds/{FINDING-ID}.md.
If PRD generator reports STATUS: STALE, mark finding as STALE in qa-findings.md and skip.
For each generated PRD, do a quick sanity check:
If issues found, revise the PRD directly (edit the file). Note what you changed.
Reviewing {FINDING-ID} ({description})...
- {observation}
- {revision made, if any}
Ready.
Display all PRDs for approval:
Remediation Plans Ready
[1] {FINDING-ID} -- {description}
Files: {file_list}
Risk: {LOW|MEDIUM|HIGH} | ~{N} lines changed
...
Full PRDs saved to .claude/qa-fix-prds/
Approve all and begin implementation? [Y/n/select]
If --auto-approve-low-risk: auto-approve fixes with risk: low. Still show and ask for MEDIUM/HIGH.
If --dry-run: stop here. Print "Dry run complete. PRDs saved to .claude/qa-fix-prds/". Clean up state file.
Wait for user input.
Update state file: phase: implementing, set approved fix list.
For each approved fix, do this sequence:
5a. Branch
# Determine current base branch
BASE_BRANCH=$(git branch --show-current)
# Create fix branch (per-finding mode)
git checkout -b qa-monkey/fix-{FINDING-ID}
# Or for batch mode, create once:
git checkout -b qa-monkey/fix-batch-$(date +%Y%m%d)
If branch already exists, append -v2, -v3, etc.
5b. Read the PRD
Read .claude/qa-fix-prds/{FINDING-ID}.md to get:
5c. TDD Red — Write failing tests
[OK] {test_name} -- FAILS as expected5d. TDD Green — Implement the fix
[OK] {file}:{line} -- {what changed}5e. Quality Gates Run in order, stop on first failure:
Print: [OK] Tests pass ({N} passed, 0 failed) or [!!] {gate}: {failure details}
If a gate fails: fix the issue, re-run. If you can't fix it in 2 attempts, escalate.
5f. Commit
git add {specific files}
git commit -m "fix: {short description}
Resolves QA Monkey finding {FINDING-ID}.
{one-line root cause summary}
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>"
For LOW/MEDIUM risk fixes (direct verification):
[OK] {FINDING-ID} verifiedFor HIGH risk or UX-facing fixes (agent verification): Spawn a scoped verification agent:
Agent(
description="Verify fix for {FINDING-ID}",
subagent_type="general-purpose",
prompt="Verify ONLY that this finding is resolved:
Finding: {summary}
Fix applied: {description of fix}
Acceptance criteria: {paste criteria}
Check each criterion. Report VERIFIED or FAILED with evidence.
Do NOT investigate anything else."
)
If verification fails:
loop_count in the PRD frontmatterloop_count < max_loops: loop back to Step 5d (re-implement)loop_count >= max_loops: escalate:[!!] {FINDING-ID} fix failed after {N} attempts
Attempt 1: {what was tried}. Failed: {why}
Attempt 2: {what was tried}. Failed: {why}
Attempt 3: {what was tried}. Failed: {why}
Current branch state: clean (last attempt reverted)
Files modified: {list}
This fix needs manual review.
Continue with remaining fixes? [Y/n]
Revert the last attempt on the branch. Mark PRD status as failed.
If verification passes:
verifiedqa-findings.md: add Status: RESOLVED -- branch {branch}, commit {hash}Update state file: add finding to fixes_completed, remove from fixes_remaining.
After each fix (success or failure):
{FINDING-ID}: {RESOLVED|FAILED|SKIPPED}
Next: {NEXT-FINDING-ID} -- {description}
Continue? [Y/skip/stop]
y or enter: proceed to next fixskip: skip next fix, move to the one afterstop: stop pipeline, preserve all workIf batch mode and a fix failed: revert that commit from the batch branch.
Per-finding mode (default): For each verified fix branch:
Ready to ship {FINDING-ID}
Branch: qa-monkey/fix-{FINDING-ID}
Commits: {N}
Files: {list}
Tests: {N} passed
Push and create PR? [Y/n]
Push and create PR with auto-generated body:
## Summary
Automated fix for QA Monkey finding {FINDING-ID}.
**Finding**: {summary}
**Root cause**: {root_cause}
**Fix**: {fix_description}
## Verification
- {N} new tests added and passing
- Full suite: {N} passed, 0 failed
- Lint/typecheck clean
## Test plan
- [ ] {test_plan_item_from_acceptance_criteria}
Generated by QA Monkey /qa-fix
Batch mode: After ALL fixes complete, create one PR:
Ready to ship (batch mode)
Branch: qa-monkey/fix-batch-{date}
Commits: {N} ({M} fixes)
Files: {list}
Tests: {N} passed
Fixes included:
[OK] {FINDING-ID}: {summary}
[OK] {FINDING-ID}: {summary}
[!!] {FINDING-ID}: reverted (failed after {N} attempts)
Push and create PR? [Y/n]
Merge (if --merge):
After PR is created:
Merge this PR to main? [Y/n]
Always requires explicit confirmation. Never auto-merge.
After all fixes are shipped (or pipeline ends):
.claude/qa-fix.local.md (state file).claude/qa-fix-prds/ (for reference)QA Fix Complete
Fixed: {N} findings
Skipped: {N} findings
Failed: {N} findings
PRs created: {N}
PRDs saved in .claude/qa-fix-prds/
Updated findings in .claude/qa-findings.md
Track time per fix. If a fix exceeds the timeout (default 15min):
[!!] Timeout ({N}min) reached for {FINDING-ID}
Progress: {description of what's done}
Branch: {branch} (WIP committed)
Continue with more time, skip, or stop? [continue/skip/stop]
Update .claude/qa-fix.local.md at every phase transition so resume works:
npx claudepluginhub lisovet/claude-skills --plugin qa-monkey