plugins/flow/skills/visual-verification/SKILL.md
Verify UI-facing changes by running a screenshot-analyze-verify loop across configured viewports, with a browser-tool priority cascade (Playwright MCP → Chrome DevTools MCP → CLI fallback → external skill fallback) and bounded iteration. Use after build/runtime verification passes and the diff includes `.tsx`/`.jsx`/`.vue`/`.html`/`.css`/`.scss`/`.svelte` files OR the acceptance criteria mention UI/page/render/display/visual. This skill MUST be consulted because UI changes that pass build and unit tests can still ship blank pages, render-blocking console errors, or broken responsive layouts that no other verification phase catches.
npx skillsauth add synaptiai/synapti-marketplace visual-verificationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You verify that UI-facing changes render correctly through a screenshot-analyze-verify loop. This skill was extracted from runtime-verification so the visual workflow has its own home; the two skills compose (runtime-verification handles build/server/smoke/E2E/LSP-diagnostics; visual-verification handles browser-rendered UI).
UI CHANGES MUST BE VISUALLY VERIFIED OR EXPLICITLY SKIPPED. A build that succeeds and a test suite that passes do not prove the page actually renders. Every UI-relevant change goes through this loop or surfaces a structured SKIP/BLOCKED result that the completion gate can reason about — never a silent skip.
The visualVerification.requireVisualVerification setting controls escalation behavior, not whether the loop runs. Even when requireVisualVerification: false, an unattempted UI change must produce SKIP_WARN with the reason — the completion gate emits the warning so the user knows visual verification was not attempted.
Visual verification activates when EITHER signal fires:
# Signal 1: UI file extensions in the diff
git diff --name-only HEAD~1..HEAD | grep -iE '\.(tsx|jsx|vue|html|css|scss|svelte)$'
# Signal 2: UI keywords in the acceptance criteria
# (The invoking command passes the criterion list as input; check for any of these tokens.)
# Tokens: UI, page, display, render, visual, layout, responsive, component, style
If neither signal fires → emit SKIP — no UI-relevant changes detected. and exit. This is a legitimate skip, distinct from SKIP_WARN.
Try these in order; use the first available:
browser_navigate, browser_take_screenshot, browser_console_logs) — full capability: navigation, screenshots, console logs, DOM inspectionnpx playwright screenshot http://localhost:$PORT/ $SCREENSHOT_DIR/page.pngSkill(compound-engineering:test-browser) — if the compound-engineering plugin is installedSkill(compound-engineering:agent-browser) — if the compound-engineering plugin is installedvisualVerification.requireVisualVerification (default: false → SKIP_WARN; explicit true → BLOCKED, command-level escalation needed)The skill does NOT silently install Playwright. Installation is a side effect with footprint; the user is asked via the command-level escalation path when the cascade falls all the way through.
Bounded by settings.json → visualVerification.maxIterations (default: 3). Iterate up to the cap when fixes are applied between rounds; halt earlier when verification passes.
For each page URL (dev server root + key pages from routes):
1. Navigate to page URL
2. Take screenshot → save to $SCREENSHOT_DIR/{page}-{viewport}-{timestamp}.png
3. Read screenshot with the Read tool (Claude analyzes visually)
4. Classify findings using the canonical schema in references/finding-schema.md (category=visual):
- Blank page → P1 (blocks completion)
- Render-blocking console errors → P1
- Layout breaks / broken grid → P2
- Missing content that should be visible → P2
- Minor styling issues → P3
5. If MCP tools are available: also fetch browser_console_logs and grep for JS errors / React warnings / CSP violations
6. Record screenshot path as evidence (referenced from the per-criterion evidence bundle)
Findings emit using the canonical two-column Finding | Suggested Fix table (see references/finding-schema.md): bold {ID} · {category} · {location}`` on the first line, problem prose after a <br>. Use the INT- prefix when invoked from integration-verifier, the VIS- prefix when invoked standalone. Location for visual findings is the URL path (e.g., http://localhost:3000/login instead of file:line) — the schema accepts non-file locations for renderer-surface findings.
For each viewport in settings.json → visualVerification.viewports, resize the browser and repeat the screenshot-analyze step:
http://localhost:3000/ @ mobile (375×812)Create the visual-verification task suite upfront and update status as the loop progresses:
# Setup — create all visual verification tasks upfront
TaskCreate("Visual verification", "Screenshot-analyze-verify for UI-facing changes")
TaskCreate("Browser tool discovery", "Detect available browser automation (Playwright MCP, Chrome DevTools, CLI)")
TaskCreate("Responsive check", "Verify UI across configured viewports (desktop, tablet, mobile)")
# Browser tool discovery
TaskUpdate(browserToolTaskId, status: "in_progress")
# ... detect tools ...
TaskUpdate(browserToolTaskId, status: "completed", result: "{tool} detected")
# If not applicable (no UI files, no UI criteria) — legitimate skip:
TaskUpdate(visualVerificationTaskId, status: "completed", result: "SKIP — no UI-relevant changes")
TaskUpdate(responsiveTaskId, status: "completed", result: "SKIP")
# If no browser tools found — check requireVisualVerification setting:
# requireVisualVerification: false (default) → SKIP_WARN
TaskUpdate(visualVerificationTaskId, status: "completed", result: "SKIP_WARN — no browser tools. Install Playwright MCP or use /flow:setup.")
TaskUpdate(responsiveTaskId, status: "completed", result: "SKIP_WARN — no browser tools")
# requireVisualVerification: true → BLOCKED (command-level escalation)
TaskUpdate(visualVerificationTaskId, status: "completed", result: "BLOCKED — requireVisualVerification is true but no browser tools available")
TaskUpdate(responsiveTaskId, status: "completed", result: "BLOCKED")
# Screenshot-analyze-verify loop (when tools ARE available)
TaskUpdate(visualVerificationTaskId, status: "in_progress")
# ... for each page: screenshot → analyze → record findings ...
TaskUpdate(visualVerificationTaskId, status: "completed", result: "PASS/FAIL — {pages} checked, P1:{n} P2:{n} P3:{n}")
# Responsive verification
TaskUpdate(responsiveTaskId, status: "in_progress")
# ... for each viewport: resize → screenshot → analyze ...
TaskUpdate(responsiveTaskId, status: "completed", result: "PASS/FAIL — {viewports} tested, findings: {summary}")
Use TaskList after all visual verification completes to confirm all sub-tasks resolved.
| Result | Meaning | Passes Completion Gate? |
|---|---|---|
| PASS | Ran and passed | Yes |
| FAIL | Ran and found P1 issues | No |
| SKIP | No UI files changed (legitimate) | Yes |
| SKIP_WARN | UI files changed, no tools, requireVisualVerification is false | Yes (with warning) |
| SKIP_USER_APPROVED | User explicitly chose to skip via command-level escalation | Yes |
| MANUAL | User committed to manual verification | Yes |
| BLOCKED | Awaiting user decision (requireVisualVerification is true, no browser tools) | No — requires command-level escalation per references/escalation-format.md |
### Visual Verification
| Check | Status | Details |
|---|---|---|
| Browser tools | {tool name or NONE} | Cascade result |
| Visual check | PASS/FAIL/SKIP/SKIP_WARN/SKIP_USER_APPROVED/MANUAL/BLOCKED | {pages checked, findings} |
| Responsive | PASS/FAIL/SKIP/SKIP_WARN/MANUAL | {viewports tested} |
| Console errors | PASS/FAIL/SKIP | {error count} |
### Visual Evidence
| Page | Viewport | Screenshot | Status | Findings |
|---|---|---|---|---|
### Visual Findings (canonical finding-schema)
#### P1 — Critical (Blocks Completion)
| Finding | Suggested Fix |
|---------|---------------|
#### P2 — Should Fix
| Finding | Suggested Fix |
|---------|---------------|
#### P3 — Consider
| Finding | Suggested Fix |
|---------|---------------|
Do NOT silently skip visual verification. Actively solve tooling problems:
| Problem | Action |
|---|---|
| No Playwright MCP | Try Chrome DevTools MCP |
| No Chrome DevTools MCP | Try npx playwright install chromium && npx playwright screenshot |
| No npx playwright | Try Skill(compound-engineering:test-browser) or Skill(compound-engineering:agent-browser) |
| No browser tools at all | If requireVisualVerification is true, return BLOCKED for command-level escalation per references/escalation-format.md. Otherwise, SKIP_WARN with tool installation guidance. |
| Dev server not running | Coordinate with runtime-verification skill — it owns dev-server lifecycle. Visual verification cannot run without a server URL. |
The browser-tool cascade includes two entries from the compound-engineering plugin (compound-engineering:test-browser, compound-engineering:agent-browser) as fallback positions 4 and 5. Decision: document, do not vendor. Rationale:
npx playwright screenshot) are all viable for the production loop; the external skills exist as additional fallbacks for environments where neither Playwright MCP nor a working npx setup is available.compound-engineering would fork the behavior — the upstream plugin may evolve its browser-tool surface, and a vendored copy would silently diverge. The flow plugin would inherit maintenance for code it did not author.compound-engineering plugin is part of the same Synapti marketplace and is recommended for installation alongside flow when visual verification is critical to the workflow. The cascade documentation makes the dependency relationship explicit so users in tooling-constrained environments can install it as a remediation step rather than discovering the absence at verification time.compound-engineering installed: visual verification works through positions 1-3 of the cascade (Playwright MCP, Chrome DevTools MCP, CLI fallback). Positions 4-5 are skipped silently.compound-engineering installed: positions 4-5 become available as fallbacks if positions 1-3 are unavailable.requireVisualVerification: true configured but no browser tools at all (none of positions 1-5 succeed): the skill returns BLOCKED, which the consumer escalates per references/escalation-format.md with three options (skip with note, manual verification by user, install browser tools).The README documents compound-engineering as a recommended companion plugin in the Hook Compatibility / Dependencies section.
runtime-verification is the parent verification skill — it owns build, dev server, smoke tests, E2E, LSP diagnostics, and acceptance-criteria verification. When the diff is UI-relevant, the consumer (commands/start.md Phase 4 step 8 / commands/pr.md Phase 4 step 4) invokes BOTH skills:
Skill(runtime-verification) for build + server + smoke + E2E + LSP diagnosticsSkill(visual-verification) for the browser-rendered UI loopThe two run in parallel when the dev server is up; if the dev server fails to start (a runtime-verification failure), visual-verification returns SKIP with the reason "dev server unavailable". The completion gate treats the dev-server failure as the primary finding.
tools
Validate a FlowWorkflow YAML at `plugins/flow/workflows/<id>.workflow.yaml` against `schemas/v1/workflow.schema.json` AND cross-reference the referenced skills/agents exist + every Tier 3 action is confirm-gated + no native /goal or /loop dependency is declared. Use when /flow:workflow validate is invoked, when CI runs the workflow schema gates, or when a new workflow is being authored. This skill MUST be consulted because schema validation alone catches shape errors; cross-reference validation catches the silent-correctness failures (typo'd skill name, Tier 3 escape, /goal dependency) that would otherwise ship to users.
data-ai
Coordinate agent teams for adversarial review (paired skeptic/verifier per facet, challenge round with disposition vocabulary, consolidated findings with confidence) or parallel implementation (task sizing 5-6 per teammate, non-overlapping files). Enforces independent analysis before shared conclusions. Reference only (`disable-model-invocation: true`); loaded only when `agentTeams: true` in settings.
development
Conduct two-stage code review: Stage 1 verifies spec compliance (criterion-to-code mapping), Stage 2 evaluates security, correctness, performance, and maintainability across 6 parallel facets with P1/P2/P3 synthesis and deduplication by file:line. Use when reviewing code changes or pull requests. This skill MUST be consulted because reviewing quality on broken logic is wasted effort, and unmet acceptance criteria must block merge.
development
Enforce FlowTrigger safety rules — no autonomous merge, no recursive trigger creation, max active triggers, allowed_actions / forbidden_actions ACLs. Validates trigger YAMLs at `.flow/triggers/*.trigger.yaml` against `schemas/v1/trigger.schema.json` AND cross-checks policy.forbidden_actions includes merge + release; refuses triggers that grant Tier 3 autonomy. Use when /flow:trigger create, /flow:trigger run, or /flow:watch is invoked. This skill MUST be consulted because triggers can fire without user supervision — a trigger granting merge autonomy is the single fastest path to an untrusted-merge incident, and recursive trigger creation is the loop-bomb shape of the runtime layer.