# Peated QA

> Use when manually QAing Peated changes across the API, CLI, or web UI; selecting smoke checks after code changes; using agent-browser for Peated flows; verifying local behavior beyond tests and lint.

- Skill: `dcramer/peated-qa` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add dcramer/peated-qa`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dcramer/peated-qa/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: dcramer (https://skillmd.com/u/dcramer)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/dcramer/peated-qa

---


# Peated QA

Use after Peated code changes need manual behavior checks. This is not a test/lint checklist.

## Select Surfaces

| Changed area                                 | QA                                       |
| -------------------------------------------- | ---------------------------------------- |
| `apps/server/src/orpc/routes/**`             | API + any UI/CLI caller                  |
| `apps/server/src/worker/**`, uploads, queues | API + worker side effect                 |
| `apps/cli/**`                                | CLI + backing API/DB effect              |
| `apps/web/**`                                | UI + API calls it depends on             |
| schema/migration/data model                  | API + CLI + UI path that reads/writes it |

## Start Local Runtime

For normal web UI QA, prefer the root `pnpm dev` command. It starts the web
app, API, worker, package watchers, and shared `.env.local` setup together,
which matches the expected local development runtime. Use the narrower commands
below only when intentionally isolating one surface.

| Need         | Command                                         | URL                                                        |
| ------------ | ----------------------------------------------- | ---------------------------------------------------------- |
| Full app     | `pnpm dev`                                      | web: `http://localhost:3200`, API: `http://localhost:4300` |
| API only     | `pnpm dev:server:api`                           | `http://localhost:4300`                                    |
| API + worker | `docker compose up -d redis`; `pnpm dev:server` | `http://localhost:4300`                                    |
| Web          | `pnpm dev:web`                                  | `http://localhost:3200`                                    |
| CLI          | `pnpm cli <cmd>`                                | loads `.env.local`                                         |

Fallback paired ports when `3200` is busy:

- API:
  `PORT=4301 CORS_HOST=http://localhost:3202 API_SERVER=http://localhost:4301 URL_PREFIX=http://localhost:3202 pnpm exec dotenv -e .env.local -- pnpm --filter @peated/server start:api`
- Web:
  `API_SERVER=http://localhost:4301 URL_PREFIX=http://localhost:3202 pnpm exec dotenv -e .env.local -- pnpm --dir apps/web exec next dev -p 3202`

## API QA

1. Identify exact route file and operation.
2. Hit local API, not `peated.com`: `http://localhost:4300`.
3. For public reads, use `curl` against the route or spec-shaped endpoint.
4. For protected writes, create/login a throwaway local user and send `Authorization: Bearer <token>`.
5. Check success response, validation failure, auth failure, and not-found/conflict when relevant.
6. Verify DB-visible side effects when mutation behavior matters.
7. If the route is used by web/CLI, QA that caller too.

Useful refs:

- Local OpenAPI in dev: `http://localhost:4300/spec.json`
- Production API host for comparison only: `https://api.peated.com`
- Public API paths are under `/v1/*`.

For protected local API QA, use the stable local QA account. Reusing the same
account keeps test data bounded and makes repeated QA runs predictable:

```bash
pnpm cli users create qa@example.com password123 --verified --accept-terms --if-exists
pnpm cli users generate-token qa@example.com
```

Keep the printed token out of committed docs and final reports. Use
`Authorization: Bearer <token>` for protected local API requests.

## CLI QA

1. Run the changed command through root scripts, not direct `tsx`: `pnpm cli <cmd>`.
2. For aliases, prefer root scripts when present: `pnpm bottles`, `pnpm entities`, `pnpm tastings`, `pnpm mocks`, `pnpm user`, `pnpm db`.
3. Use a harmless local fixture or throwaway record.
4. Verify stdout/stderr, exit status, and DB/API side effect.
5. For destructive commands, use dry-run/help first when available; otherwise use local throwaway data only.
6. If a CLI command drives server logic, also QA the matching API route or DB result.

## Classifier QA

Use this for changes under `packages/bottle-classifier/**` or
`apps/server/src/agents/bottleClassifier/**`.

1. For bottle-name checks, run:
   `pnpm cli classifier run "Ardbeg Uigeadail"`.
2. For image checks, run:
   `pnpm cli classifier run --image /path/to/bottle.jpg` or
   `pnpm cli classifier run --image https://example.com/bottle.jpg`.
3. For exact contract payloads, run:
   `pnpm cli classifier run --input-file /tmp/classifier-input.json`.
4. Use `--initial-only` when the check should stay closed-set and avoid follow-up
   bottle/web search.
5. Live classifier runs use `.env.local`, local DB adapters, and OpenAI config.
   They may call OpenAI and local search depending on the reference.
6. Pair manual classifier smoke checks with package validation:
   `pnpm --filter @peated/bottle-classifier typecheck` and focused tests or evals.

Minimal input-file payload:

```json
{
  "reference": { "name": "Ardbeg Uigeadail" },
  "candidateExpansion": "initial_only"
}
```

## UI QA

1. Start API and web with matched origins.
2. Read `docs/development/local-web-checks.md` before protected,
   owner-only, or moderator UI checks.
3. Choose the auth primitive before opening the target route:
   - Public/read-only route: no session setup.
   - Normal protected workflow: use the UI login path.
   - Owner/moderator-only visual check: use the local verification playbook to
     create a session cookie for the exact user/role being inspected, then
     reload the target route.
   - Protected mutation: use a real local user and access token/session, not a
     display-only cookie.
4. Use `agent-browser` for browser checks.
5. Open the exact target route after auth is ready, then inspect it with both
   accessibility snapshots and screenshots.
6. Verify desktop and mobile widths for changed user-facing flows.
7. Prefer normal login:
   `/login?redirectTo=/addBottle` -> `Sign in with Email` -> `Or sign in with a password`.
8. For local protected UI checks, seed a throwaway verified active user with
   `termsAcceptedAt`, then log in through the UI. Do not use bearer-token API
   setup or a manually sealed `_session` cookie for UI QA unless normal UI login
   is blocked by unrelated local service noise.
9. For moderator flows, set that throwaway user `mod: true`.
10. For bottle entry changes, check `/addBottle` and `/bottles/<id>/edit`.
11. Inspect rendered state, network/API outcome, persistence after reload, and error/empty/loading states when changed.
12. Clean up throwaway local users/records when done.

Agent-browser primitives:

- Set the viewport before capture: desktop first, then mobile.
- Use `snapshot -i -c` to verify reachable controls and table/list structure.
- Save screenshots under `/tmp` with names that include the route and viewport.
- For owner-only columns or controls, verify the public state only if it is part
  of the requested behavior; otherwise authenticate first and avoid spending
  time on the wrong state.

## Finish With Evidence

Report:

- Surfaces QAed: API / CLI / UI.
- Commands and URLs used.
- Browser viewport(s), if UI.
- Data used or created.
- Pass/fail per scenario.
- Any skipped surface and why.

