ghost-qa 0.0.0-stage → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +273 -3
- package/SKILL.md +105 -0
- package/dist/bin/ghost-qa.d.ts +35 -0
- package/dist/bin/ghost-qa.d.ts.map +1 -0
- package/dist/bin/ghost-qa.js +406 -0
- package/dist/bin/ghost-qa.js.map +1 -0
- package/dist/src/engine/audit-runner.d.ts +10 -0
- package/dist/src/engine/audit-runner.d.ts.map +1 -0
- package/dist/src/engine/audit-runner.js +138 -0
- package/dist/src/engine/audit-runner.js.map +1 -0
- package/dist/src/engine/browser-session.d.ts +37 -0
- package/dist/src/engine/browser-session.d.ts.map +1 -0
- package/dist/src/engine/browser-session.js +114 -0
- package/dist/src/engine/browser-session.js.map +1 -0
- package/dist/src/engine/interaction-runner.d.ts +41 -0
- package/dist/src/engine/interaction-runner.d.ts.map +1 -0
- package/dist/src/engine/interaction-runner.js +274 -0
- package/dist/src/engine/interaction-runner.js.map +1 -0
- package/dist/src/engine/route-crawler.d.ts +31 -0
- package/dist/src/engine/route-crawler.d.ts.map +1 -0
- package/dist/src/engine/route-crawler.js +110 -0
- package/dist/src/engine/route-crawler.js.map +1 -0
- package/dist/src/engine/server-lifecycle.d.ts +41 -0
- package/dist/src/engine/server-lifecycle.d.ts.map +1 -0
- package/dist/src/engine/server-lifecycle.js +154 -0
- package/dist/src/engine/server-lifecycle.js.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +16 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/server.d.ts +111 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +267 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/reporter/agent-diagnostic.d.ts +17 -0
- package/dist/src/reporter/agent-diagnostic.d.ts.map +1 -0
- package/dist/src/reporter/agent-diagnostic.js +80 -0
- package/dist/src/reporter/agent-diagnostic.js.map +1 -0
- package/dist/src/reporter/html-report.d.ts +9 -0
- package/dist/src/reporter/html-report.d.ts.map +1 -0
- package/dist/src/reporter/html-report.js +142 -0
- package/dist/src/reporter/html-report.js.map +1 -0
- package/dist/src/reporter/terminal-summary.d.ts +5 -0
- package/dist/src/reporter/terminal-summary.d.ts.map +1 -0
- package/dist/src/reporter/terminal-summary.js +71 -0
- package/dist/src/reporter/terminal-summary.js.map +1 -0
- package/dist/src/traps/a11y-trap.d.ts +27 -0
- package/dist/src/traps/a11y-trap.d.ts.map +1 -0
- package/dist/src/traps/a11y-trap.js +173 -0
- package/dist/src/traps/a11y-trap.js.map +1 -0
- package/dist/src/traps/console-trap.d.ts +28 -0
- package/dist/src/traps/console-trap.d.ts.map +1 -0
- package/dist/src/traps/console-trap.js +151 -0
- package/dist/src/traps/console-trap.js.map +1 -0
- package/dist/src/traps/layout-trap.d.ts +31 -0
- package/dist/src/traps/layout-trap.d.ts.map +1 -0
- package/dist/src/traps/layout-trap.js +150 -0
- package/dist/src/traps/layout-trap.js.map +1 -0
- package/dist/src/traps/network-trap.d.ts +24 -0
- package/dist/src/traps/network-trap.d.ts.map +1 -0
- package/dist/src/traps/network-trap.js +132 -0
- package/dist/src/traps/network-trap.js.map +1 -0
- package/dist/src/traps/perf-trap.d.ts +42 -0
- package/dist/src/traps/perf-trap.d.ts.map +1 -0
- package/dist/src/traps/perf-trap.js +196 -0
- package/dist/src/traps/perf-trap.js.map +1 -0
- package/dist/src/types.d.ts +95 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +80 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +91 -6
- package/scripts/prepare-build.mjs +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VibeFoundry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,273 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# 👻 ghost-qa
|
|
2
|
+
|
|
3
|
+
**Autonomous headless browser QA & self-healing verification loop for coding agents.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/avivgerz-hue/ghost-qa/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/ghost-qa)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
[](https://playwright.dev)
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
Coding agents (Claude Code, Codex, Cursor, Windsurf) write code **blind** — then declare victory while the actual browser has React hydration errors, broken buttons, 500ing APIs, or mobile layout overflow.
|
|
14
|
+
|
|
15
|
+
`ghost-qa` fixes that. One command launches a headless browser against your running app, crawls the live DOM, safely pokes every button, traps runtime/network/layout failures, and hands the agent a structured **Self-Healing Bug Report** so it fixes its own bugs *before* telling you it's done.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx github:avivgerz-hue/ghost-qa test http://localhost:3000
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
No test scripts. No config. No mercy for "it works on my machine".
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## ⚡ Quickstart
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 1. Start your app as usual
|
|
29
|
+
npm run dev # → http://localhost:3000
|
|
30
|
+
|
|
31
|
+
# 2. Verify it in a real browser (one-time: downloads Chromium)
|
|
32
|
+
npx playwright install chromium
|
|
33
|
+
npx github:avivgerz-hue/ghost-qa test http://localhost:3000
|
|
34
|
+
|
|
35
|
+
# 3. Teach your coding agent to do this automatically, forever
|
|
36
|
+
npx github:avivgerz-hue/ghost-qa init
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`ghost-qa init` installs `.claude/skills/ghost-qa/SKILL.md` and appends the strict **"Verify in Browser Before Done"** protocol to `CLAUDE.md`, `AGENTS.md`, and `.cursorrules`. From then on, your agent runs ghost-qa itself, fixes what it finds, and only reports completion on a PASS.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 🔁 The Autonomous Self-Healing QA Loop
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
┌──────────────────────────────────────────┐
|
|
47
|
+
│ CODING AGENT │
|
|
48
|
+
│ Claude Code · Codex · Cursor · Windsurf │
|
|
49
|
+
└───┬──────────────────────────────▲───────┘
|
|
50
|
+
writes code │ │ Self-Healing
|
|
51
|
+
▼ │ Bug Report
|
|
52
|
+
┌───────────────┐ ┌─────────┴──────────┐
|
|
53
|
+
│ DEV SERVER │ │ AGENT DIAGNOSTIC │
|
|
54
|
+
│ localhost:3000 │ │ verdict · #ids · │
|
|
55
|
+
└───────┬───────┘ │ fix playbook │
|
|
56
|
+
│ serves live DOM └─────────▲──────────┘
|
|
57
|
+
▼ │ Markdown / JSON
|
|
58
|
+
┌────────────────────────────────────────┴──────────┐
|
|
59
|
+
│ 👻 ghost-qa │
|
|
60
|
+
│ │
|
|
61
|
+
│ Route Crawler ──► Interaction Runner │
|
|
62
|
+
│ │ │ │
|
|
63
|
+
│ ▼ ▼ │
|
|
64
|
+
│ ┌─────────┐ ┌──────────┐ ┌─────────┐ │
|
|
65
|
+
│ │ CONSOLE │ │ NETWORK │ │ LAYOUT │ │
|
|
66
|
+
│ │ A11Y │ │ PERF │ │ 5 TRAPS │ │
|
|
67
|
+
│ │ TRAP │ │ TRAP │ │ TRAP │ │
|
|
68
|
+
│ └─────────┘ └──────────┘ └─────────┘ │
|
|
69
|
+
│ Desktop 1440×900 + Mobile 390×844 (iPhone) │
|
|
70
|
+
└────────────────────────────────────────────────────┘
|
|
71
|
+
│
|
|
72
|
+
fix bugs ───────┘ re-run until ✔ PASS
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
1. The agent writes code and starts the dev server.
|
|
76
|
+
2. `ghost-qa test` crawls every internal route on **desktop + mobile**, exercising interactive controls.
|
|
77
|
+
3. Five traps capture everything the browser actually experienced.
|
|
78
|
+
4. Failures return as a token-efficient diagnostic; the agent fixes the root causes and re-runs.
|
|
79
|
+
5. The loop ends only at **PASS** — that's when the agent may tell you it's done.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 🪤 The 5-Trap Engine
|
|
84
|
+
|
|
85
|
+
### 1. Console Trap — `src/traps/console-trap.ts`
|
|
86
|
+
- Uncaught `pageerror` exceptions with stack traces
|
|
87
|
+
- Unhandled promise rejections
|
|
88
|
+
- **React hydration mismatches** ("Text content did not match", "A tree hydrated but…")
|
|
89
|
+
- `console.error` (major) and `console.warning` (minor) — with dev-server noise (`[vite]`, HMR, React DevTools banners) filtered out
|
|
90
|
+
|
|
91
|
+
### 2. Network Trap — `src/traps/network-trap.ts`
|
|
92
|
+
- HTTP `5xx` API crashes (critical) and `4xx` responses (major)
|
|
93
|
+
- Failed `fetch`/`XHR` requests and connection failures
|
|
94
|
+
- **CORS-blocked requests** with remediation guidance
|
|
95
|
+
- Broken static assets (JS/CSS/images/fonts) and missing favicons (minor)
|
|
96
|
+
|
|
97
|
+
### 3. Layout Trap — `src/traps/layout-trap.ts`
|
|
98
|
+
- **Horizontal overflow**: `scrollWidth > innerWidth`, with the offending elements named (critical on mobile)
|
|
99
|
+
- Zero-dimension interactive elements — buttons rendered at 0×0 that no human could tap
|
|
100
|
+
- Broken images (`naturalWidth === 0`)
|
|
101
|
+
- Missing `<meta name="viewport">` on mobile
|
|
102
|
+
|
|
103
|
+
### 4. Accessibility Trap — `src/traps/a11y-trap.ts` *(new in v1.1.0)*
|
|
104
|
+
- Buttons and links with **no accessible name** (icon-only controls screen readers can't identify)
|
|
105
|
+
- Images **missing `alt`** attributes (descriptive alt, or `alt=""` for decorative)
|
|
106
|
+
- Form inputs with **no associated label** — a placeholder is not a label
|
|
107
|
+
- Missing document `<title>` and missing `<html lang>`
|
|
108
|
+
|
|
109
|
+
### 5. Performance & Asset Trap — `src/traps/perf-trap.ts` *(new in v1.1.0)*
|
|
110
|
+
- Slow page loads via Navigation Timing (DOMContentLoaded / load budgets, 2× = critical)
|
|
111
|
+
- **Oversized resources** (> 1MB single asset) and excessive total payload (> 3MB)
|
|
112
|
+
- Main-thread jank / layout-thrashing indicators from the Long Tasks API
|
|
113
|
+
- Render-blocking `<head>` resources and excessive DOM size
|
|
114
|
+
|
|
115
|
+
Plus a **safety-first Interaction Runner**: it fills forms with inert data (`ghost-qa@example.com`), opens tabs/modals/menus, and clicks ordinary buttons — but *never* destructive ones (`delete`, `checkout`, `pay`, `logout`, `publish`… are blocked by a tested safety gate).
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 🔌 Native MCP Server *(new in v1.1.0)*
|
|
120
|
+
|
|
121
|
+
ghost-qa ships a zero-dependency **Model Context Protocol** server (JSON-RPC 2.0 over stdio), so MCP hosts can invoke browser verification as a native tool instead of shelling out:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npx github:avivgerz-hue/ghost-qa mcp
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| MCP tool | What it does |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `ghost_qa_audit_url` | Runs the full crawl + 5-trap suite against a running URL and returns the Self-Healing Bug Report (text + structured content) |
|
|
130
|
+
| `ghost_qa_doctor` | Verifies Node, Chromium availability, and runs a live browser smoke test |
|
|
131
|
+
|
|
132
|
+
`npx github:avivgerz-hue/ghost-qa init` writes the ready-to-use `.mcp.json` entry for you (merging with any servers you already have):
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{ "mcpServers": { "ghost-qa": { "command": "npx", "args": ["-y", "github:avivgerz-hue/ghost-qa", "mcp"] } } }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Works with Claude Code, Claude Desktop, Cursor, Codex — any MCP host.
|
|
139
|
+
|
|
140
|
+
**Docker / Glama:** the repo ships a production `Dockerfile` whose entrypoint is the MCP server (`node dist/bin/ghost-qa.js mcp`). Registry introspection (`initialize` + `tools/list` over stdio) answers instantly with no Chromium present — a browser is only launched when a tool is actually called:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
docker build -t ghost-qa .
|
|
144
|
+
docker run -i ghost-qa # MCP JSON-RPC over stdin/stdout
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 🖥️ Zero-lifecycle testing with `--server-cmd` *(new in v1.1.0)*
|
|
150
|
+
|
|
151
|
+
Don't even start the dev server yourself — ghost-qa will spawn it, wait for the URL to respond, audit, and terminate the whole process tree afterward:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npx github:avivgerz-hue/ghost-qa test http://localhost:3000 --server-cmd "npm run dev"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Pair it with `--html ghost-qa-report.html` for a self-contained, dark-mode **visual evidence dashboard** (routes, interactions, every trap finding per viewport) you can attach to CI artifacts or PRs.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 📟 Example output
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
👻 ghost-qa — autonomous browser verification
|
|
165
|
+
Target: http://localhost:3000/
|
|
166
|
+
Duration: 8.4s · Viewports: desktop + mobile · Depth: 2
|
|
167
|
+
|
|
168
|
+
Routes crawled
|
|
169
|
+
/ Home [200] 3 issues
|
|
170
|
+
/pricing Pricing [200] ✓
|
|
171
|
+
/dashboard Dashboard [200] 2 issues
|
|
172
|
+
|
|
173
|
+
Coverage
|
|
174
|
+
Routes visited: 3
|
|
175
|
+
Interactions tested: 21 passed · 1 failed · 4 skipped (safety)
|
|
176
|
+
Issues: 5 total — 2 critical, 3 major, 0 minor
|
|
177
|
+
|
|
178
|
+
Failures caught
|
|
179
|
+
✖ CRITICAL [console] React hydration mismatch: Text content did not match…
|
|
180
|
+
↳ / · desktop · #a91f03cc
|
|
181
|
+
✖ CRITICAL [network] Server error HTTP 500 for /api/users — backend/API is crashing on this route.
|
|
182
|
+
↳ /dashboard · mobile · #51bd77e0
|
|
183
|
+
▲ MAJOR [layout] Horizontal overflow on mobile: page scrolls sideways by 130px…
|
|
184
|
+
↳ / · mobile · #c04d19aa
|
|
185
|
+
|
|
186
|
+
✖ GHOST-QA FAIL — blocking browser failures found. Fix them and re-run before reporting done.
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The agent-facing report (`--report ghost-qa-report.md`) groups the same bugs by route with a per-category fix playbook and the exact re-run command.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🚀 CLI reference
|
|
194
|
+
|
|
195
|
+
| Command | Description |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| `ghost-qa test <url>` | Crawl a running app and trap browser failures. Exit `0` = PASS, `1` = blocking issues, `2` = runner error |
|
|
198
|
+
| `ghost-qa init [--force]` | Install `.claude/skills/ghost-qa/SKILL.md`, verification protocol (`CLAUDE.md`, `AGENTS.md`, `.cursorrules`) + MCP config (`.mcp.json`) — all idempotent |
|
|
199
|
+
| `ghost-qa mcp` | Run the native MCP server (JSON-RPC 2.0 over stdio) exposing `ghost_qa_audit_url` and `ghost_qa_doctor` |
|
|
200
|
+
| `ghost-qa doctor` | Diagnose Node ≥ 20, Playwright and Chromium setup, with a live browser smoke test |
|
|
201
|
+
| `ghost-qa --version` / `--help` | Version / usage |
|
|
202
|
+
|
|
203
|
+
### `test` flags
|
|
204
|
+
|
|
205
|
+
| Flag | Default | Description |
|
|
206
|
+
| --- | --- | --- |
|
|
207
|
+
| `--max-depth <n>` | `2` | Link-following depth from the start URL |
|
|
208
|
+
| `--max-routes <n>` | `25` | Maximum routes to visit |
|
|
209
|
+
| `--timeout <ms>` | `15000` | Per-navigation timeout |
|
|
210
|
+
| `--viewport <name>` | `both` | `both` \| `desktop` \| `mobile` |
|
|
211
|
+
| `--no-interactions` | off | Load pages only; don't click or fill anything |
|
|
212
|
+
| `--headed` | off | Show the browser window (debugging) |
|
|
213
|
+
| `--fail-on <severity>` | `major` | Exit 1 on `critical` \| `major` \| `minor` issues |
|
|
214
|
+
| `--json` | off | Print the full machine-readable JSON report to stdout |
|
|
215
|
+
| `--report <file>` | — | Write diagnostic to a file (Markdown, or JSON if the name ends `.json`) |
|
|
216
|
+
| `--html <file>` | — | Write the self-contained dark-mode HTML visual evidence dashboard |
|
|
217
|
+
| `--server-cmd <cmd>` | — | Spawn a dev server, wait for the URL, audit, then terminate the server tree |
|
|
218
|
+
| `--server-timeout <ms>` | `30000` | How long to wait for `--server-cmd` to start responding |
|
|
219
|
+
| `--quiet` | off | Suppress the terminal summary (report file + exit code only) |
|
|
220
|
+
|
|
221
|
+
Works with any stack that serves HTML on localhost — Next.js, Vite, Remix, Astro, Create React App, plain static servers, Rails, Django… if a browser can open it, ghost-qa can judge it.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 🤖 The Agent Skill
|
|
226
|
+
|
|
227
|
+
`SKILL.md` (repo root) is the master skill. `npx github:avivgerz-hue/ghost-qa init` installs it for:
|
|
228
|
+
|
|
229
|
+
- **Claude Code** → `.claude/skills/ghost-qa/SKILL.md` + protocol in `CLAUDE.md`
|
|
230
|
+
- **Codex / generic agents** → protocol in `AGENTS.md`
|
|
231
|
+
- **Cursor / Windsurf** → protocol in `.cursorrules`
|
|
232
|
+
|
|
233
|
+
The protocol is wrapped in `<!-- ghost-qa:start/end -->` markers, so re-running `init` updates it in place without duplicating or clobbering your other instructions.
|
|
234
|
+
|
|
235
|
+
## ⚖️ Scope & limitations (read this — we mean it)
|
|
236
|
+
|
|
237
|
+
ghost-qa is a **local development verification tool**, and we'd rather be honest than viral:
|
|
238
|
+
|
|
239
|
+
- **Not a WCAG audit.** The Accessibility Trap catches common machine-checkable failures (names, alt, labels, title, lang). Full WCAG conformance still needs assistive-technology testing.
|
|
240
|
+
- **Not a replacement for your test suite.** It complements unit/E2E tests by checking the *live* app the way a browser experiences it — it writes no persistent tests for you.
|
|
241
|
+
- **Heuristic safety.** The Interaction Runner refuses destructive-looking controls (delete, checkout, pay, logout…) and fills only inert data, but "destructive" is ultimately a word list. It is designed for localhost dev servers.
|
|
242
|
+
- **Auth-gated apps.** Without credentials, ghost-qa audits what an anonymous visitor sees (often the login page). Authenticated crawling is on the roadmap, not in the box today.
|
|
243
|
+
- **Performance numbers are local-machine heuristics.** Borderline perf findings on a loaded CI box deserve a re-run, not a panic.
|
|
244
|
+
- **Never point it at production systems or sites you don't own** or have explicit permission to test. It clicks real buttons.
|
|
245
|
+
- The MCP server is **stdio-only** (no network ports). Only wire it into MCP hosts you trust.
|
|
246
|
+
|
|
247
|
+
Found a trap flagging a healthy page? That's our most valuable issue type — [file it with the report attached](https://github.com/avivgerz-hue/ghost-qa/issues/new/choose). Security reports: see [SECURITY.md](./SECURITY.md). Release history: [CHANGELOG.md](./CHANGELOG.md).
|
|
248
|
+
|
|
249
|
+
## 🧑💻 Development
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
npm install
|
|
253
|
+
npx playwright install chromium
|
|
254
|
+
npm run build # tsc → dist/
|
|
255
|
+
npm test # Vitest: trap evaluators, crawler policy, safety gate, reporters
|
|
256
|
+
node dist/bin/ghost-qa.js doctor
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the "pure evaluator first" architecture rules.
|
|
260
|
+
|
|
261
|
+
## 📄 License
|
|
262
|
+
|
|
263
|
+
MIT © VibeFoundry — see [LICENSE](./LICENSE).
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Part of the VibeFoundry Agent Suite
|
|
268
|
+
|
|
269
|
+
| Tool | Description |
|
|
270
|
+
| --- | --- |
|
|
271
|
+
| 🎨 [unslop](https://github.com/avivgerz-hue/unslop) | Studio-grade UI design systems & Anti-Slop engine for coding agents. |
|
|
272
|
+
| 🛡️ [vibe-shield](https://github.com/avivgerz-hue/vibe-shield) | Automated security scanner & MCP guard for AI-generated codebases. |
|
|
273
|
+
| 👻 [ghost-qa](https://github.com/avivgerz-hue/ghost-qa) | Autonomous headless browser QA & self-healing verification loop. |
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ghost-qa
|
|
3
|
+
description: Verify frontend work in a real headless browser before reporting a task complete. Use after building or changing any UI, route, form, API integration, or client-side logic — crawls the running app on desktop and mobile, runs a 5-trap engine (console/hydration, network, layout, accessibility, performance), exercises interactive controls, and returns a self-healing bug report to fix from. Also usable via the ghost_qa_audit_url MCP tool.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 👻 ghost-qa — Verify in Browser Before Done
|
|
8
|
+
|
|
9
|
+
Coding agents write code blind. Code that type-checks can still ship with React hydration mismatches, uncaught exceptions, 500ing APIs, dead buttons, icon-only controls no screen reader can name, and mobile layouts that scroll sideways. **The browser is the source of truth — never your mental model of the DOM.**
|
|
10
|
+
|
|
11
|
+
## The Rule
|
|
12
|
+
|
|
13
|
+
> Before reporting ANY task that touches frontend code as complete, you MUST run the app in a real browser with ghost-qa, fix everything blocking it catches, and re-run until it passes.
|
|
14
|
+
|
|
15
|
+
Unit tests, type-checking, linting and code review do **not** satisfy this rule. They cannot see hydration, layout, network or accessibility failures.
|
|
16
|
+
|
|
17
|
+
## When to use this skill
|
|
18
|
+
|
|
19
|
+
- ✅ You created or changed pages, components, routes, forms, styles, or client-side data fetching
|
|
20
|
+
- ✅ You fixed a bug that manifested in the browser
|
|
21
|
+
- ✅ You are about to tell the user a UI task is "done"
|
|
22
|
+
|
|
23
|
+
**Not a substitute for:** your unit/E2E test suites, a full WCAG accessibility audit (ghost-qa's a11y trap covers common machine-checkable failures, not full WCAG conformance), load testing, or manual exploratory QA.
|
|
24
|
+
|
|
25
|
+
## Choose your path
|
|
26
|
+
|
|
27
|
+
| Situation | Command |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| Dev server already running | `npx github:avivgerz-hue/ghost-qa test <url>` |
|
|
30
|
+
| Server not running (most common) | `npx github:avivgerz-hue/ghost-qa test <url> --server-cmd "npm run dev"` — ghost-qa spawns it, waits for it, audits, and kills the process tree afterward |
|
|
31
|
+
| Your host exposes MCP tools | Call **`ghost_qa_audit_url`** with the URL (call `ghost_qa_doctor` first if it errors) — identical engine, identical report |
|
|
32
|
+
| Mobile-only bug hunt | add `--viewport mobile` |
|
|
33
|
+
| Large app | add `--max-depth 3 --max-routes 50` |
|
|
34
|
+
| Evidence for a PR/CI | add `--report ghost-qa-report.md --html ghost-qa-report.html` |
|
|
35
|
+
|
|
36
|
+
Common local URLs: Next.js / CRA `http://localhost:3000`, Vite `http://localhost:5173`, Astro `http://localhost:4321`, Angular `http://localhost:4200`. If unsure, check the dev server output or `package.json` scripts — never guess silently; state the URL you verified in your completion message.
|
|
37
|
+
|
|
38
|
+
## The Self-Healing Loop
|
|
39
|
+
|
|
40
|
+
1. **Run the audit** (path table above). The 5-Trap Engine checks, on Desktop 1440×900 *and* Mobile 390×844:
|
|
41
|
+
- **Console** — uncaught errors, unhandled promise rejections, React hydration mismatches, `console.error`
|
|
42
|
+
- **Network** — HTTP 4xx/5xx, failed fetch/XHR, CORS failures, broken assets
|
|
43
|
+
- **Layout** — horizontal overflow, zero-size interactive elements, broken images, missing viewport meta
|
|
44
|
+
- **Accessibility** — buttons/links with no accessible name, images missing `alt`, inputs with no label, missing `<title>` / `<html lang>`
|
|
45
|
+
- **Performance** — slow loads, oversized assets/payloads, main-thread long-task jank, render-blocking resources, excessive DOM
|
|
46
|
+
2. **Read the Self-Healing Bug Report.** Every issue has a stable `#id`, a severity (`critical` / `major` / `minor`), the route, and the viewport. Fix **critical and major** issues. Note minors; fix them when cheap.
|
|
47
|
+
3. **Fix root causes in source** (fix guidance below). Reference issues by `#id` in your own narration so the user can follow along.
|
|
48
|
+
4. **Re-run the identical command.** A fix that breaks a different route or viewport only shows up on re-run.
|
|
49
|
+
5. **Repeat until `GHOST-QA PASS`.** If you have looped 5 times on the same `#id`, stop and report to the user what is stuck and why — do not silently give up or declare success.
|
|
50
|
+
6. **Only then** report completion, using the completion template below.
|
|
51
|
+
|
|
52
|
+
## Fix guidance per trap
|
|
53
|
+
|
|
54
|
+
| Trap | Typical root causes | Fix like this |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| Hydration mismatch | `Date.now()`/`Math.random()`/`window` during render, server/client branching, invalid HTML nesting (`<p>` in `<p>`, `<div>` in `<p>`) | Make server and client render identical markup; move time/random/client-only values into `useEffect` + state; fix the nesting |
|
|
57
|
+
| Uncaught page error | undefined data, missing null checks on async data, bad imports | Reproduce via the stack trace in the report; guard the actual data path |
|
|
58
|
+
| Console error | failed state updates, rejected promises, React warnings treated seriously by the app | Trace the first error, not the cascade after it |
|
|
59
|
+
| HTTP 5xx | API route crash, bad env var, DB down | Read the server logs for that endpoint; the browser found it, the fix is server-side |
|
|
60
|
+
| HTTP 404 / broken asset | wrong path, case-sensitivity, asset not emitted by the build | Compare the URL in the report with the actual build output / public dir |
|
|
61
|
+
| CORS failure | API missing `Access-Control-Allow-Origin` for the page origin | Fix the API's CORS config (or the dev proxy), not the fetch call |
|
|
62
|
+
| Horizontal overflow | `100vw` + scrollbar, fixed-width children, flex/grid children without `min-width: 0` | Constrain widths (`max-width: 100%`, `min-width: 0`, `overflow-wrap`); the report names the offending elements |
|
|
63
|
+
| Zero-size interactive | collapsed CSS, `display: contents` misuse, content that never rendered | Restore a real, tappable size (≥ 24px, ideally ≥ 40px on mobile) |
|
|
64
|
+
| No accessible name | icon-only `<button>`/`<a>` | Add visible text or `aria-label` describing the action/destination |
|
|
65
|
+
| Missing `alt` | forgotten attribute | Descriptive alt; `alt=""` only if purely decorative |
|
|
66
|
+
| Input without label | placeholder used as label | Real `<label for>`, wrapping `<label>`, or `aria-label` |
|
|
67
|
+
| Slow load / oversized asset | unoptimized images, giant bundles, blocking scripts | Compress/lazy-load, `defer`/`async`, code-split; check the named resource first |
|
|
68
|
+
| Long-task jank | heavy sync JS, layout reads in loops after writes | Break up work, memoize, batch DOM reads before writes |
|
|
69
|
+
|
|
70
|
+
## Anti-cheating rules (this is the point of the skill)
|
|
71
|
+
|
|
72
|
+
- ❌ Never silence the checker: no deleting the failing UI, no blanket `try/catch`, no `suppressHydrationWarning`, no removing the code path "so the error goes away"
|
|
73
|
+
- ❌ Never use `--no-interactions` or narrow `--viewport`/`--max-depth` to hide failures (legitimate only when a page has side-effectful controls, and you must say so)
|
|
74
|
+
- ❌ Never edit ghost-qa's report, thresholds, or your project's ghost-qa invocation to manufacture a PASS
|
|
75
|
+
- ✅ If a finding is a genuine false positive, say so explicitly in your completion message with the `#id` and why — a human can overrule the tool; you may not quietly ignore it
|
|
76
|
+
|
|
77
|
+
## Safety guarantees you can rely on
|
|
78
|
+
|
|
79
|
+
ghost-qa never clicks destructive controls (delete, checkout, pay, logout, publish, sign-in…), never submits real orders/payments, fills forms only with inert data (`ghost-qa@example.com`, `ghost-qa test`), stays on same-origin links, and is designed for localhost/dev servers. **Do not point it at production systems you do not own or have permission to test.** Pages behind authentication will typically redirect to a login page — ghost-qa will audit what an anonymous visitor sees; say so if that's what happened.
|
|
80
|
+
|
|
81
|
+
## Troubleshooting
|
|
82
|
+
|
|
83
|
+
| Symptom | Do this |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| "could not launch Chromium" | `npx playwright install chromium` (one-time), then `npx github:avivgerz-hue/ghost-qa doctor` |
|
|
86
|
+
| `navigation-failed` on every route | Server isn't on that URL/port — start it, or re-run with `--server-cmd "npm run dev"` |
|
|
87
|
+
| Everything 404s | Wrong port or base path — confirm the URL in a browser/`curl` yourself first |
|
|
88
|
+
| Audit seems to test a login page | The app requires auth for those routes; report that limitation instead of claiming full verification |
|
|
89
|
+
| Perf findings vary between runs | Machine load affects timings; re-run once before treating a borderline perf major as real |
|
|
90
|
+
| MCP tool unavailable | Fall back to the CLI — the audit engine and report are identical |
|
|
91
|
+
|
|
92
|
+
## Completion template
|
|
93
|
+
|
|
94
|
+
When the final run passes, report completion like this:
|
|
95
|
+
|
|
96
|
+
> ✅ Done. Verified in a real browser with ghost-qa: `npx github:avivgerz-hue/ghost-qa test <url>` → **GHOST-QA PASS**
|
|
97
|
+
> Routes crawled: N · Interactions tested: N · Issues fixed this session: (list `#id`s, or "none found")
|
|
98
|
+
> Stack: desktop 1440×900 + mobile 390×844, 5 traps (console, network, layout, accessibility, performance)
|
|
99
|
+
|
|
100
|
+
## Completion checklist
|
|
101
|
+
|
|
102
|
+
- [ ] Final code state audited (not an earlier draft of the change)
|
|
103
|
+
- [ ] All critical/major issues fixed at the root cause, or explicitly reported as false positives with reasoning
|
|
104
|
+
- [ ] Final run prints `GHOST-QA PASS`
|
|
105
|
+
- [ ] Completion message uses the template above and names the URL verified
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type GhostQAOptions } from '../src/types.js';
|
|
3
|
+
export declare const VERSION = "1.3.0";
|
|
4
|
+
export declare const AGENT_PROTOCOL = "<!-- ghost-qa:start -->\n## \uD83D\uDC7B ghost-qa \u2014 Browser Verification Protocol (MANDATORY)\n\nBefore reporting any task that touches frontend code as complete, you MUST verify it in a real browser:\n\n1. Ensure the app is running locally (e.g. `npm run dev`).\n2. Run: `npx github:avivgerz-hue/ghost-qa test <local-url>` (e.g. `npx github:avivgerz-hue/ghost-qa test http://localhost:3000`) \u2014 or call the `ghost_qa_audit_url` MCP tool if your host exposes it. Add `--server-cmd \"npm run dev\"` to let ghost-qa manage the dev server itself.\n3. If ghost-qa reports ANY critical or major issue (hydration errors, console errors, 4xx/5xx responses, mobile overflow, accessibility or performance failures, broken interactions), fix the root cause in source and re-run.\n4. Repeat until ghost-qa prints **PASS**. Only then may you tell the user the task is done.\n\nNever declare a UI task finished based only on code review, type-checking, or unit tests. The browser is the source of truth.\n<!-- ghost-qa:end -->";
|
|
5
|
+
export interface ParsedTestArgs {
|
|
6
|
+
target: string;
|
|
7
|
+
options: GhostQAOptions;
|
|
8
|
+
json: boolean;
|
|
9
|
+
quiet: boolean;
|
|
10
|
+
reportFile?: string;
|
|
11
|
+
htmlFile?: string;
|
|
12
|
+
serverCmd?: string;
|
|
13
|
+
serverTimeoutMs: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function parseTestArgs(args: string[]): ParsedTestArgs;
|
|
16
|
+
export declare function installSkill(targetDir: string, force?: boolean): Promise<Array<{
|
|
17
|
+
file: string;
|
|
18
|
+
action: string;
|
|
19
|
+
}>>;
|
|
20
|
+
/**
|
|
21
|
+
* Writes (or merges into) `.mcp.json`, preserving any MCP servers the
|
|
22
|
+
* project already configured. The ghost-qa entry is always refreshed so
|
|
23
|
+
* hosts invoke the published CLI: `npx -y github:avivgerz-hue/ghost-qa mcp`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function installMcpConfig(mcpJsonPath: string, force?: boolean): Promise<string>;
|
|
26
|
+
export declare function main(argv?: string[]): Promise<number>;
|
|
27
|
+
/**
|
|
28
|
+
* True when this module is the process entry point. The entry path MUST be
|
|
29
|
+
* realpath-resolved first: package managers invoke bins through a
|
|
30
|
+
* `node_modules/.bin/ghost-qa` symlink, while `import.meta.url` always
|
|
31
|
+
* points at the real file — comparing unresolved paths would make the CLI
|
|
32
|
+
* silently no-op (exit 0, no output) under `npx`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isMainEntry(argvEntry: string | undefined, moduleUrl?: string): boolean;
|
|
35
|
+
//# sourceMappingURL=ghost-qa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ghost-qa.d.ts","sourceRoot":"","sources":["../../bin/ghost-qa.ts"],"names":[],"mappings":";AAWA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEvE,eAAO,MAAM,OAAO,UAAmB,CAAC;AAKxC,eAAO,MAAM,cAAc,mgCAWX,CAAC;AAyEjB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,CA+E5D;AAyDD,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,KAAK,UAAQ,GACZ,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAqBlD;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,KAAK,UAAQ,GACZ,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAuCD,wBAAsB,IAAI,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoDxE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,SAAS,GAAE,MAAwB,GAClC,OAAO,CAOT"}
|