一键导入
manually-validate-fix
Validate a bug-fix PR by reproducing the bug in production and confirming the fix locally, using browser automation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Validate a bug-fix PR by reproducing the bug in production and confirming the fix locally, using browser automation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | manually-validate-fix |
| description | Validate a bug-fix PR by reproducing the bug in production and confirming the fix locally, using browser automation. |
| disable-model-invocation | true |
| argument-hint | <pr-number> |
Validate a bug-fix PR by testing like a human — reproduce the bug in production (broken), confirm the fix works locally (working). Uses a single Selenium WebDriver script run against both environments.
PR → UNDERSTAND BUG → PLAN REPRODUCTION → WRITE SCRIPT → RUN vs PRODUCTION (bug)
→ RUN vs LOCAL (fix)
→ VERDICT → label PR
| Environment | URL | Runs | Expected |
|---|---|---|---|
| Production | https://basecamp.github.io/lexxy/try-it.html | Latest released version (CDN) | Bug reproduces |
| Local | http://lexxy.localhost:3000 | Current branch with the fix | Bug does NOT reproduce |
The try-it page loads Lexxy from jsDelivr CDN. After JS executes:
<lexxy-editor> with toolbar, emoji prompt on : triggerdata-direct-upload-url and data-blob-url-template are set but uploads go to a service worker (no real backend)http://lexxy.localhost:3000 runs the Rails dummy app:
/sandbox) — editor with @ mention and : emoji prompts, template switcher/posts) — full Action Text form, all features/posts/new control features: ?attachments_disabled=true, ?toolbar_disabled=true, etc.gh pr view $ARGUMENTS --json title,body,files,commits,headRefName
gh pr diff $ARGUMENTS
Extract:
If the PR references an issue, fetch that too.
Write a concrete step-by-step plan:
The plan must map directly to WebDriver actions.
ls /tmp/node_modules/selenium-webdriver >/dev/null 2>&1 || {
cd /tmp && npm install selenium-webdriver
}
which chromedriver >/dev/null 2>&1 || echo "ERROR: Install chromedriver"
Write a single .mjs script in /tmp/ that accepts a URL argument and runs the reproduction steps. The same script runs against both environments — only the URL changes.
Script skeleton:
import webdriver from '/tmp/node_modules/selenium-webdriver/index.js'
import chrome from '/tmp/node_modules/selenium-webdriver/chrome.js'
import { Key } from '/tmp/node_modules/selenium-webdriver/lib/input.js'
import fs from 'fs'
const BASE_URL = process.argv[2]
if (!BASE_URL) {
console.error('Usage: node script.mjs <url>')
process.exit(1)
}
const ENV = BASE_URL.includes('github.io') ? 'production' : 'local'
async function sleep(ms) { return new Promise(r => setTimeout(r, ms)) }
async function screenshot(driver, name) {
const data = await driver.takeScreenshot()
fs.writeFileSync(`/tmp/validation-${ENV}-${name}.png`, Buffer.from(data, 'base64'))
console.log(`Screenshot: /tmp/validation-${ENV}-${name}.png`)
}
const options = new chrome.Options()
options.addArguments('--headless=new', '--no-sandbox', '--window-size=1280,900')
const driver = await new webdriver.Builder()
.forBrowser('chrome').setChromeOptions(options).build()
try {
// Navigate and wait for editor
await driver.get(BASE_URL)
await driver.wait(
webdriver.until.elementLocated(webdriver.By.css('lexxy-editor[connected]')),
15000
)
const content = await driver.findElement(webdriver.By.css('.lexxy-editor__content'))
await content.click()
await sleep(300)
// ===== REPRODUCTION STEPS HERE =====
// Use real browser interactions:
// content.sendKeys('text') — type text
// content.sendKeys(Key.RETURN) — press Enter
// content.sendKeys(Key.BACK_SPACE) — press Backspace
// content.click() — click to focus
// driver.findElement(...).click() — click toolbar buttons
// driver.executeScript(...) — read DOM state (not for actions)
// ===== COLLECT EVIDENCE =====
await screenshot(driver, 'result')
const html = await driver.executeScript(
'return document.querySelector("lexxy-editor").value'
)
console.log(`[${ENV}] Editor value:`, html)
// ===== ASSERT =====
// Check whether the bug manifests or not.
// Print a clear PASS/FAIL line:
// PASS = behavior is correct (expected for local)
// FAIL = bug manifests (expected for production)
// Example:
// const bugPresent = html.includes('<some-broken-markup>')
// console.log(`[${ENV}] Bug present: ${bugPresent}`)
} finally {
await driver.quit()
}
Key rules for the script:
sendKeys, click). No programmatic shortcuts.executeScript is for reading state only — never for producing the action under test.curl -s -o /dev/null -w "%{http_code}" http://lexxy.localhost:3000/ 2>/dev/null | grep -q 200 || {
echo "Starting local server..."
cd ~/Work/basecamp/lexxy && bin/dev &
for i in $(seq 1 30); do
curl -s -o /dev/null -w "%{http_code}" http://lexxy.localhost:3000/ 2>/dev/null | grep -q 200 && break
sleep 1
done
}
Verify the right branch is checked out:
cd ~/Work/basecamp/lexxy && git branch --show-current
# Must match the PR's head branch
# Production — expect the bug
node /tmp/validate-fix-<pr>.mjs "https://basecamp.github.io/lexxy/try-it.html"
# Local — expect the fix
node /tmp/validate-fix-<pr>.mjs "http://lexxy.localhost:3000"
Review screenshots and console output from both runs.
| Production | Local | Verdict |
|---|---|---|
| Bug reproduces | Bug does NOT reproduce | Validated |
| Bug reproduces | Bug STILL reproduces | Not Fixed |
| Bug does NOT reproduce | N/A | Cannot Validate |
Verdict format:
**Validation Verdict: [Validated / Not Fixed / Cannot Validate]**
**PR:** #<number> — <title>
**Bug:** <one-line description>
**Production** (https://basecamp.github.io/lexxy/try-it.html):
- <what happened>
- Evidence: <screenshot paths>
**Local** (http://lexxy.localhost:3000):
- <what happened>
- Evidence: <screenshot paths>
**Steps executed:**
1. <step> — <result>
2. ...
If Validated:
gh pr edit <number> --add-label "fix-validated" -R basecamp/lexxy
gh pr comment <number> --body "$(cat <<'EOF'
## Manual Validation: Validated
<Brief description of what was tested — written for a human reviewer. Describe the steps you performed and what you observed, e.g. "Typed a bulleted list, selected all items, applied heading format from the toolbar. Confirmed the list converted to a heading without leaving orphaned list markers.">
EOF
)"
If Not Fixed — comment on the PR:
gh pr comment <number> --body "$(cat <<'EOF'
## Manual Validation: Not Fixed
<Same human-readable description of the steps tested and what was observed, explaining why validation failed.>
EOF
)"
Bug reproduction for the Lexxy rich text editor. Core editing bugs use Playwright (Selenium fallback); system-level bugs use Capybara. All local.
Process multiple bugs from a Fizzy board (or GitHub issues) in parallel. Uses worktree agents to reproduce, fix, test, create PRs, and comment on cards.