diff --git a/README.md b/README.md index 03d44f2..71a3f0a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ This plugin includes the following skills (see `skills/` for details): | [fetch](skills/fetch/SKILL.md) | Fetch HTML or JSON from static pages without a browser session — inspect status codes, headers, follow redirects | | [search](skills/search/SKILL.md) | Search the web and return structured results (titles, URLs, metadata) without a browser session | | [ui-test](skills/ui-test/SKILL.md) | AI-powered adversarial UI testing — analyzes git diffs to test changes, or explores the full app to find bugs | +| [ui-debugging](skills/ui-debugging/SKILL.md) | Fix user-reported UI bugs with exact browser checks — reproduce with a source-blind probe, patch, verify with a page-side check whose JSON failure feeds the next fix attempt | ## Installation diff --git a/skills/ui-debugging/LICENSE.txt b/skills/ui-debugging/LICENSE.txt new file mode 100644 index 0000000..f2f4397 --- /dev/null +++ b/skills/ui-debugging/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Browserbase, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/skills/ui-debugging/SKILL.md b/skills/ui-debugging/SKILL.md new file mode 100644 index 0000000..b28c8c3 --- /dev/null +++ b/skills/ui-debugging/SKILL.md @@ -0,0 +1,121 @@ +--- +name: ui-debugging +description: Debug and fix user-reported UI bugs using exact browser checks instead of repeated browsing. Use when a bug report describes user-visible misbehavior in a web app you have code access to - wrong state after a click, missing or overlapping elements, validation accepting bad input, stale async results, broken mobile layout, focus or accessibility failures. The workflow - reproduce in a browser with a source-blind probe, fix, then verify with an exact post-fix check whose JSON output names the failing element and the pass condition - measurably outperforms one-shot fixing (39% -> 67% fix rate on an 18-bug benchmark, with zero re-browsing during repair). +license: MIT +metadata: + author: browserbase + version: "0.1.0" +allowed-tools: Bash Read Edit Glob Grep +compatibility: "Works with any browser tool that can navigate and evaluate JS in the page (browse CLI, Stagehand/Playwright page.evaluate, chrome-devtools). Local apps: browse CLI local mode. Deployed/staging sites: browse --remote (Browserbase session)." +--- + +# UI Debugging — fix bugs with exact browser checks + +Fix UI bugs by treating the browser as a **diagnostic instrument, not an explorer**. The core finding from benchmarking this workflow: when a fix attempt fails, more browsing barely helps — a *sharper assertion* does. One precise DOM check that names the exact wrong element recovers bugs that narrative re-investigation cannot. + +## When to use + +A user-visible bug in a web app whose code you can edit: state bugs (counter goes down instead of up, draft lost on tab switch), validation bugs (bad input accepted), async bugs (stale results, spinner never clears), auth/visibility bugs (protected UI still shown), layout bugs (overflow, hidden menus, overlap), a11y bugs (focus not moving into a dialog, missing accessible names). + +For *finding* unknown bugs in changed UI, use the `ui-test` skill; this skill is for *fixing* a reported bug and proving the fix. + +## The loop + +``` +1. REPRODUCE browser probe, source-blind -> evidence +2. FIX smallest credible code change +3. CHECK exact check: passed / measurements -> if passed, done +4. FEED BACK the check's JSON (not prose!) into the next fix attempt -> goto 2 +``` + +With the `browse` CLI: + +```bash +browse open http://127.0.0.1:5173/route --wait networkidle +browse viewport 375 700 # only for mobile-width bugs +browse eval '' +``` + +For a deployed or staging site, add `--remote` to run in a Browserbase cloud session (you also get a session replay to attach to the bug report). Any tool with `page.evaluate` works the same way. + +### Step 1 — Reproduce with a source-blind probe + +Before reading any code, write a probe that follows the *user's* reproduction path using only what is visible on the page: query visible controls, set input values, dispatch events, click, wait, then return the before/after state. Do not let what you expect from the source bias what you measure. + +```js +(async () => { + const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); + // For React apps, set inputs via the native setter so state actually updates: + const setValue = (el, value) => { + Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set?.call(el, value); + el.dispatchEvent(new Event("input", { bubbles: true })); + }; + const before = document.querySelector("output")?.textContent; + [...document.querySelectorAll("button")].find((b) => b.textContent === "+")?.click(); + await sleep(100); + return { before, after: document.querySelector("output")?.textContent }; +})() +``` + +### Step 2 — Fix + +Read the code, make the smallest change that explains *all* of the probe evidence. Prefer 1–2 files. Don't refactor. + +### Step 3 — Write an exact check (the part that wins) + +Write the verification as a **check contract** — a page-side expression returning: + +```js +{ + passed: , // the assertion, computed in the page + ...measurements, // named evidence: elements, computed styles, rects, text + passCondition: "", + instructionToFixer: "" +} +``` + +Three rules make checks effective: + +1. **Name the exact element the assertion inspects.** Don't just assert "menu is visible" — return *which* element your selector matched, its `display`/`visibility`, its rect, and all other candidates. The classic failure: the selector matches a hidden desktop `