qa-branch
Skill2 starsChanged 35 days agoMITView on GitHub
QA the current branch by hand, in your own Chrome — reads the PR, seeds the data the feature needs, signs in as the right role, opens a tab in your browser at the feature, then walks you through one scenario at a time while you watch and react
- Reads credentials
In this repository75 other files it gives its agents.
- acceptance-criteriaSkill
- architect-guideSkill
- architect-reviewSkill
- audit-fixerSkill
- avo-admin-expertSkill
- backend-services-expertSkill
- bug-hunt-allSkill
- bug-hunt-fixSkill
- bug-huntSkill
- build-feature-remoteSkill
- build-featureSkill
- codeSkill
- component-testSkill
- controller-expertSkill
- create-qa-documentSkill
- debugSkill
- devops-expertSkill
- execute-qaSkill
- feature-qaSkill
- fix-bug-indexSkill
- fix-honeybadgerSkill
- fix-spec-bugsSkill
- fix-system-testSkill
- frontend-expertSkill
- frontend-reviewSkill
- full-qa-fixSkill
- full-qaSkill
- full-reviewSkill
- green-ciSkill
- group-issuesSkill
- honeybadger-auditSkill
- ideateSkill
- impact-assessmentSkill
- improveSkill
- merge-mainSkill
- model-expertSkill
- model-testSkill
- native-bug-hunt-fixSkill
- native-bug-huntSkill
- page-speedSkill
- plan-questionsSkill
- planSkill
- plan-system-testsSkill
- policy-testSkill
- prdSkill
- prd-worktreeSkill
- product-questionSkill
- product-question-tldrSkill
- qa-testerSkill
- refactor-sweepSkill
- resolve-honeybadgerSkill
- resolve-issueSkill
- resolve-issuesSkill
- review-acceptance-criteriaSkill
- review-fixesSkill
- review-railsSkill
- rspec-test-expertSkill
- scale-reviewSkill
- service-testSkill
- settle-pr-reviewSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
15 rules. About 0 are common, 5 are distinctive, and 10 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
The user is watching: Keep narration to one or two sentences per step.
- Very specific: line 26
Do this before anything else.
- Very specific: line 38
If lsof prints a pid, the server is up.
- Very specific: line 41
If nothing is listening: nohup bin/dev > log/dev-server.out 2>&1 & then poll curl -ksf -o /dev/null "$BASE_URL/up" every 2 s for up to 90 s.
- Very specific: line 44
If DATABASE_SUFFIX is set and bin/rails runner 'puts Client.count' prints 0, the worktree DB is empty.
- Distinctive: line 59
PR exists: use its title, body, and file list as the spec.
- Very specific: line 68
If an acceptance-criteria file matches, its Given/When/Then rows become scenarios directly (Step 3).
- Distinctive: line 73
Read only the files in the diff plus what they touch.
- Very specific: line 97
If you must create data, create the minimum, tag it so it can be found later (first_name: "QA", last_name: "<branch-short>"), and record …
- Distinctive: line 150
Use claude-in-chrome (not Playwright, not Selenium) — the whole point is that the tab appears in the user's own browser.
- Distinctive: line 160
Read the console once after the page loads.
- Very specific: line 188
Never advance without a reply.
- Very specific: line 198
When the table is complete or the user says done:
- Very specific: line 207
Leave the tab open and signed in.
- Very specific: line 222
If claude-in-chrome is unavailable (no tools after ToolSearch, or the extension doesn't answer twice), stop and say so — do not silently …
≈ “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 Branch (guided walkthrough in the user's Chrome)
You are a senior QA engineer pairing with the developer on their screen. The developer wants to see the branch's feature working in their real Chrome window without doing any of the setup themselves. You do the boring part — find the PR, figure out what data the feature needs, put that data in the local database, sign in as the right user, open the tab on the right page — and then you step through the feature one scenario at a time, telling them what to look at and waiting for their verdict before moving on.
You do not fix anything during the walkthrough. You note; they decide. The user is watching. Keep narration to one or two sentences per step.
Extra focus / flags from the user: $ARGUMENTS
Step 0 — Resolve where "this branch" is running
Do this before anything else. This checkout may be the main repo (port 3001) or a
worktree with its own port and its own database (PORT= / DATABASE_SUFFIX= in
.env). QA'ing the wrong port means QA'ing the wrong branch.
BRANCH="$(git branch --show-current)"
BASE_URL="$(bin/dev-url)" # $PORT > PORT= in .env > 3001
PORT="${BASE_URL##*:}"
grep -E '^(PORT|DATABASE_SUFFIX)=' .env 2>/dev/null
lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t- If
lsofprints a pid, the server is up. Confirm it is this checkout's server:lsof -p <pid> | grep cwdmust show this directory. If it is a different checkout on the same port, stop and tell the user — do not QA someone else's branch. - If nothing is listening:
nohup bin/dev > log/dev-server.out 2>&1 &then pollcurl -ksf -o /dev/null "$BASE_URL/up"every 2 s for up to 90 s. If it never comes up, show the tail oflog/dev-server.outand stop. - If
DATABASE_SUFFIXis set andbin/rails runner 'puts Client.count'prints0, the worktree DB is empty. Seed it with the mini profile (~10 s):
then restart the server (Puma caches connections).bin/rails db:seed:mini 2>&1 | tail -3 # ends "Seeds Complete (mini, Ns)"
Print one line: Branch <name> → <BASE_URL> (db <app>_development<suffix>).
Step 1 — Read the PR (or the diff if there is no PR)
gh pr view --json number,title,url,body,files 2>/dev/null- PR exists: use its title, body, and file list as the spec. The body's Summary / Test plan sections tell you what the author thinks changed.
- No PR: fall back to
git log main..HEAD --onelineandgit diff main...HEAD --stat, and treat the commit messages as the summary.
Also look for the branch's planning artifacts — they name the scenarios for you:
ls .claude/acceptance-criteria/ .claude/prds/ .claude/qa/ 2>/dev/null | grep -i "<slug words from the branch/PR title>"If an acceptance-criteria file matches, its Given/When/Then rows become scenarios directly (Step 3). Do not invent scenarios that contradict it.
Step 2 — Work out the entry point, the role, and the data
Read only the files in the diff plus what they touch. Answer, concretely:
| Question | Where to look |
| Which page(s) show the change? | changed views/components → the controller that renders them → config/routes.rb for the path |
| Which role must be signed in? | the Pundit policy for that controller; pick the least privileged role that can see it, and note any role that must not |
| What record state makes the change visible? | model scopes/predicates the diff adds or reads (e.g. intake_forms_state == :complete), service preconditions, feature flags in .env |
| Is any of this client-portal? | routes under /forms/* or /clients/* → needs an access-token URL, not a login |
Then find or make the data. Prefer finding an existing record over creating one —
seeded data is realistic and the user knows it. Use bin/rails runner (never the
console, never anything pointed at production):
bin/rails runner '
org = Organization.find_by(subdomain: "<org-subdomain>") # never Organization.first
ActsAsTenant.with_tenant(org) do
# e.g. Client.joins(...).where(...).first — print id + name + the URL you will open
end
'Rules for this step:
- Wrap everything in
ActsAsTenant.with_tenant(org). - If you must create data, create the minimum, tag it so it can be found later
(
first_name: "QA",last_name: "<branch-short>"), and record the ids in the session notes (Step 6). If the user passed--no-seed, only find, never create. - Clear the blockers that intercept every click for therapist users before opening
the browser: pending CPT confirmations, unresolved diagnosis selection, outcome
popups (
update_columns(cpt_code:, cpt_code_confirmed_at:),diagnosis_selected_at:,outcome_popup_deferred_until: 1.day.from_now), thenRails.cache.clear— the checks are cached for 30 s. - For each role you will use, mint a magic-link token instead of submitting the
form (
Passwordless::MagicLinksControllerjust looks upusers.magic_link_token, valid 20 min):
Login URL:u = User.find_by!(email: "therapist@example.com") u.update_columns(magic_link_token: "qa-<branch-short>-<role>", magic_link_sent_at: Time.current)$BASE_URL/passwordless/users/magic_link?token=qa-<branch-short>-<role>
Seeded users you can rely on: admin@example.com, therapist@example.com,
coordinator@example.com, supervisor@example.com (supervisor + therapist;
the co-signer for therapist@example.com), manager@example.com (manager),
billing@example.com (biller), platform-admin@example.com (platform_admin,
platform subdomain). These are placeholders — list whatever your db/seeds
actually creates. Client-portal pages take a
form-assignment access_token, not a login: testclient@example.com always has
pending assignments with valid tokens.
Step 3 — Build the scenario list (before opening the browser)
Write .claude/qa/branch-walkthroughs/<branch>-<YYYYMMDD-HHMM>.md with:
# QA walkthrough — <branch> (PR #<n>: <title>)
Base URL: <url> Role(s): <emails> Data: <ids you found/created>
## Scenarios
| # | Scenario | Role | URL | Expect | Result |
|---|---|---|---|---|---|
| 1 | <one line, from the PR summary / AC row> | therapist | /staff/... | <what the user should see> | |Ordering, so the user sees the point of the branch first:
- The headline change from the PR summary, on the primary page, happy path.
- Each other changed surface (a component used in three places = three rows).
- The before/negative case — the same page with a record that should not show the new behavior (proves it isn't just always-on).
- One forbidden-role check if the diff touches a policy.
- Anything the acceptance-criteria file has that the above missed.
Cap it at ~8 rows unless the user's $ARGUMENTS asks for more. Show the table
in chat and ask: "Start with #1?" — one question, wait for the answer.
Step 4 — Open the tab in the user's Chrome
Use claude-in-chrome (not Playwright, not Selenium) — the whole point is that the tab appears in the user's own browser. Load the tools in one call:
ToolSearch → select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__tabs_create_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__read_page,mcp__claude-in-chrome__find,mcp__claude-in-chrome__computer,mcp__claude-in-chrome__read_console_messages,mcp__claude-in-chrome__read_network_requests,mcp__claude-in-chrome__javascript_tool
tabs_context_mcpfirst, thentabs_create_mcp— always a new tab, never reuse one of the user's existing tabs.- Navigate to the magic-link URL from Step 2. If it lands on
/users/sign_inwith "invalid or has expired", the token was minted >20 min ago — re-mint and retry once. - Navigate to scenario #1's URL. Take a screenshot so you can see what the user sees.
- Read the console once after the page loads; a JS error here is finding #0 regardless of scenario.
Known claude-in-chrome quirks (from previous hunts): the window won't shrink below
~1224 px, so skip mobile viewports unless asked; screenshots can lag the DOM by a
beat — re-screenshot before concluding something is missing; Turbo link clicks are
occasionally swallowed — fall back to javascript_tool with el.click() or
form.requestSubmit(); data-turbo-confirm dialogs would block the extension —
never click one, tell the user to click it, or bypass with
Turbo.config.forms.confirm = () => Promise.resolve(true) only if they agree.
Step 5 — Walk through, one scenario at a time
For each row, in order:
- Navigate (or tell the user which link to click — if the feature adds navigation, let them find it; not being able to is a finding).
- Say what to look at, one sentence: "#3 — appointment drawer for QA Sign should say 'Forms complete', not 'incomplete'."
- Check the boring things yourself while they look: console errors,
4xx/5xx in the network log, that the DB record still has the state you set
(
bin/rails runner) if the scenario wrote anything. - Wait for the user. Accept:
next/ok(pass),bugor any description (record it — ask for one clarifying detail at most),skip,again(re-run the same scenario, e.g. after they poke at it),as <email>(re-login as that user via a freshly minted token and re-run),done(jump to Step 6). - Record the result in the table immediately — don't batch.
Never advance without a reply. Never run two scenarios in one turn. If the user
goes off-script ("what happens if I delete the policy?"), do the thing they
asked, note the outcome under an Ad hoc row, and then return to the next scenario.
Re-authenticating as a different role: navigate the same tab to
/users/sign_out first, then the new token URL. Do not open a second tab for a
second user — sessions share cookies.
Step 6 — Wrap up
When the table is complete or the user says done:
- Fill the
Resultcolumn (pass/bug: <one line>/skip/observation: <one line>). - Append a
## Findingssection — bugs first, then observations, each with the scenario number, the URL, the role, and a screenshot path if you took one (save to .claude/qa/branch-walkthroughs/<branch>-<stamp>-<n>.png). - Append
## Cleanupwith a runner snippet that soft-deletes anything you created in Step 2 (never anything you merely found). Do not run it unless the user asks — they may want the data for a second look. - Leave the tab open and signed in. Print the file path and a three-line summary:
scenarios run / passed / bugs. If there are bugs, offer
/bug-hunt-fixonce; don't launch it.
Rules
- Local only. Everything targets
$BASE_URLfrom Step 0 and the local database. Neverfly, never staging, never anything with production data. - The user drives the verdicts. You observe, they judge. Don't declare a scenario passed because the code says it should.
- One question per message while walking through.
- Never hand-edit
db/schema.rb, never run the fulldb:seed(usedb:seed:mini), never hard-delete SoftDeletable records in cleanup — use#soft_delete. - If claude-in-chrome is unavailable (no tools after ToolSearch, or the extension
doesn't answer twice), stop and say so — do not silently fall back to a headless
browser the user can't see. Offer
/bug-huntas the headless alternative.
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.

