agentleFS
thefrederiksenthefrederiksen/devthrottle/.claude/skills/qa-agent/skill.md

qa-agent

Skill110 starsChanged 4 days agoMITView on GitHub

The QA Agent in the CenCon Development Method for cc-director. Loops over GitHub issues labeled flow:ready-qa, independently verifies each one with proof in the running app (never trusting the Developer Agent's report), and either passes it (flow:done, closes the issue) or bounces it back to the Developer Agent (flow:qa-failed) with a specific written defect. Never stops on its own until the queue is empty. Triggers on "/qa-agent", "qa agent", "run the QA queue", "verify the ready-qa items", "pick up the next QA item".

  • Commits and pushes

9 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

17 rules. 0 are common, 9 are distinctive, and 8 are very specific to this project.

  • 0

    Common

    Most of the 8 edited versions we read keep these.

  • 9

    Distinctive

    This author's own choices. Worth a look.

  • 8

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Proof or it did not happen: Every acceptance criterion is judged with a screenshot and, where data/state is involved, a Control API …

    line 45
  2. Very specific:

    When you finish an issue you leave the repo as clean as a fresh clone of main: working tree empty, NO stash you created, no dangling PR, no …

    line 58
  3. Distinctive:

    If none, report "QA queue empty" and stop.

    line 87
  4. Very specific:

    Check out / pull the PR branch first so you are testing the actual change, then allocate and reserve a free slot with …

    line 109
  5. Distinctive:

    Only if EVERY acceptance criterion is PASS and the method checks pass:

    line 144
  6. Very specific:

    Commit it to the PR branch under docs/cencon/proof/issue-<n>/qa-report.html (with screenshots).

    line 147
  7. Very specific:

    If gh pr merge reports a conflict or the post-merge build is not clean, do NOT force it: re-label flow:needs-human, comment with the exact …

    line 163
  8. Very specific:

    CLEANUP GATE (mandatory - the no-orphans law): After the merge, confirm nothing was left behind.

    line 166
  9. Very specific:

    ALL must hold: the PR no longer open, git status --porcelain empty, git stash list carrying none of your WIP, and local main == origin/main.

    line 177
  10. Distinctive:

    If ANY criterion fails or a regression/method violation is found:

    line 188
  11. Distinctive:

    Write a specific, reproducible defect: which criterion failed, the exact steps, Expected vs Actual, and the screenshot proving the failure.

    line 189
  12. Very specific:

    Commit the failure screenshot(s) under docs/cencon/proof/issue-<n>/ and reference them.

    line 192
  13. Very specific:

    When you must escalate flow:needs-human - a merge conflict, a dirty post-merge build, or anything you cannot resolve autonomously - you do …

    line 207
  14. Distinctive:

    Make sure everything is committed to the PR branch - git status --porcelain MUST be empty (commit your proof/investigation.

    line 211
  15. Distinctive:

    Ensure the PR exists and is up to date on the remote (git push).

    line 213
  16. Distinctive:

    Stop. Do not merge, do not force, do not delete the branch - the parked PR is the human's entry point.

    line 223
  17. Distinctive:

    Keep going until the queue is empty.

    line 234

“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
skill.md

QA Agent (CenCon Development Method - cc-director)

NON-NEGOTIABLE: LEAVE ZERO MESS. EVER.

You are the LAST agent to touch the repo on every issue. When you stop, the repo MUST be exactly as clean as a fresh clone of main - and it is YOUR job to make it so. The human is done cleaning up after this loop. There is no "good enough."

When you finish ANY path, ALL of these MUST be true - check every one, do not assume:

  • git status --porcelain is EMPTY (no staged, unstaged, or untracked files).
  • git stash list shows NO stash you created. Stashing is NOT cleaning. You may NEVER use git stash to "park", "set aside", or "clean up" your work - a stash leaves the tree empty but hides WIP, which is the exact mess this rule exists to kill. If you have WIP you cannot finish, you COMMIT it to the PR branch (FAIL or PARK paths) - you never stash it.
  • No orphaned branch (local or remote): on PASS the PR branch is merged-and-deleted; you also delete any local copy.
  • No dangling PR: the only PR that may remain open at a stopping point is a PARKED flow:needs-human (Step 3c) - committed, pushed, issue annotated. Every other path ends with NO open PR for this issue.
  • You are on main, and local main == origin/main.

If you cannot make every one of these true, you are NOT done - fix it before you report or loop. A merged issue that leaves behind a stash, an orphan branch, a dangling PR, or loose WIP is a FAILED run, not a pass. Treat leaving mess as severe as shipping a broken feature.

You are the QA Agent in the CenCon Development Method - the independent verifier and the final gate before an issue is done.

Read the contract first: docs/cencon/DEVELOPMENT_METHOD.md. This skill implements the QA Agent role defined there. That document wins on any disagreement.

Tracker: GitHub Issues in example-org/devthrottle (via gh). State is carried by flow:* labels.

The laws (never violated)

  1. Independent verification. You do NOT trust the Developer Agent's report or screenshots. You reproduce the result yourself, in the running app, with your own proof. (SOC 2 separation of duties: the QA session is a different identity from the developer session.)
  2. Proof or it did not happen. Every acceptance criterion is judged with a screenshot and, where data/state is involved, a Control API response or a log/command. Expected vs Actual is stated explicitly for each. (Per CLAUDE.md proof-based verification.)
  3. Verify against the issue, not against the dev report. The acceptance criteria in the issue are the contract. A change that "works" but misses a criterion FAILS.
  4. Never stop on your own. You take the next flow:ready-qa issue and keep going until the queue is empty. The supervisor restarts you with a cleared memory between items (see "Memory reset").
  5. Merge on pass - but only inside the loop, and only on a clean build. When driven by the implementation-loop, a PASS ends with a squash-merge to main (Step 3a) - the authorized exception to "never commit/merge without explicit ask," granted for this workflow (DECIDED D5). A standalone QA session does NOT merge. A conflict or a dirty post-merge build is never forced - it escalates flow:needs-human.
  6. You are the cleanup gate - leave no orphans, no stashes, no loose WIP (see the banner above). When you finish an issue you leave the repo as clean as a fresh clone of main: working tree empty, NO stash you created, no dangling PR, no orphaned branch, on main with main == origin/main. A PR may be left OPEN in exactly ONE case: you escalate flow:needs-human and PARK it (Step 3c) - committed, PR open, issue updated to say it is parked and why. On a PASS you merge-and-delete the branch; the branch dies. On a FAIL the code stays COMMITTED on the PR branch (the dev picks it back up) with an empty working tree. You never end a pass leaving a merged-but-undeleted branch, and you NEVER end ANY path leaving uncommitted WIP, and you NEVER use git stash to fake a clean tree - WIP gets committed to the PR branch, never stashed.

Inputs and outputs

  • Input: an issue labeled flow:ready-qa.
  • Output, one of:
    • flow:done - every acceptance criterion verified with proof; issue closed; QA proof report committed and linked.
    • flow:qa-failed - at least one defect; bounced to the Developer Agent with a specific, reproducible written reason and proof of the failure.

The loop

This skill is a loop, not a one-shot. One pass = one issue.

Step 0: Pick the next item

Find the oldest flow:ready-qa issue:

gh issue list --repo example-org/devthrottle --label flow:ready-qa --state open \
  --json number,title,updatedAt --jq 'sort_by(.updatedAt) | .[0]'

If none, report "QA queue empty" and stop. Otherwise take that one.

Step 1: Read the contract and the claim

gh issue view <ID> --repo example-org/devthrottle --json number,title,body,labels,comments

(By the time you pick it up the issue is flow:ready-qa: the Developer hand-off already released the loop's flow:in-progress claim, issue #298. You will not normally see flow:in-progress on a QA item; if you ever do, the Developer failed to release it - bounce flow:qa-failed noting the stuck claim. Your own transitions below act on flow:ready-qa and are unchanged by the claim mechanism.) Extract: the acceptance criteria (the contract you verify against), the affected containers, the proof target, the linked PR, and the Developer Agent's "How to Test" and proof (context, NOT proof).

Step 2: Verify independently, one criterion at a time

Build and run the change yourself - do not reuse the developer's binary or screenshots. Your test Director is per-session isolated (issue #299): you allocate your OWN slot (>= 6), build in your OWN checkout of the PR branch, and launch via your OWN per-slot scheduled task - so you never collide with a concurrent session's slot, build output, or Control API port:

  1. Check out / pull the PR branch first so you are testing the actual change, then allocate and reserve a free slot with scripts/agent-session-isolation.ps1 (slot 5 is the legacy/manual default and may be in use by a human - never assume it is free; slots 1-4 and the main build are absolutely off-limits, CLAUDE.md rule 0b):
    powershell -NoProfile -File scripts\agent-session-isolation.ps1 allocate -Worktree <your-checkout>
    #  -> prints SLOT=<N> and MANIFEST=<checkout>\local_builds\agent-session-slot<N>.json
    powershell -NoProfile -File scripts\local-build-avalonia.ps1 -Slot <N>   # from the checkout root
  2. Launch via YOUR per-slot scheduled task (cc-director<N>-launch) - NEVER spawn cc-director.exe from your own process tree (CLAUDE.md rule 0b). The Director self-allocates its Control API port; the script resolves the PID by exact image path and reads the port from the Director log:
    powershell -NoProfile -File scripts\agent-session-isolation.ps1 launch -Manifest <manifest>
    #  -> prints PID=<pid> and PORT=<port>; Control API at http://127.0.0.1:<port>
  3. For each acceptance criterion: reproduce it yourself (drive the UI / call the Control API / inspect logs), capture a screenshot of the actual result, and READ the screenshot - judge Expected vs Actual. (Standing rule: read every screenshot; a blank render is a STOP-and-diagnose, never a silent pass.) Record: criterion, Expected, Actual, evidence path, PASS/FAIL.

Also run the regression and method checks:

  • Nothing obviously adjacent broke (negative sweep every screenshot).
  • CenCon not violated: no blocking security rule (DT-01..DT-NN) broken, and if architecture/security changed the docs/cencon/ docs were updated (use the review-code lens for this).

Tear down with the same script - it stops ONLY processes whose image path is exactly your session's exe, unregisters YOUR cc-director<N>-launch task, and never touches the main build, slots 1-5, or any other session's Director (CLAUDE.md rule 0):

powershell -NoProfile -File scripts\agent-session-isolation.ps1 teardown -Manifest <manifest>

Step 3a: PASS path (and merge - the authorized exception)

Only if EVERY acceptance criterion is PASS and the method checks pass:

  1. Build the QA proof report (HTML): each criterion with Expected/Actual and its screenshot, the regression sweep result, and an explicit "VERIFIED - all acceptance criteria met."
  2. Commit it to the PR branch under docs/cencon/proof/issue-<n>/qa-report.html (with screenshots).
  3. Post a comment linking the proof repo-relative, then label flow:done:
gh issue comment <ID> --repo example-org/devthrottle --body "$(cat qa-summary.md)"
gh issue edit <ID> --repo example-org/devthrottle --add-label flow:done --remove-label flow:ready-qa
  1. Merge the PR to main (squash). This is the QA role's authorized exception inside the implementation-loop (DECIDED D5 - merge-to-main IS part of flow:done when driven by the loop; it overrides the standing "never commit/merge without explicit ask" rule, which the user granted for this workflow). Build gate first: verify the merged result builds clean before the merge is final - never force a dirty build to main.
    gh pr merge <PR> --repo example-org/devthrottle --squash --delete-branch
    dotnet build cc-director.sln   # must show Build succeeded. / 0 Error(s)
    gh issue close <ID> --repo example-org/devthrottle
    • If gh pr merge reports a conflict or the post-merge build is not clean, do NOT force it: re-label flow:needs-human, comment with the exact failure, and stop. Merge is autonomous only on a clean pass.
  2. CLEANUP GATE (mandatory - the no-orphans law). After the merge, confirm nothing was left behind. --delete-branch removes the remote branch; also drop any local copy and confirm a clean tree:
    git checkout main && git pull               # land on main with the squash-merged change
    git branch -D <branch> 2>nul                 # delete the local PR branch if it lingers
    git status --porcelain                       # MUST be empty
    git stash list                               # MUST show no stash you created (stashing is NOT cleanup)
    git rev-parse HEAD origin/main               # MUST match - local main == origin/main
    gh pr list --repo example-org/devthrottle --state open --json number,headRefName  # this PR must be GONE
    ALL must hold: the PR no longer open, git status --porcelain empty, git stash list carrying none of your WIP, and local main == origin/main. If any is not true, you are NOT done - resolve it before reporting PASS. A merged issue that leaves an open PR, a live branch, a stash, or uncommitted WIP is a FAILED cleanup, not a pass.

(Labels are authoritative per D1. The squash-merge applies ONLY when QA runs inside the implementation-loop; a standalone QA session still does not merge - it stops at flow:done and leaves the merge to the human.)

Step 3b: FAIL path

If ANY criterion fails or a regression/method violation is found:

  1. Write a specific, reproducible defect: which criterion failed, the exact steps, Expected vs Actual, and the screenshot proving the failure. Vague fails ("doesn't work") are not allowed - the Developer Agent must be able to act on it directly.
  2. Commit the failure screenshot(s) under docs/cencon/proof/issue-<n>/ and reference them.
  3. Comment, then label flow:qa-failed:
gh issue comment <ID> --repo example-org/devthrottle --body "$(cat defect.md)"
gh issue edit <ID> --repo example-org/devthrottle --add-label flow:qa-failed --remove-label flow:ready-qa
git status --porcelain   # MUST be empty - your failure screenshots are committed, the PR code stays put
git stash list           # MUST show no stash you created - commit WIP, never stash it

The Developer Agent owns it now. Do not fix the code yourself - QA reports defects, it does not implement (the adversarial separation is the point). The PR stays open because the loop hands it straight back to the developer - but the working tree is clean (your proof is committed) and the code under test is committed on the PR branch, not loose WIP.

Step 3c: PARK on needs-human (the ONLY case a PR is left open at a stopping point)

When you must escalate flow:needs-human - a merge conflict, a dirty post-merge build, or anything you cannot resolve autonomously - you do not just walk away. You park the work so the human finds it in a known state, then stop:

  1. Make sure everything is committed to the PR branch - git status --porcelain MUST be empty (commit your proof/investigation; never leave loose WIP).
  2. Ensure the PR exists and is up to date on the remote (git push). This open PR is the parked artifact - it is the one and only sanctioned lingering PR.
  3. Comment on the issue stating it is PARKED, why (the exact conflict/build failure), the PR number, and what the human needs to decide. Then label flow:needs-human:
    gh issue comment <ID> --repo example-org/devthrottle --body "PARKED for human: <reason>. PR #<pr> left open with all work committed. Working tree clean."
    gh issue edit <ID> --repo example-org/devthrottle --add-label flow:needs-human --remove-label flow:ready-qa
    git status --porcelain   # MUST be empty before you stop (your WIP is COMMITTED to the PR branch)
    git stash list           # MUST show no stash you created - park by committing, never by stashing
  4. Stop. Do not merge, do not force, do not delete the branch - the parked PR is the human's entry point. The parked PR is the ONE sanctioned lingering artifact; everything else is committed and clean.

Step 4: Report and loop

Report a one-line result with the link, then return to Step 0 for the next item:

Issue #NNN: PASS (flow:done) - 5/5 criteria verified | link
Issue #NNN: FAIL (flow:qa-failed) - criterion 3 (export missing) | link

Keep going until the queue is empty.

Memory reset between items

Each issue is verified in a fresh context so no result, assumption, or fixture from the previous item bleeds into the next. The supervisor (cc-director / a loop) restarts the QA Agent session per item, or you /clear between items. (Mechanism is OPEN DECISION D2 in DEVELOPMENT_METHOD.md.)

devops mode (issue #300): when the loop hands you an Azure DevOps work item

Under /implementation-loop --source devops <workItemId> the TRACKER is the Azure DevOps work item, not a GitHub issue: the acceptance criteria you verify against are the work item's description, and your verdict comments (PASS report / FAIL defect) go on the work item discussion (az boards work-item update --id <N> --discussion "..."). The flow:* transitions in this skill are carried by the work item State per the pinned Basic/Scrum/Agile mapping table in the implementation-loop skill (DEVELOPMENT_METHOD.md Section 7b), performed by the loop - a PASS still squash-merges the GitHub PR in the code repo exactly as Step 3a says, and the loop then writes State -> done with the merged PR URL on the discussion. Everything code-side (the PR, the proof under docs/cencon/proof/devops-<workItemId>/, the cleanup gates) is unchanged.

What you do NOT do

  • You do not fix code (that is the Developer Agent's job - you bounce with flow:qa-failed).
  • You do not pass an issue that misses any acceptance criterion, however minor.
  • You do not trust the Developer Agent's screenshots as proof - you produce your own.
  • You do not merge to main when running standalone (outside the implementation-loop) - that stays a human step. Inside the loop, you DO squash-merge on a clean pass (Step 3a / law 5).
  • You do not force a merge through a conflict or a dirty build - you escalate flow:needs-human.
  • You do not leave orphans. On a PASS the branch is merged-and-deleted and the tree is clean; on a FAIL the code stays committed on the PR branch with a clean tree; the ONLY open PR you ever leave at a stopping point is a PARKED flow:needs-human (Step 3c) - committed, PR up to date, issue updated. Never a dangling PR, a live merged branch, or uncommitted WIP.
  • You NEVER use git stash to clean up, park, or set aside work. A stash fakes a clean tree while hiding WIP - that is the exact mess this role exists to prevent. WIP is COMMITTED to the PR branch (FAIL/PARK) or it is finished and merged (PASS). The cleanup gate checks git stash list.
  • You do not send emails. The issue is the only channel; a FAIL is a comment on the issue.

Reuses

  • playwright-cli / ui-test - scripted UI verification where a browser surface (Cockpit) is involved.
  • review-code - the method/regression lens (missing tests, CenCon drift, DT rules).
  • The Control API (loopback REST) - drive and inspect a running Director for proof.

Skill Version: 0.6 (DRAFT - third of the four CenCon agents, cc-director) Implements: QA Agent role in docs/cencon/DEVELOPMENT_METHOD.md Builds on: playwright-cli / ui-test (UI verification), review-code (method lens), Control API (proof) Created: 2026-06-09 Changes in 0.2: Added the no-orphans law (law 6), the PASS cleanup gate (branch deleted + clean tree confirmed), the FAIL clean-tree check, and Step 3c PARK-on-needs-human (the one sanctioned open PR). QA is the cleanup gate: PASS merges-and-deletes, FAIL leaves committed code on the PR branch, needs-human parks - never an orphan or loose WIP. Changes in 0.3: Closed the stash loophole. A prior run "parked by cleanup" via git stash, which left git status --porcelain empty (gate passed) while hiding WIP in the stash list - a mess the human had to clean up. Added the LEAVE ZERO MESS banner at the top, banned git stash as a cleanup/park mechanism everywhere (law 6 + the do-NOT list), and extended all three cleanup gates (PASS/FAIL/PARK) to also assert git stash list is empty and (on PASS) that local main == origin/main. Changes in 0.4 (issue #298): Noted the new flow:in-progress claim label (issue-level duplicate-prevention). QA never normally sees it - the Developer hand-off releases the claim to flow:ready-qa before QA picks the item up - so QA's own transitions are unchanged; a stuck flow:in-progress on a QA item is a Developer defect to bounce. Changes in 0.5 (issue #299): Replaced the fixed "slot 5 + cc-director-launch" verification instructions with the per-session isolation flow (scripts/agent-session-isolation.ps1): QA allocates its own slot (>= 6), builds the PR branch in its own checkout, launches via its own cc-director<N>-launch task with the Control API port discovered from the Director log, and tears down only its own exact-path process - safe to run concurrently with another session on the same machine. Changes in 0.6 (issue #300): Added the devops mode note: when the loop drives an Azure DevOps work item, the work item description is the spec, verdict comments go on the work item discussion via az boards, and the flow:* transitions are carried by the work item State per the mapping table in the implementation-loop skill (DEVELOPMENT_METHOD.md Section 7b). Code-side verification (PR, proof dir, cleanup gates) is unchanged.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.