vision-verify — the visual gate

SkillWeb & browsing

Visually verify a rendered web page against a goal + rubric — screenshot it (reliable off-box render, NOT the flaky Chrome-MCP), then grade the pixels with an INDEPENDENT vision pass. Use for any UI/visual change before calling it done, or to confirm a fix landed on a live/preview page. Catches what verify-build + code review can't SEE: contrast, overlap, broken images, layout shift, duplicated elements.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the vision-verify — the visual gate skill

What this skill tells your AI

The instructions your AI receives, as published by seldonframe/seldonframe in .claude/skills/vision-verify/SKILL.md and read by ahel’s review.

verify-build proves a change compiles and passes tests. It cannot prove the page looks right — code review reasons about JSX/CSS, it never sees the result. This skill closes that gap: render → screenshot → an independent visual grade against a rubric. It is the visual complement to verify-build, not a replacement — run both for UI-affecting work.

Proven 2026-07-05: caught a duplicate "Services" nav item on a live r1 site that unit tests, tsc, next build, AND two code reviews all missed — then confirmed the fix by re-screenshot. First bug on SF caught by seeing, not reasoning about code.

When to use

  • After ANY UI-affecting change, before "done" — especially landing/site render (hero, nav, sections), the dashboard shell, or anything themed.
  • To confirm a fix visually landed on a live/preview URL (the found → fix → confirm loop).

Steps

  1. Get a public URL to the page — a deployed /w/<slug>, the <slug>.app.seldonframe.com subdomain, or a Vercel preview URL. It must be publicly reachable (the renderer fetches it). If you just pushed a fix, first confirm the deploy is live: curl -s https://app.seldonframe.com/api/version → the sha should be your commit (else wait for the deploy).

  2. Render (from packages/crm), at desktop and — for anything responsive — mobile:

    node scripts/vision-shot.mjs <url> /tmp/vv-desktop.png 1280
    node scripts/vision-shot.mjs <url> /tmp/vv-mobile.png 390
    

    It cache-busts so a just-deployed change is captured fresh. Prints the saved path. (Set MICROLINK_API_KEY for higher rate limits; the free endpoint works without it, but can rate-limit on rapid retries — space them out.)

  3. Grade — independent (maker ≠ checker), on haiku — PINNED. Dispatch the vision-grader agent (Agent tool, subagent_type: "vision-grader" — its definition in .claude/agents/vision-grader.md pins model: haiku; do NOT pass a model override) — it Reads the PNG and grades it against the goal + a rubric, returning { pass: boolean, gaps: string[] }. Read-a-PNG→verdict is haiku work; a real session ran 4 graders on sonnet (~218k tokens — the session's biggest line item) purely because the model was left to dispatch-time habit. The pin lives in the agent definition so it can't drift. (If haiku ever provably misses what sonnet catches — run 10 known-good + 10 known-bad screenshots — change the pin there, on evidence, not per-dispatch.) Do NOT let the code's author grade its own pixels — a fresh grader sees only the artifact + the rubric, with no stake in the maker's reasoning. For a quick self-check inline, Read the PNG yourself — but a real gate uses a separate grader. Prefer a before/after DIFF grade when a baseline exists: hand the grader both screenshots and ask "what changed — is the change the requested one, and did anything regress?" A visual diff is more sensitive to regressions (the duplicate-nav class) and less subjective than an absolute grade.

  4. Act. Pass → done. Gaps → feed each gap back to the maker → re-render → re-grade until pass or a hard iteration cap (an objective stop, like /goal).

Rubric (adapt per surface)

Generic: renders with no broken images / empty sections; text is legible (contrast); nothing overlaps or overflows the viewport (no horizontal scroll); no duplicated nav/section elements; the specific change requested is visibly present; nothing is truncated mid-word in a jarring way.

Per-surface hints:

  • Hero: headline hierarchy clear; subhead + CTAs legible; any lead-form-in-hero renders; a set background sits BEHIND text with a legibility veil (never washing out the copy).
  • Nav: exactly one of each item (the duplicate-"Services" class of bug); wordmark + phone/CTA present.
  • Pricing / tables: columns aligned; numbers tabular; no clipped cells.
  • Dashboard shell: no sideways scroll; the summary reads before the detail.

Notes

  • The Chrome-MCP screenshot path is unreliable here (CDP clip.scale + backgrounded-tab 0-viewport) — use vision-shot.mjs.
  • Product version (next build): the same render+grade engine, server-side, becomes SeldonChat's "confirm the edit looks right before I say done" and a gate in the site-generation pipeline — the never-lies pillar made mechanical. Spec: docs/superpowers/specs/2026-07-05-vision-verify-spike.md.

Signals

GitHub stars
47
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
vision-verify
Source
github.com/seldonframe/seldonframe