Skip to content
Back to skills

Visual Verification

ASecurity

Use for any UI/web project — make the verify gate cover more than unit tests by composing a pipeline (types → unit → design-scan → flow-smoke) and running the built-in yoke flow-smoke gate (landmark + zero console errors + screenshot proof to .yoke/proof/<story>/, video kept on failure). Catches the unwired-page / runtime-crash / AI-slop bugs unit tests miss.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 5, 2026
ai-agentsrustgo

Works with

  • cli
  • mcp

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 5, 2026

npx -y skills add HECer/yoke --skill visual-verification --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Visual Verification?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Visual Verification
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hecer-visual-verification/badge)](https://www.skillsdirectory.com/skills/hecer-visual-verification)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: visual-verification
description: Use for any UI/web project — make the verify gate cover more than unit tests by composing a pipeline (types → unit → design-scan → flow-smoke) and running the built-in yoke flow-smoke gate (landmark + zero console errors + screenshot proof to .yoke/proof/<story>/, video kept on failure). Catches the unwired-page / runtime-crash / AI-slop bugs unit tests miss.
---

# Visual verification

Unit tests don't see a blank page, an unwired route, a runtime console error, or AI-slop design.
Make the loop's gate catch them by widening `verify`, since the loop trusts verify as truth.

## 1. Compose the verify pipeline

Set `verify.command` (in `.yoke/config.yaml`) to chain, fail-fast:

```
<typecheck> && <unit tests> && yoke design-scan . && yoke flow-smoke .
```
e.g. `tsc --noEmit && vitest run && yoke design-scan . && yoke flow-smoke .`. Any red step blocks the story.

## 2. Flow-smoke with the built-in gate

Configure the key user flows once in `.yoke/config.yaml`:

```yaml
smoke:
  baseUrl: http://localhost:3000
  sourceIdentity:
    path: /assets/app-specific-static-source.js
    sha256: "<replace with SHA-256 of the served bytes>"
  flows:
    - name: home
      path: /
      landmark: "main h1"
    - name: login
      path: /login
      landmark: "form"
```

The example contains a required hash placeholder. Before running production smoke, replace
the resource path with a stable, app-specific source resource and the hash with its actual
64-character lowercase SHA-256. The schema allows the field to be absent for existing
configuration readers; production `flow-smoke` requires it.

Start the intended server and confirm its checkout/build and port. Fetch the resource from
the effective `baseUrl` origin, using the exact body bytes returned by the server. Hash those
bytes, not a local source file that a dev server may transform. The resource must return a
successful HTTP response without redirects, finish within five seconds and contain at most
1 MiB. Keep it stable for the whole smoke run. When `--url` changes the origin, verify that
origin serves the intended build before deriving the pin.

Refresh the expected hash explicitly after an intentional source/build change and after
confirming the server serves that change. A mismatch must fail the gate; do not automatically
overwrite the expected hash with whatever a port happens to serve. A shared health response
or unchanged marker cannot identify changed app code. This static pin proves only that the
selected resource matches before and after the run; retain the checkout fingerprint and
acceptance evidence for broader source binding.

With a real pin in place, the `yoke flow-smoke .` step from the section-1 pipeline is live.
`yoke flow-smoke` loads each route against the running dev server, waits for the landmark,
fails on any console error, and **always** saves a screenshot to `.yoke/proof/<story>/`
(the loop labels the folder with the current story id via `YOKE_STORY`; standalone runs use
`latest`, or pass `--label=`). Requires Playwright in the project:
`npm i -D playwright && npx playwright install chromium`. Start the dev server before verify
(e.g. via `start-server-and-test`).

## 3. Video only when necessary

`yoke flow-smoke` records video per flow and keeps it **only on failure**
(`.yoke/proof/<story>/<flow>.webm`). When a flow goes red: watch that clip first, then use the
wired Playwright MCP to reproduce interactively. Never record every run manually — the gate
already handles the failure case.

## Rule

Green pipeline = types + units + no design-slop over budget + served-source identity matches
before and after the run + every flow renders without
console errors, with a screenshot to prove it. Only then is the story actually done.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…