qa-backend
Skill5 starsChanged 31 days agoMITView on GitHub
QA test writer for a backend/API codebase. Maps every function and endpoint that needs a test, interviews the user with selectable options about intended behavior (never guesses intent), digs into non-obvious edge cases (division by zero, rounding, lockout after N failed logins, IP bans, deletion cascades, pagination limits, time zones, concurrency, idempotency) and data scoping (who may read or change what), records every answer in a gitignored qa/TEST_DECISIONS.md so later runs never re-ask (changed functions get a "did the intent change?" question with options), then writes a /goal prompt and runs one headless worker that writes the tests and wires them to the project's test script (e.g. `bun run test` runs the full suite and shows which functions passed and failed). Every endpoint is attacked with invalid, missing, unauthorized and other-user ids (IDOR, mass assignment, trusting client data). Finally runs the suite, separates real code bugs from flaky/environment/test mistakes, and writes a gitignored qa/TEST_FAILED.md with VS Code links to the failing lines and a fix process (no code). Use whenever the user types /qa-backend (e.g. `/qa-backend api`, `/qa-backend --report`), or asks to write backend/API tests, QA-test their server, build a test suite, find bugs with tests, or test authorization/edge cases. Any language. Never edits application code.
- Reads credentials
1 other project uses a version of this.
Adopted by
Most recently taken up by
- kcayme/k-agentstheir own version, first seen Nov 1, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- kcayme/k-agents★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository4 other files it gives its agents.
- develop-frontendSkill
- make-no-mistakesSkill
- optimize-seoSkill
- analyze-stockSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
20 rules. About 0 are common, 7 are distinctive, and 13 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
13
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 25
Never guess intent: Every behavior a test asserts comes from qa/TEST_DECISIONS.md.
- Distinctive: line 28
Options, not essays: Every question is AskUserQuestion: 2–4 options, the recommended one first and labelled "(Recommended)", up to 4 …
- Very specific: line 31
Ask what is not obvious; never ask the obvious: Don't ask "should a wrong password log the user in?".
- Distinctive: line 39
Talk in the user's language: Write tests, prompts and reports in English unless the user writes in another language, then write the reports …
- Very specific: line 46
Run python "SKILL_DIR/scripts/ensure_gitignore.py" --root ..
- Very specific: line 49
Run claude --version; it must be ≥ 2.1.259 (headless /goal).
- Very specific: line 51
If qa/state.json exists, read its phase and resume from there.
- Very specific: line 64
Read each kept function's body once (line ranges only) to find its branches, inputs, side effects and the policy questions it raises.
- Very specific: line 66
If docs/SECURITY_PROBLEMS.md exists, read it: each finding becomes a SEC-n decision (a test that proves the hole) in Phase 4.
- Distinctive: line 85
If the backend has users, roles, tenants or owned data, build the access matrix with the user: roles × resources × actions (read / list / …
- Distinctive: line 99
Module by module: Start each module with one question: *Ask me each decision* / *Use recommended defaults and show me the list* / *Skip …
- Distinctive: line 109
Update or retire the affected decisions.
- Very specific: line 114
Write every answer into qa/TEST_DECISIONS.md as you go (format in templates/TEST_DECISIONS.md), then
- Very specific: line 123
Write qa/goal-prompt.md from templates/goal-prompt.md: goal condition (≤ 1,500 chars, measurable, evidence printed in the transcript), …
- Distinctive: line 129
Ask the one runtime question: *Auto mode (Recommended)* / *Accept edits + test-command allowlist* / *Stop here (keep the plan)*.
- Very specific: line 133
Always through the launcher (it avoids Git Bash rewriting /goal).
- Very specific: line 135
When it exits: read qa/worker-report.md and run python "SKILL_DIR/scripts/check_tests.py" --root ..
- Distinctive: line 148
Blame check every failing test: before it is reported:
- Very specific: line 152
Read the test and its decision.
- Very specific: line 156
Write qa/results/analysis.json (format in failure-report.md), then python "SKILL_DIR/scripts/make_report.py" --root .
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/qa-backend
Input: $ARGUMENTS = [backend_path] [--report] [--only <module or F-ids, comma-separated>].
Examples: /qa-backend, /qa-backend api, /qa-backend --report, /qa-backend --only auth,F012.
SKILL_DIR = the "Base directory for this skill" shown when this skill loaded (if none is shown,
the folder containing this SKILL.md). Scripts are python "SKILL_DIR/scripts/<name>.py"
(standard library only). Read each reference file when you reach the phase that points to it.
You are the QA orchestrator. You map the code, interview the user, record decisions, brief one test-writing worker, then run the suite and write the failure report. You never fix the app.
Hard rules
- Never edit application code. Allowed changes: test files, test helpers/fixtures, test
config, dev-only test dependencies, the test scripts in the manifest (
package.jsonscripts,pyproject.toml,Makefile…),.env.test.example, and everything underqa/. A bug is reported inqa/TEST_FAILED.md, never fixed. - Never guess intent. Every behavior a test asserts comes from
qa/TEST_DECISIONS.md. A decision is either the user's answer, or a default the user explicitly accepted. Current code behavior is shown to the user as information, never used as the expected result on its own. - Options, not essays. Every question is AskUserQuestion: 2–4 options, the recommended one first and labelled "(Recommended)", up to 4 questions per call. The automatic "Other" box is the user's space to write an intent you did not offer. Never ask a plain-text question and wait.
- Ask what is not obvious; never ask the obvious. Don't ask "should a wrong password log the
user in?". Do ask "after how many failed logins is the IP blocked, and for how long?".
references/edge-cases.mdlists what to ask and what to default silently. - Never re-ask. Decisions persist in
qa/TEST_DECISIONS.mdand function hashes inqa/state.json. Only new functions, changed functions and new scoping questions are asked. - Safety. Tests never touch a production database or live payment keys. Never print secret values (scripts report key names and booleans only). Never run a git command that changes anything; the new tests stay uncommitted for the user to review.
- Talk in the user's language. Write tests, prompts and reports in English unless the user writes in another language, then write the reports in theirs.
Phase 0: Preflight
- Parse arguments.
--report→ jump to Phase 6 (needsqa/test-commands.json; without it, say so and run the full flow). - Run
python "SKILL_DIR/scripts/ensure_gitignore.py" --root .. It adds/qa/and.env.testto.gitignore. If it reportstracked_files, tell the user to rungit rm -r --cached qathemselves. - Run
claude --version; it must be ≥ 2.1.259 (headless/goal). Older → tell the user to update; the interview and decisions can still be done, the worker launch can't. - If
qa/state.jsonexists, read itsphaseand resume from there.
Phase 1: Map the backend (read references/mapping.md)
python "SKILL_DIR/scripts/detect_env.py" --root . [--src <backend_path>]→qa/env.json: stack, package manager, test framework, the command that runs the full suite, existing tests,TEST_DATABASE_URLpresence and safety, external services and their key mode, docker,docs/SECURITY_PROBLEMS.mdpresence.python "SKILL_DIR/scripts/map_functions.py" --root . --src <backend_path>→qa/function-map.json: every function and route with file, line range, kind, route, a body hash, and a status againstqa/state.json(new/changed/unchanged/removed).- Prune and group as
mapping.mdsays: keep what needs a test, drop trivial getters, types, config and generated code, group the rest into modules (auth, users, orders, payments…). Read each kept function's body once (line ranges only) to find its branches, inputs, side effects and the policy questions it raises. Writeqa/modules.json. - If
docs/SECURITY_PROBLEMS.mdexists, read it: each finding becomes aSEC-ndecision (a test that proves the hole) in Phase 4. Ask only where the intended behavior is unclear. - With
--only, keep only those modules/functions for Phases 2–5.
Phase 2: Test setup (read references/test-setup.md; ask at most 2 questions)
- Database:
TEST_DATABASE_URLfound and safe → use it. Not found → ask "Do you have a test database?": Yes, I'll add TEST_DATABASE_URL to .env.test now / No, use a throwaway database (Recommended). Yes → wait, re-rundetect_env.py, check it is found and safe. No (or still missing) → throwaway database. Never ask the user to paste a connection string in chat. - External services: sandbox/test-mode keys present → use the sandbox; live keys or none → mock at the network boundary. No question.
- Test location, framework, command: decided by you from
env.json, never asked. Existing tests are never edited or deleted; they run in the full suite and are reported too.
Record the result in the Setup section of qa/TEST_DECISIONS.md.
Phase 3: Scoping (read references/scoping.md)
If the backend has users, roles, tenants or owned data, build the access matrix with the user:
roles × resources × actions (read / list / create / update / delete / export), shared vs private,
admin powers, what a non-owner gets (404 or 403). Ask with options; derive candidate roles and
resources from the code. Record it as S-n rows. Every endpoint is then attacked against this
matrix (other user's id in path/body/query, lower role, anonymous, forged server-owned fields),
following references/attack-matrix.md. The attack rows are generated, not asked, except where
the matrix leaves a real choice open.
Phase 4: Intent interview (read references/interview.md and references/edge-cases.md)
- Global rules first (one round,
G-n): validation error status (400/422), not-found vs forbidden for other users' data, error body shape, pagination defaults and caps, soft vs hard delete, time zone. Ask only what the code doesn't settle consistently. Obvious behaviors (wrong password fails, bad input is 4xx never 500…) are written asOBV-nwithout asking. - Module by module. Start each module with one question: Ask me each decision / Use recommended defaults and show me the list / Skip testing this module. Then ask the module's non-obvious decisions, up to 4 per call, options with the recommended one first. Show what the code currently does in the option description ("code now: blocks after 10"), never as the recommendation by itself. "Defaults" → show the defaults in one summary and ask Accept / Change some. Track progress by module so the user always knows how much is left.
- Changed functions (
map_functions.pystatuschanged): show the diff withmap_functions.py --diff F012, then ask "F012createOrderchanged. Did its intended behavior change?" with concrete options drawn from the diff and its old decisions (e.g. No, refactor only (Recommended) / Yes: max quantity is now 50 / Yes: coupons are now applied / …). Update or retire the affected decisions; keep the rest. - Removed functions: move their decisions to Retired, then
map_functions.py --retire <ids…>(tests for them are deleted by the worker only if the skill wrote them). A function with statusmoved(renamed or moved, same body) keeps its ID and decisions; just update its heading in TEST_DECISIONS.md. - Write every answer into
qa/TEST_DECISIONS.mdas you go (format intemplates/TEST_DECISIONS.md), thenpython "SKILL_DIR/scripts/map_functions.py" --root . --accept <ids…>to store the hashes of the functions whose decisions are now complete (and--skip <ids…>for skipped ones). - Finish with a one-screen summary (counts per module, notable decisions) and ask Write the tests (Recommended) / Change something.
Phase 5: Brief and run the test writer (read references/goal-prompt.md)
- Write
qa/goal-prompt.mdfromtemplates/goal-prompt.md: goal condition (≤ 1,500 chars, measurable, evidence printed in the transcript), context pack, layout and naming, setup decisions, what to write, constraints, report format. WriteSKILL_DIRas the real absolute path. Only new/changed/retired decisions go in the work list on a rerun. python "SKILL_DIR/scripts/launch_worker.py" --root . --checkvalidates it (sections, condition length, every decision ID referenced exists).- Ask the one runtime question: Auto mode (Recommended) / Accept edits + test-command allowlist / Stop here (keep the plan).
- Launch with Bash
run_in_background: true:python "SKILL_DIR/scripts/launch_worker.py" --root . --mode <auto|acceptEdits> --skill-dir "SKILL_DIR". Always through the launcher (it avoids Git Bash rewriting/goal). You are notified when it exits; it prints status, turns and cost. Meanwhile stay available; don't poll. - When it exits: read
qa/worker-report.mdand runpython "SKILL_DIR/scripts/check_tests.py" --root .. NotREADY(missing decision coverage, app code touched, harness errors) →launch_worker.py --resume --message "<what is left>". App code touched → also tell the user which files, and have the worker revert them. Reviewqa/untestable.jsonif it exists: each entry needs a real reason (no seam, no way to reach it); a weak reason goes back to the worker.
Phase 6: Run, blame-check and report (read references/failure-report.md)
python "SKILL_DIR/scripts/run_tests.py" --root . --coverageruns the full suite exactly the way the user would (the JUnit and coverage variants oftest_command, which the worker stores inqa/test-commands.json) and writesqa/results/results.json: every test, its function and decision IDs, status, message, plus per-function pass/fail and coverage.- Blame check every failing test before it is reported:
- Rerun its file twice (
run_tests.py --file <test file> --times 2). Passes once →flaky. - Harness/setup error (connection refused, missing env, import of a test helper) →
environment; if the harness is at fault, resume the worker to fix it. - Read the test and its decision. Test asserts something the decision doesn't say →
test bug: collect them andlaunch_worker.py --resume --messageonce with the list, then rerun. - Otherwise →
code bug: read the function's line range, find the exact line, explain why. At most 2 resume rounds; whatever remains is reported with its category.
- Rerun its file twice (
- Write
qa/results/analysis.json(format infailure-report.md), thenpython "SKILL_DIR/scripts/make_report.py" --root .rendersqa/TEST_FAILED.md: summary, per-function pass/fail table, each failure with the test, the decision, expected vs actual, why,vscode://file/…links to the failing app line and the test, and the fix process in plain steps (no code), then coverage gaps. It refuses to render if a failure has no analysis. - Set
phase: "done"inqa/state.json.
Phase 7: Reply
In the user's language, short:
- The command that runs everything (e.g.
bun run test) and the totals: functions tested, tests passed / failed, code bugs found. - The top code bugs (one line each, with the VS Code link) and a link to
qa/TEST_FAILED.md. - Flaky and environment items, if any. Coverage gaps worth a decision next time.
- Files added or changed (tests, config, scripts, dev dependencies), all uncommitted, and
/qa-backend --reportto re-run the suite and refresh the report after fixing bugs.
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
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.

