{
  "markdown": "<p align=\"center\"><img src=\"logo.png\" width=\"120\" alt=\"logo\" /></p>\n\n# browser-qa\n\nBrowser QA on any website - dev, staging, or prod - for anyone.\n\nGive it a URL and a one-line prompt, and browser-qa explores the site, generates test\nscenario cases, drives a real browser through them, detects side effects the flow\nitself would never assert (console errors, JS exceptions, failed requests, unexpected\ndialogs/popups/tabs), and writes a report a non-developer can read - in your language.\n\nTwo ways to use it:\n\n- **As a Claude Code skill** - the agent reads `SKILL.md`, explores with\n  agent-browser, writes scenario YAMLs, runs them deterministically, and triages the\n  findings for you.\n- **As a standalone app** - a Textual TUI plus CLI. Record a scenario by clicking\n  through the site in a real browser, then run, schedule, and automate it. No code.\n\n## Why\n\n- QA after every feature: a developer finishes a backend/frontend change, you run the\n  site's saved cases (`superqa run --all --site myshop`) and get a regression verdict\n  with evidence in minutes.\n- Non-developers own the tests: recording is literally clicking through the site while\n  a floating browser-qa panel captures each step with a human-readable description.\n- Side effects are first-class: every run watches the whole browser context - including\n  popups - so a 500 on an API, an uncaught exception, or an unexpected new tab shows up\n  even when every asserted step passed. Duplicates are counted, known noise is split\n  out via per-site ignore rules.\n- Every run auto-compares against the previous run of the same scenario: new failures\n  and newly appeared side-effect types are flagged as regressions; identical runs get\n  a clean \"no regression\" verdict.\n- Visual regression built in: accept a trusted run as baseline (`superqa baseline`),\n  and later runs pixel-diff every step screenshot, flagging layout changes with a\n  red-overlay diff image. Failing runs also save a Playwright `trace.zip` replay.\n- Reviewable user-story DAGs: each new case stores stable IDs, user stories, visible\n  acceptance criteria, and prerequisites in YAML. `superqa dag check` validates the\n  graph, and the local Admin draws branches and joins without exposing browser mechanics,\n  values, or secrets.\n- CI-ready: `--junit results.xml` renders runs as native test results in\n  Jenkins/GitHub Actions; `superqa doctor` checks the environment in plain language.\n\n## Install\n\n```bash\ngit clone https://github.com/cskwork/browser-qa ~/.claude/skills/browser-qa\ncd ~/.claude/skills/browser-qa\npip3 install textual playwright pyyaml && python3 -m playwright install chromium\n# optional: pip3 install -e .   ->  gives you the `superqa` command\n```\n\nRequirements: Python 3.10+, Chromium via Playwright (installed above).\n\n## Quick start (no code)\n\n```bash\nsuperqa serve                        # web admin: click Run on any scenario\nbash scripts/superqa.sh              # or the terminal TUI\n```\n\nThe **web admin** (`superqa serve` -> http://127.0.0.1:8760) is the most clickable\nsurface: every scenario - recorded or agent-authored - with a reviewable dependency\nDAG, a Run button, live progress, run history, and inline reports. It shares the\nTUI/CLI data.\n\n- `n` - record: a Chrome window opens with a browser-qa panel (bottom-right). Click\n  through the site; every click/input becomes a step. Passwords are stored as\n  `{{password}}` placeholders, never plain text. Press \"저장 후 종료\" to save.\n- `r` - run the selected scenario and watch the browser replay it.\n- `a` - run everything (regression sweep). `u` - one-button smoke QA for any URL.\n- `s` - schedule a scenario every N minutes. `v` - manage accounts/variables.\n- `o` - open the latest HTML report.\n\n## Quick start (CLI / CI)\n\n```bash\nsuperqa record https://myshop.example.com --site myshop --name 로그인-정상\nsuperqa vars set myshop username myid\nsuperqa vars set myshop password s3cret          # auto-masked in reports\nsuperqa dag check --all --site myshop             # validate YAML DAGs before replay\nsuperqa run --all --site myshop --headless        # exit code 0 = green\nsuperqa auto https://myshop.example.com           # smoke QA, zero setup\nsuperqa schedule add 로그인-정상 --every 30 && superqa schedule daemon\n\n# same cases against another target (local stack, staging) - nothing is persisted\nsuperqa run --all --site myshop --headless --var base_url=http://localhost:3000\n```\n\n## Running against a local stack\n\n`--var KEY=VALUE` retargets a run without rewriting the stored variables, so one scenario\nset covers shared environments and a copy of the stack running on your machine. Testing\nagainst local services and a local data subset is the way to cover destructive cases and\nfirst-time-user states that shared environments cannot hold -\n[`reference/local-offline.md`](reference/local-offline.md) has the procedure, including how\nto derive fixtures from the local database and how to prove a case can actually fail.\n\n## What a run produces\n\n`~/.superqa/reports/<stamp>-<scenario>/`:\n\n- `report.html` - pass/fail badges, step table with inline screenshots, side-effect\n  table. Self-contained; send it to anyone.\n- `report.md` - the same, paste-ready.\n- `step-NN.png` - screenshot after every step.\n\nReport language follows the scenario's `language:` field (Korean and English built in).\n\n## Scenario format\n\nPlain YAML that non-developers can read and edit - see\n[reference/scenario-format.md](reference/scenario-format.md):\n\n```yaml\nname: 로그인-정상\nsite: myshop\nlanguage: ko\npolicy: { dialogs: accept, popups: follow }\ndag:\n  nodes:\n    - id: arrive-login\n      story: \"방문자로서 서비스의 로그인 시작점에 도착할 수 있다.\"\n      depends_on: []\n      acceptance: [\"로그인 입력 화면이 표시된다.\"]\n    - id: prepare-login\n      story: \"등록 회원은 자신의 로그인 정보를 준비할 수 있다.\"\n      depends_on: [arrive-login]\n      acceptance: [\"아이디와 비밀번호를 입력할 수 있다.\"]\n    - id: reach-account\n      story: \"회원으로서 내 계정에 접근하기 위해 로그인할 수 있다.\"\n      depends_on: [prepare-login]\n      acceptance: [\"환영 문구와 계정 영역이 표시된다.\"]\n```\n\nThe checked YAML contains no `action`, `selector`, or input value. The recorder/QA agent\nkeeps the detailed browser binding locally under `~/.superqa/runtimes/`; one story can\ntherefore replay several browser operations without becoming several review nodes. Nodes\nexecute serially in stable topological order (YAML declaration order breaks ties), while\nthe DAG makes their branches and joins reviewable. Existing `steps:` files remain readable\nwithout a rewrite; use `superqa dag migrate` only when you want to convert one.\n\n## Domain QA packs\n\nRepeat QA on the same product should not start from zero. A **pack**\n(`~/.superqa/packs/<domain>/` by default; location is asked once and stored in\n`~/.superqa/config.yaml`) keeps the domain's feature map (`pack.md`), per-feature\nnotes, and **archived reusable scripts** - the data-discovery SQL, probes, and\nharnesses that would otherwise die in ticket folders. Saying \"QA \\<domain\\>\n\\<feature\\>\" loads the pack and runs what already exists; only gaps get explored.\nSee [reference/domain-packs.md](reference/domain-packs.md).\n\nInteractive exploration picks the engine by what the case needs, then falls back to\nthe cascade. The default is **agent-browser**: it follows popups and new windows,\nrecords API requests with their **response bodies**, and ships native binaries for\nmacOS, Linux and Windows. When the target needs the user's own logged-in session,\ntake ego-browser on macOS; after that Playwright MCP, `playwright-cli`, and\nchrome-devtools-mcp for deep network work ([reference/engines.md](reference/engines.md)).\n\nOne engine per page: chrome-devtools-mcp only records traffic it navigated itself, so\ndriving with another engine and inspecting here yields an empty network log. lightpanda\nis not used - no renderer means no screenshots, and popups never open.\n\nDeterministic replay and reports always come from the browser-qa engine.\n\n## Site data stays local\n\nEverything site-specific lives under `~/.superqa/` - never in this repo:\n\n```\n~/.superqa/\n├── superqa.db               # accounts/vars (SQLite; secret keys masked in reports)\n├── config.yaml              # pack home + exploration engine choice\n├── scenarios/<site>/*.yaml  # your test cases\n├── runtimes/<site>/*.yaml   # local browser bindings; never the review artifact\n├── reports/                 # run evidence\n├── packs/<domain>/          # feature map + archived reusable QA scripts\n└── sites/<site>/rules.md    # per-site playbook the agent maintains\n```\n\n## Architecture\n\n```\nSKILL.md + reference/        agent lane: explore -> generate cases -> run -> triage\nsuperqa_tui/\n├── engine.py                Playwright driver: replay, record, auto-smoke,\n│                            side-effect collectors (context-wide, incl. popups)\n├── recorder_overlay.js      injected shadow-DOM panel: record / assert / save\n├── scenario.py  store.py    YAML DAG/legacy models; SQLite vars + run history\n├── report.py    i18n.py     md/html reports, ko/en strings, secret masking\n├── visual.py    junit.py    screenshot baselines; JUnit XML for CI\n├── diff.py      scheduler.py run-to-run diff; interval schedules\n├── admin.py                 web admin server (stdlib http, DAG review + click-to-run)\n├── app.py                   Textual TUI\n└── cli.py                   headless CLI (CI-friendly exit codes)\n```\n\n## Tests\n\n```bash\npython3 tests/test_engine_smoke.py   # replay + record + auto QA on local fixtures\npython3 tests/test_tui_smoke.py      # Textual pilot smoke\npython3 tests/test_dag.py            # DAG validation, migration, execution semantics\npython3 tests/test_admin.py          # Admin graph rendering + one real replay\n```\n\nVerified against live sites: full pipeline (scenarios, dialogs, multi-tab popup\nchains, login via stored vars) ran 3 consecutive green rounds on two independent\nsites, and the side-effect collector surfaced a real uncaught JS exception on one\nof them.\n\n## License\n\nMIT\n",
  "bytes": 9900,
  "sha": "383d4a0df0ab5751782511344c002f6777cba82fd7eadb8aa7a9d1e3ab25b541",
  "repo_slug": "cskwork/browser-qa",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_cskwork_browser_qa_747922ae/readme"
}