From citadel
Launches a real browser with Playwright to verify web app functionality through interaction testing. Works standalone or as a campaign phase end condition.
How this skill is triggered — by the user, by Claude, or both
Slash command
/citadel:qaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
/qa requires Playwright. It's an optional dependency.
/qa requires Playwright. It's an optional dependency.
If Playwright is installed: full browser QA works. If Playwright is NOT installed: the skill offers to install it, or falls back to /live-preview (screenshot-only verification).
Detection:
npx playwright --version 2>/dev/null
Installation (if user agrees):
npm install -D playwright
npx playwright install chromium
Only installs Chromium (smallest download, ~150MB). Not Firefox or WebKit unless the user asks for cross-browser testing.
/do setup integration: During setup, if the project is a web app (has React, Next.js, Vue, Svelte, or HTML files), offer to install Playwright: "I see this is a web project. Want to enable browser QA testing? This installs Playwright (~150MB) for interaction testing. (y/n)"
If they say no, /qa falls back to /live-preview. No pressure.
Before testing, understand what to test:
If no PRD or campaign exists, ask: "What should I test? Give me 1-3 user flows."
Before testing, the app needs to be running:
npm run dev or equivalent, in backgroundTrack whether the agent started the server. If so, kill it on completion.
For each flow identified in Step 1, write and run a Playwright script:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
// Navigate
await page.goto('http://localhost:3000');
// Verify page loaded
const title = await page.title();
// Test interactions
await page.click('button[data-testid="add-todo"]');
await page.fill('input[name="title"]', 'Test todo');
await page.click('button[type="submit"]');
// Verify result
const todoText = await page.textContent('.todo-item:last-child');
// Screenshot for evidence
await page.screenshot({ path: '.planning/screenshots/qa-flow-1.png' });
await browser.close();
})();
For each test:
Write results to .planning/qa-report-{date}.md:
# QA Report: {App Name or Feature}
> Date: {ISO date}
> Flows tested: {N}
> Passed: {N}
> Failed: {N}
> Screenshots: .planning/screenshots/qa-*.png
## Results
### Flow 1: {description}
- Steps: {what was done}
- Expected: {what should happen}
- Actual: {what did happen}
- Result: PASS / FAIL
- Screenshot: {path}
- Notes: {any observations}
### Flow 2: ...
When running as a phase end condition:
The campaign file can specify QA conditions:
| 3 | qa_verify | /qa passes for: add todo, complete todo, delete todo |
/qa reads the condition, runs those specific flows, and reports pass/fail. The phase is complete only if all specified flows pass.
For apps with authentication:
Test credentials should come from .env.example or the campaign file.
NEVER read from .env (protected by the hook). Use test accounts only.
If Playwright isn't installed and the user declines installation:
Playwright not installed and user declines: Fall back to /live-preview. Mark all interaction tests as SKIPPED in the report. Visual-only verification still runs.
Dev server won't start: Report the startup error and stop. Do not attempt to test a server that isn't running. Suggest the user fix the startup error first.
No routes or pages discoverable: Ask the user for 1-3 flows to test. Do not guess at routes.
No UI (API-only project): Report "No UI detected — /qa requires a browser-accessible interface. Use typecheck and unit tests for API verification." Then stop gracefully.
If .planning/screenshots/ does not exist: Create it before saving screenshots. If .planning/ doesn't exist, save screenshots to a qa-screenshots/ directory in the project root and note the path in the report.
After saving screenshots, videos, rendered PDFs, or QA reports in Codex, register each durable artifact so the Codex app/browser workflow can find it later:
node scripts/codex-app-artifacts.js record --workflow qa --kind screenshot --path ".planning/screenshots/qa-flow-1.png" --status pass
The manifest lives at .planning/artifacts/codex-app-evidence.jsonl.
Before reporting QA as complete in Codex, verify the manifest points at real files:
node scripts/codex-app-artifacts.js verify --require-artifacts
Disclosure: May start a dev server; saves screenshots and report to .planning/. States server ownership before starting.
Reversibility: amber — creates report and screenshots; dev server stopped only if this skill started it. Delete generated files to undo.
Trust gates: Any. Familiar (5+) to run against external/production URLs.
---HANDOFF---
- QA Report: .planning/qa-report-{date}.md
- Flows tested: {N}
- Passed: {N} | Failed: {N} | Skipped: {N}
- Screenshots: .planning/screenshots/qa-*.png
- Server: {started by agent (killed) | was already running (left running)}
- Reversibility: amber — delete `.planning/qa-report-{date}.md` and `screenshots/qa-*.png` to undo
---
npx claudepluginhub sethgammon/citadel --plugin citadelDrives web app UI through core positive flows using Playwright automation. Verifies end-to-end user journeys with snapshots and bug reporting.
Tests local web applications using Playwright: verifies frontend functionality, debugs UI behavior, captures screenshots, views logs. Mandatory before declaring implementation complete.
Runs a full QA pipeline: launches app-scout for project recon, then tests the app via browser interaction, produces a QA report, and generates Playwright E2E tests for regression.