Skip to content

Add gstack browse and qa-only commands#13

Open
jmcoimbra wants to merge 1 commit intomainfrom
jmcoimbra/gstack-browse-qa-only
Open

Add gstack browse and qa-only commands#13
jmcoimbra wants to merge 1 commit intomainfrom
jmcoimbra/gstack-browse-qa-only

Conversation

@jmcoimbra
Copy link
Contributor

@jmcoimbra jmcoimbra commented Mar 18, 2026

Summary

  • Adds /qa:browse command: persistent headless Chromium for QA testing, screenshots, element assertions (~100ms per command)
  • Adds /qa:qa-only command: report-only QA testing with structured health scoring, diff-aware mode, and evidence collection
  • Source: garrytan/gstack - adapted for our plugin format (stripped gstack-specific preamble/contributor mode)

Context

Recommended by Zach in #rnd-engineering-leadership. These enable browser-based QA testing directly from Claude Code sessions.

Test plan

  • Verify /qa:browse setup detects gstack binary correctly
  • Test /qa:qa-only report generation on a staging URL
  • Confirm commands appear in plugin menu after install

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added comprehensive documentation for the headless browser QA command, including setup instructions, core QA patterns, and full command reference.
    • Added documentation for the report-only QA testing workflow, covering operational modes, testing phases, health score rubric, and output specifications.

Brings headless browser QA testing from garrytan/gstack into our QA plugins.
browse: persistent Chromium for page testing, screenshots, element assertions.
qa-only: structured report-only QA with health scoring and evidence collection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jmcoimbra jmcoimbra requested a review from a team March 18, 2026 21:34
@jmcoimbra jmcoimbra self-assigned this Mar 18, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

Two new documentation files are added for QA testing workflows. browse.md describes the headless browser QA command with usage patterns and command reference. qa-only.md defines a report-only QA testing workflow with phases, modes, and evaluation rubrics.

Changes

Cohort / File(s) Summary
QA Documentation
plugins/qa/commands/browse.md, plugins/qa/commands/qa-only.md
New documentation files covering headless browser QA command usage, testing workflows, QA patterns, command reference, operational modes, and health score rubrics for structured QA testing without code modifications.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 Whiskers twitch with testing glee,
Browse commands, now documented for all to see!
QA workflows dance from page to page,
Screenshots captured, each finding on stage—
No code to fix, just evidence to trace! 📸

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add gstack browse and qa-only commands' accurately and concisely describes the main change: adding documentation for two new QA commands to the plugin.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jmcoimbra/gstack-browse-qa-only
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/qa/commands/qa-only.md (1)

219-219: Consider using clearer multiplication notation.

The formula uses x for multiplication, which might be ambiguous. Consider using * or × for clarity:

-Final score: `score = sum(category_score x weight)`
+Final score: `score = sum(category_score * weight)`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/qa/commands/qa-only.md` at line 219, Replace the ambiguous
multiplication symbol in the final score formula: update the text "Final score:
`score = sum(category_score x weight)`" to use a clear multiplication operator
such as `*` or the proper multiplication sign `×` (e.g., `score =
sum(category_score * weight)`), ensuring the formula in the qa-only.md
documentation is unambiguous.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/qa/commands/browse.md`:
- Around line 1-253: The file browse.md uses descriptive headers (e.g., "##
SETUP", "## Core QA Patterns") and inline $B examples instead of the project's
step-based command file format; update browse.md to follow the "## Step 1, ##
Step 2" pattern used by other commands, convert major sections (Setup, Core QA
Patterns, Snapshot Flags, Full Command List, etc.) into numbered steps, and
replace inline usage of the $B shim with $ARGUMENTS placeholders for
user-provided inputs (URL, selector, file path, output path, flags) so commands
read from $ARGUMENTS rather than assuming $B is pre-set; ensure examples and
references (snapshot flags, ref usage like `@e/`@c, commands such as goto,
snapshot, screenshot, upload) show how to pass arguments via $ARGUMENTS and keep
guidance about the one-time setup prompt for the gstack browse build.

---

Nitpick comments:
In `@plugins/qa/commands/qa-only.md`:
- Line 219: Replace the ambiguous multiplication symbol in the final score
formula: update the text "Final score: `score = sum(category_score x weight)`"
to use a clear multiplication operator such as `*` or the proper multiplication
sign `×` (e.g., `score = sum(category_score * weight)`), ensuring the formula in
the qa-only.md documentation is unambiguous.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 903725f6-c1ca-4b18-a93b-e0654796b084

📥 Commits

Reviewing files that changed from the base of the PR and between 4d525f4 and 1dd4cbf.

📒 Files selected for processing (2)
  • plugins/qa/commands/browse.md
  • plugins/qa/commands/qa-only.md

Comment on lines +1 to +253
---
description: Fast headless browser for QA testing and site dogfooding. Navigate any URL, interact with elements, verify page state, take annotated screenshots, test forms, check responsive layouts, and assert element states. Requires gstack browse binary (~100ms per command). Use when asked to "open in browser", "test the site", "take a screenshot", or "dogfood this".
---

# browse: QA Testing & Dogfooding

Persistent headless Chromium. First call auto-starts (~3s), then ~100ms per command.
State persists between calls (cookies, tabs, login sessions).

## Prerequisites

This command requires the [gstack](https://github.com/garrytan/gstack) browse binary. If not installed, follow setup below.

## SETUP (run this check BEFORE any browse command)

```bash
_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
B=""
[ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse"
[ -z "$B" ] && B=~/.claude/skills/gstack/browse/dist/browse
if [ -x "$B" ]; then
echo "READY: $B"
else
echo "NEEDS_SETUP"
fi
```

If `NEEDS_SETUP`:
1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait.
2. Run: `cd ~/.claude/skills/gstack/browse && ./setup`
3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash`

---

## Core QA Patterns

### 1. Verify a page loads correctly

```bash
$B goto https://yourapp.com
$B text # content loads?
$B console # JS errors?
$B network # failed requests?
$B is visible ".main-content" # key elements present?
```

### 2. Test a user flow

```bash
$B goto https://app.com/login
$B snapshot -i # see all interactive elements
$B fill @e3 "user@test.com"
$B fill @e4 "password"
$B click @e5 # submit
$B snapshot -D # diff: what changed after submit?
$B is visible ".dashboard" # success state present?
```

### 3. Verify an action worked

```bash
$B snapshot # baseline
$B click @e3 # do something
$B snapshot -D # unified diff shows exactly what changed
```

### 4. Visual evidence for bug reports

```bash
$B snapshot -i -a -o /tmp/annotated.png # labeled screenshot
$B screenshot /tmp/bug.png # plain screenshot
$B console # error log
```

### 5. Find all clickable elements (including non-ARIA)

```bash
$B snapshot -C # finds divs with cursor:pointer, onclick, tabindex
$B click @c1 # interact with them
```

### 6. Assert element states

```bash
$B is visible ".modal"
$B is enabled "#submit-btn"
$B is disabled "#submit-btn"
$B is checked "#agree-checkbox"
$B is editable "#name-field"
$B is focused "#search-input"
$B js "document.body.textContent.includes('Success')"
```

### 7. Test responsive layouts

```bash
$B responsive /tmp/layout # mobile + tablet + desktop screenshots
$B viewport 375x812 # or set specific viewport
$B screenshot /tmp/mobile.png
```

### 8. Test file uploads

```bash
$B upload "#file-input" /path/to/file.pdf
$B is visible ".upload-success"
```

### 9. Test dialogs

```bash
$B dialog-accept "yes" # set up handler
$B click "#delete-button" # trigger dialog
$B dialog # see what appeared
$B snapshot -D # verify deletion happened
```

### 10. Compare environments

```bash
$B diff https://staging.app.com https://prod.app.com
```

### 11. Show screenshots to the user

After `$B screenshot`, `$B snapshot -a -o`, or `$B responsive`, always use the Read tool on the output PNG(s) so the user can see them. Without this, screenshots are invisible.

---

## Snapshot Flags

The snapshot is your primary tool for understanding and interacting with pages.

```
-i --interactive Interactive elements only (buttons, links, inputs) with @e refs
-c --compact Compact (no empty structural nodes)
-d <N> --depth Limit tree depth (0 = root only, default: unlimited)
-s <sel> --selector Scope to CSS selector
-D --diff Unified diff against previous snapshot (first call stores baseline)
-a --annotate Annotated screenshot with red overlay boxes and ref labels
-o <path> --output Output path for annotated screenshot (default: /tmp/browse-annotated.png)
-C --cursor-interactive Cursor-interactive elements (@c refs - divs with pointer, onclick)
```

All flags can be combined freely. `-o` only applies when `-a` is also used.
Example: `$B snapshot -i -a -C -o /tmp/annotated.png`

**Ref numbering:** @e refs are assigned sequentially (@e1, @e2, ...) in tree order.
@c refs from `-C` are numbered separately (@c1, @c2, ...).

After snapshot, use @refs as selectors in any command:

```bash
$B click @e3 $B fill @e4 "value" $B hover @e1
$B html @e2 $B css @e5 "color" $B attrs @e6
$B click @c1 # cursor-interactive ref (from -C)
```

Refs are invalidated on navigation. Run `snapshot` again after `goto`.

---

## Full Command List

### Navigation

| Command | Description |
|---------|-------------|
| `back` | History back |
| `forward` | History forward |
| `goto <url>` | Navigate to URL |
| `reload` | Reload page |
| `url` | Print current URL |

### Reading

| Command | Description |
|---------|-------------|
| `accessibility` | Full ARIA tree |
| `forms` | Form fields as JSON |
| `html [selector]` | innerHTML of selector or full page HTML |
| `links` | All links as "text -> href" |
| `text` | Cleaned page text |

### Interaction

| Command | Description |
|---------|-------------|
| `click <sel>` | Click element |
| `cookie <name>=<value>` | Set cookie on current page domain |
| `cookie-import <json>` | Import cookies from JSON file |
| `cookie-import-browser [browser] [--domain d]` | Import cookies from Chrome, Arc, Brave, or Edge |
| `dialog-accept [text]` | Auto-accept next alert/confirm/prompt |
| `dialog-dismiss` | Auto-dismiss next dialog |
| `fill <sel> <val>` | Fill input |
| `header <name>:<value>` | Set custom request header |
| `hover <sel>` | Hover element |
| `press <key>` | Press key (Enter, Tab, Escape, Arrow keys, etc.) |
| `scroll [sel]` | Scroll element into view or page bottom |
| `select <sel> <val>` | Select dropdown option |
| `type <text>` | Type into focused element |
| `upload <sel> <file> [file2...]` | Upload file(s) |
| `useragent <string>` | Set user agent |
| `viewport <WxH>` | Set viewport size |
| `wait <sel\|--networkidle\|--load>` | Wait for element, network idle, or page load |

### Inspection

| Command | Description |
|---------|-------------|
| `attrs <sel\|@ref>` | Element attributes as JSON |
| `console [--clear\|--errors]` | Console messages |
| `cookies` | All cookies as JSON |
| `css <sel> <prop>` | Computed CSS value |
| `dialog [--clear]` | Dialog messages |
| `eval <file>` | Run JavaScript from file |
| `is <prop> <sel>` | State check (visible/hidden/enabled/disabled/checked/editable/focused) |
| `js <expr>` | Run JavaScript expression |
| `network [--clear]` | Network requests |
| `perf` | Page load timings |
| `storage [set k v]` | Read/write localStorage + sessionStorage |

### Visual

| Command | Description |
|---------|-------------|
| `diff <url1> <url2>` | Text diff between pages |
| `pdf [path]` | Save as PDF |
| `responsive [prefix]` | Screenshots at mobile, tablet, desktop |
| `screenshot [--viewport] [--clip x,y,w,h] [selector\|@ref] [path]` | Save screenshot |

### Snapshot

| Command | Description |
|---------|-------------|
| `snapshot [flags]` | Accessibility tree with @e refs. See Snapshot Flags above |

### Tabs

| Command | Description |
|---------|-------------|
| `closetab [id]` | Close tab |
| `newtab [url]` | Open new tab |
| `tab <id>` | Switch to tab |
| `tabs` | List open tabs |

### Server

| Command | Description |
|---------|-------------|
| `restart` | Restart server |
| `status` | Health check |
| `stop` | Shutdown server |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check structure of existing command files to understand the expected format

# Find all command markdown files
echo "=== Existing command files ==="
fd -e md . plugins/*/commands/ --exec echo {}

echo -e "\n=== Checking for Step numbering pattern ==="
fd -e md . plugins/*/commands/ --exec rg -l '## Step [0-9]' {}

echo -e "\n=== Checking for ARGUMENTS usage ==="
fd -e md . plugins/*/commands/ --exec rg -l '\$ARGUMENTS' {}

echo -e "\n=== Sample frontmatter and first few headers from other command files ==="
fd -e md . plugins/*/commands/ -x bash -c 'echo "--- File: {} ---"; head -30 {} | grep -E "^(---|description:|## )"'

Repository: thanx/thanx-qa-claude-plugins

Length of output: 5846


Restructure browse.md to follow command file guidelines.

The coding guidelines require command files to use ## Step 1, ## Step 2 format and reference $ARGUMENTS for user input. This file currently uses descriptive headers (## SETUP, ## Core QA Patterns, etc.) with inline examples referencing $B instead.

12 of 14 command files in plugins/qa/commands/ follow the step-based format. Restructure browse.md to match: convert major sections into numbered steps, and reference $ARGUMENTS to accept user input (e.g., URL, selector, file path) instead of assuming $B is pre-set.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~181-~181: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... [selector]| innerHTML of selector or full page HTML | |links` | All links as "text -...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🪛 markdownlint-cli2 (0.21.0)

[warning] 227-227: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/qa/commands/browse.md` around lines 1 - 253, The file browse.md uses
descriptive headers (e.g., "## SETUP", "## Core QA Patterns") and inline $B
examples instead of the project's step-based command file format; update
browse.md to follow the "## Step 1, ## Step 2" pattern used by other commands,
convert major sections (Setup, Core QA Patterns, Snapshot Flags, Full Command
List, etc.) into numbered steps, and replace inline usage of the $B shim with
$ARGUMENTS placeholders for user-provided inputs (URL, selector, file path,
output path, flags) so commands read from $ARGUMENTS rather than assuming $B is
pre-set; ensure examples and references (snapshot flags, ref usage like `@e/`@c,
commands such as goto, snapshot, screenshot, upload) show how to pass arguments
via $ARGUMENTS and keep guidance about the one-time setup prompt for the gstack
browse build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant