jthorare

design-verify-web

Playwright screenshots at mobile/tablet/desktop viewports, diff against mockup baseline using design-comparison MCP, and report discrepancies with fix suggestions.

jthorare 1 3 Updated 3w ago
GitHub

Install

npx skillscat add jthorare/agentic-workflow/design-verify-web

Install via the SkillsCat registry.

SKILL.md

Before anything else: read $HOME/.agentic-workflow/toolkit/skills/_preamble.md and follow it (skill index, provider capability map, bootstrap check, session context). Run its Session Close section when this skill finishes.

Design context: read $HOME/.agentic-workflow/toolkit/skills/_design-preamble.md and follow it before continuing.


Design Verify Web — Playwright Screenshot Diff vs Mockup

Captures screenshots of the live implementation at each screen's route, compares against the per-screen, per-viewport mockup baselines, and reports region-level discrepancies. Artifact paths and the comparison-report.json schema come from _shared/design-artifact-paths.md.

Step 1: Load screens.json and Baselines

SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
source "$SHARED_DIR/repo-slug.sh"
cat "$AW_DIR/design/screens.json" 2>/dev/null || echo "NO_SCREENS_JSON"
ls "$AW_DIR/design/"mockup-web-*.png 2>/dev/null
ls "$AW_DIR/design/"mockup-*.png 2>/dev/null | grep -v -e 'mockup-web-' -e 'mockup-ios' || true

Read $SHARED_DIR/design-artifact-paths.md for the screens.json (CD4) schema and baseline naming (CD3).

  • Screens to verify: the [screen-name] argument if given, else every screen in screens.json with "source": "design-mockup-web".
  • Baselines: mockup-web-<screen>-<viewport>.png per the screen's baselines map.
  • Viewports: read from screens.json viewports (canonical: mobile 375×812, tablet 768×1024, desktop 1440×900) — do not hardcode a different set.
  • Legacy baselines: a bare mockup-<screen>.png (second ls line) may be used only for a single desktop-viewport compare, with the warning: "legacy baseline — re-run /design-mockup to upgrade".

If a requested screen has no entry and no baseline, or no baselines exist at all, stop:

"No mockup baseline for <screen>. Run /design-mockup-web <screen> first."

Staleness check — warn (do not stop) when either holds:

  • the screen's baseline_stale in screens.json is non-null → "baselines predate a design-token update (design-evolve) — re-run /design-mockup-web"
  • mockup-<screen>.html is newer than its baseline PNGs: ls -t "$AW_DIR/design/mockup-<screen>.html" "$AW_DIR/design/mockup-web-<screen>-desktop.png" 2>/dev/null | head -1 lists the HTML first → "baseline older than the latest mockup HTML — re-run /design-mockup-web"

Step 2: Resolve Route per Screen — Fail Loudly

For each screen, the capture URL is <base-url><route> where route is, in order:

  1. the --route <path> argument (applies only when a single [screen-name] is being verified)
  2. screens.json → .screens.<screen>.route

If neither yields a route, fail loudly — never default to /:

"No route known for screen <screen> — verifying the root URL would diff the wrong page and produce a false verdict. Re-run /design-mockup-web <screen> (which records the route) or pass --route <path>."

Mark that screen FAIL in the report with reason route unknown.

Base URL: detect the dev server from package.json scripts (typically http://localhost:3000). If it is not reachable at capture time, release the lock and stop: "Dev server not running — start it and re-run."

Step 3: Create the Run Directory

SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
source "$SHARED_DIR/repo-slug.sh"
RUN_ID="$(date -u +%Y%m%d-%H%M%S)-<screen-or-all>"
mkdir -p "$AW_DIR/design/verify/$RUN_ID"
echo "run-dir: $AW_DIR/design/verify/$RUN_ID"

All captures, diff images, and the report for this run live under design/verify/<run-id>/ — previous runs are never overwritten.

Step 4: Acquire Browser Lock

Single bash invocation (shell state does not persist between Bash calls); note skill-lock.sh enables set -euo pipefail:

SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
LOCK_NAME=browser source "$SHARED_DIR/skill-lock.sh"; acquire_lock

If acquire_lock reports TIMEOUT: "Another browser session is in progress. Wait or remove ~/.agentic-workflow/.browser.lock if stale." Every failure branch after this point must, in one invocation, re-source (LOCK_NAME=browser source "$SHARED_DIR/skill-lock.sh") and call release_lock before stopping. Use return, not exit, after sourcing.

Step 5: Capture and Diff — per Screen × Viewport

Run these calls inline (no Agent delegation). For each screen, for each viewport:

  1. mcp: playwright/browser_navigate — url: <base-url><route>
  2. mcp: playwright/browser_resize — width/height for the viewport
  3. mcp: playwright/browser_wait_for — wait for the page's main content to settle
  4. mcp: playwright/browser_snapshot — confirm the expected screen actually rendered (headings/landmarks match the screen). If the wrong page rendered (redirect, 404, auth wall), mark this screen FAIL with the evidence — do not diff the wrong page.
  5. mcp: playwright/browser_console_messages — record errors as report context
  6. mcp: playwright/browser_take_screenshot — save to $AW_DIR/design/verify/$RUN_ID/<screen>-<viewport>.png
  7. mcp: design-comparison/compare_design — reference: $AW_DIR/design/mockup-web-<screen>-<viewport>.png, implementation: the capture from call 6. Record the response's numeric diff-percentage field as diff_pct and save the returned diff image to $AW_DIR/design/verify/$RUN_ID/<screen>-<viewport>-diff.png.
  8. (optional, only when attributing a deviation to a token) mcp: playwright/browser_evaluate — sample getComputedStyle on the deviating element to name the actual vs expected token value
  9. mcp: playwright/browser_close — once, after the last screen×viewport

Per-cell verdict from diff_pct (CD11): ≤2% PASS · 2–10% WARN · >10% FAIL.

Step 6: Write comparison-report.json

Write $AW_DIR/design/verify/$RUN_ID/comparison-report.json per the schema in $SHARED_DIR/design-artifact-paths.md:

{ "schema": "comparison-report/v1", "run_id": "<run-id>",
  "screens": [ { "screen": "...", "viewport": "...", "baseline": "...", "capture": "...",
                 "diff_image": "...", "diff_pct": 0.0, "verdict": "PASS|WARN|FAIL" } ],
  "overall": { "max_diff_pct": 0.0, "verdict": "PASS|WARN|FAIL" } }

overall.verdict = worst cell verdict; overall.max_diff_pct = max diff_pct. Screens failed for route unknown or wrong-page render get diff_pct: 100, verdict: "FAIL", and the reason recorded in place of the diff image path.

Step 7: Report Results

Report honesty (region-level only): a pixel diff can say where pixels differ ("header area differs by N%"), never why. Token-level attribution ("border-radius 4px instead of token 8px") is allowed only when backed by a Step 5.8 mcp: playwright/browser_evaluate computed-style sample; otherwise it is forbidden.

[<PASS|WARN|FAIL>] Design Verification — <screen(s)>
=====================================================
Overall:  <verdict>  (max diff <N>% · thresholds: ≤2% PASS / ≤10% WARN / >10% FAIL)

| screen | viewport | diff % | verdict | deviating regions |
|--------|----------|--------|---------|-------------------|

Console errors: <count or none>
Token attributions (computed-style verified only): <list or "none">
Artifacts: ~/.agentic-workflow/<repo-slug>/design/verify/<run-id>/

For WARN/FAIL cells, describe the deviating regions and point at the diff image; suggest /design-refine then /design-verify-web again.

Step 8: Release Browser Lock

Always — success or failure:

SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
LOCK_NAME=browser source "$SHARED_DIR/skill-lock.sh"; release_lock

Rules

  • Capture every configured viewport for every verified screen — no skipping
  • Never diff a capture whose route or rendered content was not confirmed
  • Region-level findings only, unless computed-style verified (Step 7)
  • Do not modify any code — this skill is read-only verification
  • If the dev server is not running, release the lock, advise the user to start it, and stop

Next steps

Gate on overall.verdict — a FAIL run blocks the /shipRelease suggestion:

  • PASS — /shipRelease — diff is clean, ship the release
  • WARN — /design-refine — address minor discrepancies, then /design-verify-web again
  • FAIL — /design-refine or /design-implement-web — significant deviation; re-verify before any ship step