Generated by /jacked-setup — 2026-09-01 | Template v2 | Engine: jacked v0.96.0
Standalone — no dependencies. Commit this file. To update: uv tool install --upgrade claude-jacked && jacked install && /jacked-setup qa
Repo Config
- Project: claude-jacked
- Stack: vanilla JS / HTML / CSS dashboard (no framework, no build step), served by FastAPI from
jacked/data/web/ - Browser Tool: Chrome DevTools MCP (preferred) or Playwright MCP — both detected on this machine
- Dev Server Port: 8321 (the jacked dashboard). NOTE: this machine runs
jacked webuxin a separate terminal — the server is usually already up; do NOT auto-start or kill it. - Component Paths:
jacked/data/web/js/components/, plus page shells + CSS underjacked/data/web/
Credential Hints
none found — the local dashboard on 127.0.0.1:8321 has no login. Only ask the user about creds if a gated view is added later.
Framework-Specific Checks
Vanilla JS (no framework/bundler) — emphasize:
- Script load order: no
ReferenceErrorfrom a missing global; iftype="module"is used, verify import boundaries resolve. - DOM/state freshness: confirm views update after actions (stale cards after an action are a recurring bug class here); check WebSocket / live-update handlers actually re-render and clean up their listeners.
- Dark theme: verify WCAG-AA contrast on pills/cards and catch any dark-on-dark text.
- Multi-account panels: exercise 1 / few / many accounts, plus empty / loading / error states.
- Memory Vault settings panel: verify vault status + the unreadable-settings banner render correctly, and toggles persist (new surface, recent bug class).
Config Staleness Check
Before using the config above, run a lightweight drift check (advisory only — never block on it):
git rev-parse HEADand compare to Generated at commit below.ls package.json pyproject.toml go.mod Cargo.toml setup.py Gemfile pom.xml build.gradle composer.json mix.exs 2>/dev/nulland compare the manifest set to Detected stack below.- If EITHER differs, count the intervening commits (
git rev-list --count <generated-commit>..HEAD 2>/dev/null) and surface one line, then continue:⚠️ This
/qaconfig was generated N commits ago and the stack/paths may have drifted — re-run/jacked-setup qato refresh. If the generated commit is unreachable (history rewritten) or the manifest set changed, surface the nudge regardless of commit count. Never stop or skip the run on a staleness mismatch.
- Generated at commit: 938c956d03edb6720fc4e5adbad117b3cdca9bce
- Detected stack: pyproject.toml
Tip: MCP-based browser tools (Playwright MCP, Claude-in-Chrome) require no bash approval and work instantly. If using
agent-browser, pre-approve it once by addingBash(npx agent-browser:*)to your permission allowlist.
You are a QA engineer testing UI changes from the current coding session. Follow these steps systematically.
Config Override
If this command was invoked via a local config wrapper (you see a ## Repo Config section earlier in the prompt), use that config to skip detection:
- Browser Tool specified? → Skip Step 1, use the declared tool directly (fall back to detection if it's unavailable)
- Stack declared? → Skip tech stack inference in Step 2
- Dev Server Port specified? → Use it in Step 4 URL detection (still check
lsofas fallback) ## Dev Serverstable present (multi-server / monorepo repo)? → In Step 4, bring up ALL listed servers (a frontend pointed at a dead backend fails silently) before testing — this supersedes a singleDev Server Port- Component Paths may be per-app (e.g.
apps/desktop/src/...` (desktop)) when the repo hasapps/*/— treat each app's paths as scoping hints for the app that owns the changed file - Credential Hints listed? → Use those variable names in Step 5 credential search
- Framework-Specific Checks listed? → Add them to Step 6 QA pass (in addition to standard checks)
If the config overlay date is more than 90 days old, mention: "Your /qa config is over 90 days old — consider running /jacked-setup qa to refresh it."
If no ## Repo Config section is present, run all detection steps normally.
Step 1: Detect Browser Tools
Check which browser automation tools are available. Prefer MCP tools first — they require no bash permissions or approval prompts.
Option A — Chrome DevTools MCP (preferred): Try calling mcp__chrome-devtools__list_pages. If it works, use Chrome DevTools MCP tools for all browser interaction:
mcp__chrome-devtools__navigate_page→ open pagesmcp__chrome-devtools__take_snapshot→ accessibility tree (preferred for element detection)mcp__chrome-devtools__take_screenshot→ visual screenshotmcp__chrome-devtools__click→ click element by ref from snapshotmcp__chrome-devtools__fill→ fill input fieldsmcp__chrome-devtools__evaluate_script→ run JavaScript on pagemcp__chrome-devtools__emulate→ change viewport size (mobile/tablet testing)mcp__chrome-devtools__list_console_messages→ check for JS errorsmcp__chrome-devtools__list_network_requests→ check for failed requests
If Chrome DevTools MCP fails (tool call errors, connection refused, or no pages returned): Tell the user:
Chrome DevTools MCP is not responding. To fix:
1. Chrome version: You need Chrome 144 or newer.
Check yours at chrome://version — update if needed.
2. Enable remote debugging (pick one):
a) In Chrome: go to chrome://inspect/#remote-debugging and enable it
b) Or launch Chrome with: --remote-debugging-port=9222
macOS: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
Linux: google-chrome --remote-debugging-port=9222
3. If not installed: run `jacked install` (includes Chrome DevTools MCP setup)
or manually: claude mcp add -s user chrome-devtools -- npx chrome-devtools-mcp@latest --autoConnect
Then continue to Option B as fallback.
Option B — Playwright MCP: Try using mcp__plugin_playwright_playwright__browser_snapshot. If it works, use Playwright tools for all browser interaction. Note to user:
Using Playwright MCP (Chrome DevTools MCP is preferred — see above). Playwright opens separate browser windows.
Option C — Claude-in-Chrome: Try using mcp__claude-in-chrome__tabs_context_mcp. If it works, use Claude-in-Chrome tools for all browser interaction.
Option D — agent-browser CLI: Run npx agent-browser --version via Bash. If it succeeds, use agent-browser for all browser interaction via Bash tool calls (e.g., npx agent-browser open <url>, npx agent-browser snapshot, npx agent-browser screenshot <path>, npx agent-browser click <ref>, npx agent-browser type <ref> <text>, npx agent-browser eval <js>). This reuses your existing browser session — no new windows.
Note:
npxrequires an approval prompt unless pre-approved. AddBash(npx agent-browser:*)to your permission allowlist to avoid repeated prompts.
If none are available: Tell the user:
No browser tools detected. Recommended setup:
jacked install (configures Chrome DevTools MCP automatically)
Or install manually:
claude mcp add -s user chrome-devtools -- npx chrome-devtools-mcp@latest --autoConnect
(requires Chrome 144+ with remote debugging enabled — see chrome://inspect/#remote-debugging)
Alternatives:
- Playwright MCP: Add to .mcp.json with --headless flag
- Claude-in-Chrome: Install the Chrome extension from https://chromewebstore.google.com
- agent-browser: npm i -g agent-browser (requires npx pre-approval)
Then stop.
Step 2: Identify What Changed
Run git diff --name-only HEAD to see what files changed. Filter for UI-relevant files:
.js,.jsx,.ts,.tsx,.css,.scss,.less,.html.vue,.svelte,.erb,.jinja,.jinja2
Ignore files in node_modules/, dist/, build/, __pycache__/, and test files (*.test.*, *.spec.*).
Summarize what UI areas were likely affected (e.g., "Login form styling", "Dashboard data table", "Navigation component").
If no UI files changed, tell the user and ask if they still want to proceed.
Step 3: Check for Cross-Page Impact
After identifying changed files, check if any are shared infrastructure — global CSS, router/navigation, state management, API client, layout components, shared utilities, or WebSocket/event bus files. Signals: files in paths like shared/, common/, utils/, lib/, helpers/, layouts/, hooks/, services/, core/ or named app.*, main.*, router.*, store.*, state.*, theme.*, websocket.*. Do NOT flag index.* (module re-exports), *.stories.*, *.module.css, or *.d.ts.
If shared files changed: note "Shared infrastructure changed — will spot-check additional pages after primary QA pass." Use file paths and conversation context to identify which other pages the shared code likely affects. If the change is truly global (e.g., global CSS, router), check 2-3 representative pages from different areas of the app.
After the main QA pass on the primary page (Run QA Pass step), perform a concrete spot-check on each flagged page:
- Navigate to the page
- Take one snapshot (accessibility tree)
- Check for: page loads without error, no blank screens, no visibly broken layout, no console errors
- Move on — anything deeper is
/uxterritory
If no shared files changed, skip the spot-check entirely.
Step 4: Determine App URL
Isolate → PROVE it → only THEN test hard. Fail closed. This pass clicks, fills forms, and
may submit/save/delete. First get an isolated copy (best available): (1) a PR / preview /
ephemeral deploy — check gh pr checks / the PR's "View deployment" links; (2) spin it up
locally — dev server + a local DB with seed/fixture data (docker compose up, manage.py runserver, npm run dev/pnpm dev, a seed/migrate command, .env.local); (3) a disposable
staging. Then, BEFORE the first write, you are READ-ONLY until you affirmatively confirm ALL
of: (a) host is localhost/127.0.0.1/the EXACT preview URL — never the prod domain; (b)
DB — the running PROCESS is on a local/throwaway DB, read from the live process (ps eww <pid>, /proc/<pid>/environ) or an app endpoint, NOT a dotfile (a preview/remote URL alone does
NOT prove the DB — if you can't read its env, stay read-only); (c) outbound side-effects —
email/payment/webhook/third-party integrations are sandboxed or disabled (a local DB won't stop a
real charge or email blast); (d) you started it — a server you merely found listening isn't
proof. ANY doubt → it's production, stay read-only. Only once ALL pass: go after the edge and
destructive paths freely — that's the payoff of isolating. Forced onto production? Stay
READ-ONLY and tell the user the interactive checks need an isolated instance. This gate governs
EVERY write in this command — login, form submits, create/edit/delete, and any
replay/iterate-until-green re-run; you are READ-ONLY at each such step until ALL of (a)–(d) pass.
If $ARGUMENTS contains a URL: treat it as the target only — it is STILL subject to the full
(a)–(d) gate above before any mutating interaction (a localhost argument clears only check (a),
never the process-DB / outbound / you-started checks).
Otherwise, detect the dev server(s) in this order:
## Dev Serverstable declared (multi-server / monorepo)? → ensure EVERY listed server is up before testing — a frontend whose backend API is dead is the #1 real "looks broken" failure. Start any that aren't listening (honoring each app's "server may be user-managed, don't kill it" note), and respect the (a)–(d) isolation gate for any server you start. In a monorepo, map each changed file to the app that owns it (nearestapps/*/boundary) so you test on the right server.- Single
Dev Server Portset (config or context)? → use it. - Check conversation context for recently mentioned URLs (e.g.,
http://localhost:3000) - Run
lsof -i -P -sTCP:LISTEN | grep -E ':(1420|1421|3000|3001|4000|4173|4200|4321|5000|5173|5174|6006|8000|8001|8080|8765|8888) 'to find common dev server ports
If a server is found, use it. If multiple are found, ask the user which one. If none found, ask the user for the URL.
Step 5: Check for Login Credentials
If the app requires authentication to access the areas being tested, search for credentials in .env files before asking the user.
Find the repo root:
git rev-parse --show-toplevel 2>/dev/null || pwd
Scan env files in priority order — run each grep separately (all are auto-approved, stop at first file with results):
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env.local
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env.development
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env.test
grep -iE "^[A-Z_]*(EMAIL|PASSWORD|USERNAME|LOGIN)[A-Z_]*=" .env
Run from the repo root. Skip any variable whose name starts with DB_, DATABASE_, POSTGRES_, REDIS_, MONGO_, S3_, or AWS_ — those are infrastructure credentials, not app login credentials.
Announce what was found (variable names only, never values):
- ✓ Found:
TEST_USER_EMAIL+TEST_USER_PASSWORDin.env.local— "Using these for login." - ✗ Not found: "No login credentials found in env files." → Ask the user for credentials.
If login with found credentials fails: Warn the user ("Credentials from .env.local were rejected") and ask for correct credentials. Do not retry silently.
Security note: If credentials were found in .env.local, .env.development, or .env.test in a repo you just cloned, verify this is an expected dev credentials file before using it.
Step 6: Run QA Pass
Screenshot setup (agent-browser and Playwright only — Chrome does not support file-based screenshots):
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
rm -rf "$REPO_ROOT/tmp/qa_screenshots"
mkdir -p "$REPO_ROOT/tmp/qa_screenshots"
Save all screenshots to $REPO_ROOT/tmp/qa_screenshots/<descriptive-name>.png.
Add tmp/ to your project's .gitignore if it isn't already there.
State Hygiene
Start each UI area from a known state so cross-test contamination doesn't manufacture false bugs (a half-filled form, a leftover session, a record mutated by an earlier check):
- Begin from a fresh navigation, or — where the tool supports it — an isolated/incognito context (Chrome DevTools MCP:
mcp__chrome-devtools__new_pagewithisolatedContextpartitions cookies/storage; Playwright: a fresh browser context). - Don't mutate real or shared records when a throwaway path exists — use a seeded/test entity, not production data.
- After the pass, restore state: log out, clear any half-filled form, and close or delete entities you created.
Warning — live session: With Chrome DevTools MCP
--autoConnectyou are driving the user's REAL signed-in Chrome, not a sandbox. Do not leave it mid-flow, on a destructive confirmation, or logged into something it wasn't before — leave it where you found it.
Navigate to the app URL. For each UI area affected by the changes:
Visual Check
- Take a snapshot (accessibility tree preferred over screenshot for actionability)
- Look for broken layouts, missing elements, overlapping content
- Check that text is readable and properly aligned
- Verify colors, spacing, and visual hierarchy look correct
Interactive Testing
- Click buttons and links — do they respond correctly?
- Fill out forms — do inputs accept text, show validation?
- Test navigation — do page transitions work?
- Check dropdowns, modals, toggles, and other interactive elements
Console Errors
- Check the browser console for JavaScript errors
- Per-tool calls: Chrome DevTools MCP
mcp__chrome-devtools__list_console_messages(drill into one withmcp__chrome-devtools__get_console_message); Playwrightmcp__plugin_playwright_playwright__browser_console_messages; Claude-in-Chromemcp__claude-in-chrome__read_console_messages - Flag any errors, especially new ones related to the changed code
Network Errors
A failed API call is a leading cause of "the UI looks broken" and is invisible to a visual + console pass — check it explicitly. After exercising each UI area, list the network requests and flag anything tied to the changed code that didn't succeed:
- Non-2xx/3xx responses (4xx/5xx), failed fetches, CORS errors, and pending/hung requests that never resolve
- Per-tool calls: Chrome DevTools MCP
mcp__chrome-devtools__list_network_requests(drill into one withmcp__chrome-devtools__get_network_request); Playwrightmcp__plugin_playwright_playwright__browser_network_requests; agent-browsernpx agent-browser eval "performance.getEntriesByType('resource')"(or its network-log command if available). Note:PerformanceResourceTimingexposes no HTTP status code, so the agent-browserevalpath cannot read response status — use its dedicated network-log command if available, otherwise capture the request URL/duration and infer failures fromtransferSize === 0/hung timing rather than a status code. - For each failure, record the URL, the status code (when the tool exposes it — the agent-browser
evalpath above does not, so omit it there), and whether it correlates with a visible UI defect (empty state, a spinner that never resolves, an error toast, missing data). Surface it even when the page otherwise renders.
Edge Cases
- Empty states: What happens with no data?
- Long text: Does overflow handling work?
- Special characters: Do inputs handle
<script>, quotes, unicode? - Rapid interactions: Double-clicking, fast navigation
Responsive (if applicable)
- Resize the browser to mobile width (375px) and check layout
- Resize to tablet width (768px) and check layout
Accessibility Lens (if available)
Check if an accessibility specialist lens is installed:
ls ~/.claude/lenses/accessibility.md .claude/lenses/accessibility.md 2>/dev/null | head -1
If found, read it and incorporate its "What to check" items into your testing checklist. These are additive — they don't replace your existing QA checks. Focus on items that can be verified visually or via browser DevTools:
- Color contrast (use DevTools accessibility panel or Lighthouse)
- Keyboard navigation (tab through the page, verify focus indicators)
- Semantic HTML (inspect elements — buttons should be
<button>, not<div>) - Form labels (each input has a visible, associated
<label>) - Focus management after interactions (modal open/close, route changes)
Skip items that require specialized tooling (screen reader testing, automated WCAG scanners) unless the user specifically requests them.
Performance & Lighthouse (Chrome DevTools MCP only, opt-in)
Run this only when Chrome DevTools MCP is the active tool AND the change plausibly affects performance or a11y — new/large images or fonts, bigger bundles, render-blocking resources, a new heavy component, or markup/contrast changes. Skip it for quick single-component checks so they stay fast.
- Lighthouse: run
mcp__chrome-devtools__lighthouse_audit(mode=navigation, device matching the viewport you're testing) on the primary changed page for accessibility / SEO / best-practices. Note: Lighthouse here EXCLUDES performance — use the trace below for Core Web Vitals. - Performance trace (optional): navigate to the target URL first, then
mcp__chrome-devtools__performance_start_trace— by default it reloads the page and auto-stops once the page settles, so no manual reload or separateperformance_stop_tracecall is needed (passreload=false/autoStop=falseonly if you want to drive an interaction yourself, then callmcp__chrome-devtools__performance_stop_trace). Thenmcp__chrome-devtools__performance_analyze_insightto read LCP / INP / CLS and render-blocking resources. - Keep it token-cheap: direct the heavy report to disk — set the tool's
outputDirPathto$REPO_ROOT/tmp/qa_screenshots/(runmkdir -p "$REPO_ROOT/tmp/qa_screenshots"first if you skipped the screenshot setup), or write to a tmp path. Pull only the scores + top failing audits into the QA report; never inline the raw JSON.
Step 7: Report Findings
Present a structured report:
## QA Report
### Summary
- [Area 1]: PASS / FAIL
- [Area 2]: PASS / FAIL
### Issues Found
1. **[Severity: HIGH/MEDIUM/LOW]** Description
- Steps to reproduce
- Expected behavior
- Actual behavior
- [Screenshot if available]
### Console Errors
- [List any JS errors found, or "None"]
### Network Errors
- [List any failed/4xx/5xx/CORS/hung requests — URL + status + linked UI defect, or "None"]
### Suggestions
- [Optional improvements noticed during testing]
If everything passes, say so clearly. If issues are found, prioritize them by severity.
Step 8: (Optional) Convert a Verified Journey to a Regression Test
Strictly opt-in. The QA pass itself stays read-only (detect + report) — this only runs if the user explicitly asks for it after seeing the report. Offer it once:
Want me to lock this in? I can turn a verified PASS journey (or a reproduced bug) into a runnable regression test so it can't silently come back.
If the user says yes:
- Pick the journey — a clean PASS path worth protecting, or the exact reproduction steps for a confirmed bug.
- Replay the steps through the active browser tool to confirm they're accurate.
- Emit a spec using the repo's existing e2e framework (
@playwright/testif none is established), written into the repo's existing tests directory — match the current layout and naming (e.g.e2e/,tests/e2e/,playwright/). - Run it and iterate until green. For a bug, write the test to fail against current behavior first, so it goes green only once the fix lands.
If the user declines, skip straight to Cleanup.
Step 9: Cleanup
Remove the screenshot directory after presenting the report:
rm -rf "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/tmp/qa_screenshots"
This command is read-only — the QA pass detects and reports issues but does NOT fix them. The single exception is Step 8, which writes a regression test only on explicit user approval (an opt-in follow-on, never part of the detection pass). The detailed issue list is returned to the parent caller (Claude Code), which should then use superpowers:writing-plans to build a fix plan from the findings, let the user iterate on it, and execute with /dcr verification.
Tip: Run
/jacked-setup qato generate a repo-specific config that skips browser detection, bakes in your tech stack, and adds framework-specific QA checks.