/sg-visual-review — Interactive Screenshot Review
Generate and serve the ShipGuard dashboard to review visual test screenshots, code audit findings, logic contract/invariant findings, and process-check results, annotate problems, and export re-run / fix manifests.
Invocations
| Command | Behavior |
|---|---|
/sg-visual-review |
Build + start server + tell user to open the printed URL (default http://127.0.0.1:8888) |
/sg-visual-review --port=9000 |
Same, on a custom port |
Always: build the review page, start the HTTP server, and give the user the URL the server actually prints. Supported flags: --port=N (default 8888) and --host=H (default 127.0.0.1). To stop the server: /sg-visual-review-stop.
Prerequisites
/sg-visual-discoverhas been run (manifests exist invisual-tests/)/sg-visual-runhas been run at least once (screenshots +visual-results.jsonor legacyreport.mdexist invisual-tests/_results/)- No external npm dependencies — the build script uses a built-in YAML parser
Sandbox note: --serve, POST /save-manifest, and monitor smoke tests need loopback port access. See ../../docs/sandbox.md.
What It Does
Step 1: Build the Review Page
Run the build script:
node visual-tests/build-review.mjs --serve
This script:
- Reads all YAML test manifests from
visual-tests/ - Reads
visual-tests/_results/visual-results.jsonfor machine-readable status per test - Falls back to legacy
visual-tests/_results/report.mdif the JSON contract is missing or invalid - Reads
visual-tests/_regressions.yamlfor failure reasons - Matches screenshots from
visual-tests/_results/screenshots/ - Writes
visual-tests/_results/visual-results.jsonadditively: the producer owns that file, so a parseable document is kept as written — statuses (including a word this build does not know),failure_reason,summary,scope, results whose manifest is no longer on disk, and every additive per-test field of report-formats.md. The build only addsgenerated_atand a screenshot it found on disk for a test the producer left without one. With no producer document at all (a legacyreport.mdproject, or a suite that has never run) it synthesizes the contract from the manifests and the resolved statuses. An unparseable document is reported and left untouched - Reads
visual-tests/_results/logic-results.json(written by/sg-logic-audit) into the Logic tab, if present - Reads
visual-tests/_results/process-results.json(written by/sg-process-check) into the Process tab, if present - Generates a self-contained
visual-tests/_results/review.html(inline CSS + JS, no dependencies) - While
/sg-code-auditis running (oraudit-monitor.jsonexists in_results/), live agent progress renders inside the Code Audit tab — a progress bar in Overview and per-agent pods in the Agents sub-tab. There is no separate Monitor tab. - If change-report specs exist, generates persona-aware HTML reports under
visual-tests/_results/persona-reports/
--serve binds to 127.0.0.1 by default and refuses path traversal after decoding and resolving paths. Cross-origin POSTs to the server are rejected. LAN exposure requires an explicit host:
node visual-tests/build-review.mjs --serve --host=0.0.0.0
Change Reports & Client Validation
The change-report schema and workflow are owned by sg-change-report — see that skill for the report.json format and when to create one. This builder consumes:
visual-tests/_results/change-reports/<report-id>/report.json
visual-tests/_results/change-reports/<report-id>/screenshots/
and generates audience-specific decision pages (client, business, product, design, engineering, or custom) plus validation artifacts under:
visual-tests/_results/persona-reports/<report-id>/index.html
visual-tests/_results/persona-reports/<report-id>/<audience>.html
visual-tests/_results/persona-reports/<report-id>/client-invite-email.md
visual-tests/_results/persona-reports/<report-id>/client-response-email.md
visual-tests/_results/persona-reports/<report-id>/proposal-trace.md|.json
Each audience page includes before/after evidence, Accept / Adjust / Reject decisions, local comments, and JSON export; the email + trace files support manual validation without an email provider. Full example spec: skills/sg-visual-review/examples/change-report.json.
Commit the change-report source and the generated persona report with the UI change. Do not commit visual-tests/_results/review.html or visual-tests/_results/.server.pid; those are local generated files.
Step 2: Open in Browser
Open the URL printed by --serve (default http://127.0.0.1:8888):
open http://127.0.0.1:8888
# Or via agent-browser:
agent-browser open http://127.0.0.1:8888
The Code Audit tab, the live audit monitor, and the "Validate & Generate Report" button require the HTTP server. Opening review.html via file:// only shows the data embedded at build time (Logic, Visual Tests, Process, Recorded Tests) and cannot save fix manifests.
Step 3: Human Review
The review page provides:
Findings tab (unified, evidence-first — default when findings exist)
- Renders
visual-tests/_results/findings.json, a derived list the builder generates on every build: audit bugs, logic violations, process deltas, visual failures +browser_errors, crawler breakage (crawl-results.jsonfromshipguard crawl/run), and human annotations (fix-manifest.json) - Each finding:
SG-###id, severity (sorted first), an evidence badge —measured(a real observation),reasoned(a static/simulated prediction),manual(a human annotation) — source lane, and route/file location - The canonical per-lane schemas are untouched; findings.json is an additive projection
- Dynamic default tab: the dashboard opens on the first tab with data (findings → audit → logic → visual → process → recorded)
- Lane chips:
run.json(written bysg-ship/shipguard run) renders per-lane status chips (ran/skipped/not-applicable/error/needs-agent); a declared skipped lane shows its reason in place of a generic empty state - CLI equivalent:
node visual-tests/shipguard.mjs review [--serve]
Visual Tests tab
- All tests displayed as cards with screenshot thumbnails
- Color-coded badges: PASS (green), FAIL/ERROR (red), STALE (yellow), SKIPPED (muted)
- Priority badges (critical, high, medium, low)
- Sidebar with category filters
- Status filter bar (ALL / PASS / FAIL / ERROR / STALE / SKIPPED, only when present)
- Search by test name
Code Audit tab
- Shows bug cards from
audit-results.jsonif present in_results/ - Shows a completed zero-bug audit as
0 bugs found, not as missing data - Sub-tabs: Overview, Bugs, Routes, Agents
- Bug filters: severity buttons (All / Critical / High / Medium / Low, with counts), a route chip (click a row in the Routes sub-tab to filter bugs by route; click the chip to clear it), and free-text search over title, file, id, and category
- Live monitor: while an audit runs, the Overview shows a progress bar (agents done, bugs found so far) and the Agents sub-tab shows per-agent pods (status, bugs found, duration), fed by
audit-monitor.jsonand the/api/monitor/*endpoints
Logic tab
- Renders
visual-tests/_results/logic-results.jsonwritten by/sg-logic-audit - Shows contract/invariant violations with candidate, obligation, smallest counterexample, evidence, and severity
- Separately shows contract conflicts, questions, and uncovered paths so uncertainty is not presented as a bug
- Summary chips expose candidates, obligations, violations, risks, conflicts, coverage gaps, and reasoned/measured evidence
- Friendly empty or declared-skip state when the lane did not run
Process tab
- Renders
visual-tests/_results/process-results.jsonwritten by/sg-process-check(embedded at build time — rebuild after a new process check) - Summary chips (checks, behavior changes, new errors, surprises, reasoned vs measured evidence mix)
- Checks table: check name, before → after, verdict badge, reasoned/measured evidence tag, severity
- Impacted UI routes and impacted backend tables when present
- Friendly empty state when no process check has been run
Recorded Tests tab
- Cards for manifests captured with
/sg-recordfromvisual-tests/manifests/(step count, check count, recording date) - Select tests to get a ready-to-copy
sg-visual-run --manifests ...command
Lightbox
- Click any card to open full screenshot + test details
- Shows: test name, status, URL, description, steps to reproduce
- For FAIL tests: shows failure reason
Annotation Pen
- In lightbox, click "+ Add Note" (or double-click the screenshot) to annotate
- Click places a pin; drag draws a rectangle zone; each annotation gets a note + severity
- Annotations are stored per test and exported with re-run manifests
- Drawing an annotation auto-selects the test
Multi-Select + Re-run
- Click checkbox overlay on cards to select tests
- Floating action bar shows selection count
- "Re-run selected" → downloads JSON manifest with test IDs + annotations
- "Copy IDs" → copies test paths to clipboard
- Annotations are exported in the same normalized format as the fix manifest:
{
"action": "rerun",
"timestamp": "2026-04-09T...",
"tests": [
{
"test": "auth/login",
"annotations": [
{ "x1": 0.2, "y1": 0.3, "x2": 0.8, "y2": 0.6, "note": "Button overlaps footer", "severity": "high" }
]
}
]
}
Validate & Generate Report workflow
- Select one or more failed tests (checkbox overlay on cards)
- Optionally annotate each test with the pen tool to mark the problem area
- Click "Validate & Generate Report" in the floating action bar
- The page POSTs
fix-manifest.jsonto the server viaPOST /save-manifest(top-levelaction: "validate-and-fix"+timestamp; per-testredo_entirely/revert_to_before/improve_uibooleans; annotations as{x1,y1,x2,y2,note,severity}) - The saved manifest is then consumed by
/sg-visual-fixto implement fixes
Step 4: Re-run Failed/Annotated Tests
Take the exported JSON and feed it back:
/sg-visual-run <paste test IDs>
Or use the test paths directly:
/sg-visual-run auth/login dashboard/home settings/profile
Build Script Location
The build script and template are installed to the project:
| File | Purpose |
|---|---|
visual-tests/build-review.mjs |
Node.js build script |
visual-tests/_review-template.html |
HTML template with inline CSS + JS |
visual-tests/review-smoke-test.mjs |
Isolated smoke test for review build/server/save-manifest/persona reports |
visual-tests/monitor-smoke-test.mjs |
Isolated smoke test for audit monitor endpoints |
visual-tests/_results/review.html |
Generated local review workspace (not committed) |
visual-tests/_results/change-reports/<report-id>/report.json |
Durable source report (committed with UI changes) |
visual-tests/_results/persona-reports/<report-id>/index.html |
Durable generated review report (committed when used for PR/client review) |
visual-tests/_results/persona-reports/ |
Generated audience-specific reports |
Setup
If the build script is not yet in the project:
# Copy from the installed ShipGuard plugin root.
# Resolve SHIPGUARD_PLUGIN_ROOT from this skill path:
# $SHIPGUARD_PLUGIN_ROOT/skills/sg-visual-review/SKILL.md
cp "$SHIPGUARD_PLUGIN_ROOT/skills/sg-visual-review/build-review.mjs" visual-tests/
cp "$SHIPGUARD_PLUGIN_ROOT/skills/sg-visual-review/_review-template.html" visual-tests/
cp "$SHIPGUARD_PLUGIN_ROOT/skills/sg-visual-review/review-smoke-test.mjs" visual-tests/
cp "$SHIPGUARD_PLUGIN_ROOT/skills/sg-visual-review/monitor-smoke-test.mjs" visual-tests/
# Add npm script (optional)
# In package.json: "visual:review": "node visual-tests/build-review.mjs"
Smoke Tests
Run these after installing or changing the review dashboard files:
node visual-tests/review-smoke-test.mjs --port=23101
node visual-tests/monitor-smoke-test.mjs --port=23102
Both scripts use temporary fixtures. They should not write into the project except for normal process output.
Options:
--port=<port>uses a deterministic local port. The same value can be supplied withSHIPGUARD_REVIEW_SMOKE_PORT,SHIPGUARD_MONITOR_SMOKE_PORT, orSHIPGUARD_SMOKE_PORT.--keep-tmpkeeps the fixture directory for inspection after the run.--debugkeeps the fixture directory and prints server output on failure.
If a sandbox blocks local bind, the scripts fail with the fixture path, rerun command, server output tail, and a listen EPERM hint.
Design
- Dark theme (slate-900 bg, copper accents)
- Responsive grid (4 columns desktop, 1 column mobile)
- No external dependencies — a single self-contained HTML file. Server-backed features (Code Audit tab, live monitor, Validate & Generate Report) require
--serve;file://shows the build-time tabs only - Keyboard shortcuts: Escape to close lightbox/clear selection