# QA

> Generate the QA checklist for a pull request, one check per behaviour the diff changes, each saying what to do on the running app and what to expect. Run when a PR is opened or updated, or when the user asks for QA / acceptance checks on a PR.

- Skill: `astronomy20/qa` (Agent Skill)
- Install (CLI): `npx skillmds@latest add astronomy20/qa`
- Raw SKILL.md: https://api.skillmd.com/api/skills/astronomy20/qa/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Astronomy20 (https://skillmd.com/u/astronomy20)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/astronomy20/qa

---


Produce the **QA checklist** for one PR: numbered **checks**, each an action on the running app and the result to expect. Checks describe behaviour, so anyone can run them without reading the code; a check may still point at the file or test behind it for whoever wants to look.

Write in the language the ticket is written in (the PR description if there is no ticket).

If the repo documents its issue-tracker workflow (e.g. `docs/agents/issue-tracker.md`), follow it; the commands below assume GitHub via `gh`.

## Process

### 1. Pin the PR

Take the PR number from the argument. Fetch:

- `gh pr view <n> --json number,title,body,headRefName,comments`
- `gh pr diff <n>`

Stop and tell the user if the PR does not resolve or the diff is empty.

### 2. Fetch the acceptance criteria

Find the ticket from issue references in the PR body or its commits (`Closes #m`, `Part of #m`), then `gh issue view <m> --comments`. Extract its acceptance criteria verbatim.

If the PR references no ticket, ask the user for it. If they say there is none, derive the criteria from the PR description and open the checklist with one line saying so.

### 3. Map the diff

Walk every hunk and label it **observable** (a user, a caller of a public endpoint, or a job output sees it change) or **internal** (refactor, type change, logging, test, config). Step 4 spends the list.

### 4. Write the checks

Each check is numbered `QA-<k>` and has one shape: **where** to go, **what** to do, **what** to expect. Short, one action, one result. Add a `→ path/to/file` or `→ test name` after the check only when it helps whoever verifies at code level.

Cover, in order:

1. Every acceptance criterion from step 2: at least one check each. A criterion the diff does not implement is still a check, marked *(not found in diff)*, so missing work is caught rather than assumed.
2. Every observable hunk from step 3 not covered by a criterion: a check marked *(outside the criteria)*, so extra behaviour is seen before it is merged.
3. One negative check per error path or branch the diff adds: wrong input, empty input, external call failing.

Every internal hunk goes under **Not covered by these checks**, one line each stating what it changes, so the reader knows exactly where the checklist stops.

Done when: every acceptance criterion has a check, every changed file is named by a check or listed as not covered.

### 5. Post

Write the checklist to a file and post it as a PR comment (`gh pr comment <n> --body-file`). If the PR already carries a QA comment (found in step 1), edit that comment's body instead of adding a second one (`gh api repos/{owner}/{repo}/issues/comments/<id> -X PATCH -F body=@<file>`). Tell the user where it is.

Template (translate the headings into the checklist language; keep the `QA-<k>` ids as they are):

```markdown
## QA — PR #<n> · ticket #<m>

**Setup**: <one line: branch to check out and how to run the app, from the repo's own run instructions>

### Checks
- [ ] **QA-1** — <where>. <what to do>. Expect: <result>. → `<file or test, optional>`
- [ ] **QA-2** — …

### Edge cases
- [ ] **QA-<k>** — <scenario>. Expect: <result>.

### Not covered by these checks
- <what it changes, one line>
```


