ai-review-ui
Skill65 starsChanged 2 months agoApache-2.0View on GitHub
Compare the live UI of the web app against its HTML prototype in .ai-engineering/workflow/prototypes/ and report the visual and behavioral gaps. Screenshots both, then two parallel reviewers (subagents, or `claude -p`) diff them, one for visuals and one for behavior. Use when the user asks to review, check, or diff the implemented UI against a prototype (e.g. "/ai-review-ui order-list", "does the settings page match the prototype?").
In this repository41 other files it gives its agents.
- AGENTS.mdAGENTS.md
- a11y-auditSkill
- ai-adversarial-loopSkill
- ai-agents-mdSkill
- ai-architectSkill
- ai-audit-codeSkill
- ai-audit-designSkill
- ai-audit-docsSkill
- ai-brainstormSkill
- ai-codegraphSkill
- ai-config-to-projectSkill
- ai-debugSkill
- ai-design-md-plannerSkill
- ai-exploreSkill
- ai-git-cleanupSkill
- ai-issue-reportSkill
- ai-noteSkill
- ai-orchestratorSkill
- ai-prototypeSkill
- ai-prSkill
- ai-read-docsSkill
- ai-researchSkill
- ai-securitySkill
- ai-stress-testSkill
- ai-test-plannerSkill
- ai-triageSkill
- ai-verifySkill
- ai-visual-recapSkill
- ai-writeSkill
- ai-writing-behaviorSkill
- build-checkSkill
- code-auditSkill
- design-checkSkill
- feature-verifySkill
- full-reviewSkill
- perf-auditSkill
- review-routerSkill
- second-opinionSkill
- security-auditSkill
- spec-extractSkill
- verify-featureSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 20
If the route isn't obvious from the prototype name, send an Explore subagent to find the page that implements it and its component files.
- Very specific: line 24
Run curl -s -o /dev/null -w '%{http_code}' <web URL> (Project config → *Web URL*).
- Distinctive: line 66
Run from the repo root:
- Very specific: line 73
Before taking each pair of screenshots, it fingerprints the UI state on both sides: field values by label, open dialogs, alert or status …
- Very specific: line 94
Alternative:
claude -p: Use this when the user asks for it, or for a fully separate process. - Distinctive: line 108
Read by: ai-orchestrator, humans Dies: on completion Next: none
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Review UI against prototype
This skill runs in one of two modes. Work out which one you're in first.
- Standalone (a human ran
/ai-review-ui): run steps 1–5. The output is a findings report. Don't fix anything; step 5 ends by offering fixes, and fixing happens only if the user accepts. - Gate (
/ai-orchestratorGate 2): run steps 2–4 only, with the checkpoint'sui.scope. Before capturing, check thatroutein.ai-engineering/workflow/prototypes/<name>.states.jsonequals the checkpoint'sui.route; if not, fix the scenario file to useui.route, since the capture script only reads the scenario. ReturnPASSorFAILand the merged findings to the orchestrator. Never offer or apply fixes; failures go through the orchestrator's failure path. The gate passes when every in-scope, live-reproducible state ismatchand there are nohighormedfindings, other than ones tagged[intentional?].
1. Resolve the pair
- Prototype:
.ai-engineering/workflow/prototypes/<name>.html. Match it from the request; if more than one could fit, ask. - Live route: the page that implements it (see
FILEMAP.md, and Project config → Pages inAGENTS.md, which says where signed-in and public pages live). Public pages don't need the saved sign-in session. - Source files: that route's page file, plus any components it uses (Project config → Components).
If the route isn't obvious from the prototype name, send an Explore subagent to find the page that implements it and its component files. Have it return only the paths.
2. Make sure the app is reachable
- Run
curl -s -o /dev/null -w '%{http_code}' <web URL>(Project config → Web URL). If nothing answers, run the Dev server command from the repo root in the background and wait until it responds. - Signed-in pages need a saved session. If
.ai-engineering/workflow/playwright/auth.jsonis missing, stop and ask the user to run the command below, sign in, and close the window:! npx -y playwright codegen --save-storage=.ai-engineering/workflow/playwright/auth.json <web URL><sign-in path>.ai-engineering/workflow/playwright/is gitignored. If the screenshots come back showing the login page, the session has expired; ask the user to run the same command again.
3. Capture both sides in the same state
Never compare a prototype in one state with the live page in another, like an empty form against a submitted one. Every comparison is driven by a state scenario, .ai-engineering/workflow/prototypes/<name>.states.json, which /ai-prototype writes next to each prototype. If it's missing, write it first from the prototype's states:
{
"route": "/discounts",
"login": "/login",
"now": "2026-10-01T10:00:00",
"regions": ["page-header", "discount-list", "discount-form"],
"states": [
{ "name": "overview", "regions": ["page-header", "discount-list"], "steps": [] },
{ "name": "empty-form", "regions": ["discount-form"], "steps": [] },
{ "name": "validation-error", "regions": ["discount-form"], "steps": [{ "click": "Save discount" }] },
{ "name": "filled", "regions": ["discount-form"], "steps": [{ "select": "Type", "value": "Percentage" }, { "fill": "Amount", "value": "15" }] },
{ "name": "saved", "regions": ["discount-form", "discount-list"], "mutates": true, "steps": [{ "select": "Type", "value": "Percentage" }, { "fill": "Amount", "value": "15" }, { "click": "Save discount" }, { "waitFor": "Discount saved" }] },
{ "name": "no-discounts", "regions": ["discount-list"], "proto_query": "state=empty", "live": false, "live_note": "needs a store with no discounts" }
]
}Regions and scope: a checkpoint often builds only part of a screen, while its prototype shows the finished screen. The prototype marks each part with
data-region="<name>".regionslists them, and each state says which regions it exercises. With--scope page-header,balances:- the script captures only the states whose regions are all in scope;
- it fingerprints only the prototype elements inside in-scope regions, so parts that aren't built yet can't cause a MISMATCH;
- the reviewers judge only in-scope regions.
Region names match the checkpoint's
ui.scope.loginis the sign-in path from Project config (default/login). Landing there means the saved session expired. Without--scope, every state runs and the whole screen is compared (standalone mode, or the final checkpoint for a screen).- Steps:
fill/select/checktarget a field by its visible label.clicktargets a button by its name (add"role"for links or tabs).scrolltargets a CSS selector and accepts"to": "top"or"bottom"; it scrolls the element when scrollable and the page otherwise. There's alsopress,waitFor(text) andwait(ms). The same steps run on both sides, so the prototype and the live page must use the same labels and button text; a step that works on only one side is a finding in itself. - Data states: loading, error and empty lists are reached on the prototype with
proto_query, and on live withlive_queryor a different role's session ("auth": ".ai-engineering/workflow/playwright/auth-<role>.json"). If live can't reproduce the state, set"live": false. That state is then reviewed on the prototype alone and never compared. - Mutating states (
"mutates": true) run on live only when the base URL is localhost. List them last. - Viewports: both sides use the same viewports (default 1440×900 and 375×812), the same frozen clock (
now), reduced motion, and no animations. A state may override the viewport list with"viewports", for example"viewports": [[1440, 900]]for a desktop-only resize control.
Run from the repo root:
npx -y -p playwright sh -c 'NODE_PATH="$(dirname "$(command -v playwright)")/.." node skills/ai-review-ui/capture.cjs <name> <web URL> [--scope a,b]'The script writes .ai-engineering/workflow/playwright/review/<name>/<state>-<width>-{proto,live}.png, plus states.json.
Before taking each pair of screenshots, it fingerprints the UI state on both sides: field values by label, open dialogs, alert or status messages, and invalid fields. Each pair is marked match, MISMATCH (with the reasons) or proto-only.
- A MISMATCH means the two sides aren't in the same state, so their pixels aren't comparable. Report each mismatch as a
highfinding, e.g. "after submitting empty, the live page shows no validation", and exclude that pair from the visual review. redirected to <sign-in path>means the sign-in session has expired; see step 2.
4. Independent review
Hand the comparison to reviewers with fresh context, so they judge the screenshots and not your memory of building them.
Default: two agents in parallel. Launch ui-visual-reviewer and ui-behavior-reviewer in a single message. Their method, output format and rules are in their agent definitions (.claude/agents/), which also:
- give them a fixed model (visual:
opus; behavior:sonnet); - tell them to ignore
AGENTS.md, so they judge against the prototype and.ai-engineering/DESIGN.mdwithout the implementer's reasoning. Don't pass them the checkpoint's goal, tasks or implementation notes either.
Give each one only:
- the capture folder
.ai-engineering/workflow/playwright/review/<name>/; - the scope (
ui.scope, or "whole screen"); .ai-engineering/workflow/prototypes/<name>.html, plus.ai-engineering/workflow/prototypes/<name>.states.jsonfor the behavior reviewer;- the live source paths (the page and its components).
The visual reviewer judges sizes proportionally against each screenshot's own dimensions, not by eye. The behavior reviewer owns the MISMATCH findings.
Alternative: claude -p. Use this when the user asks for it, or for a fully separate process. Run both from the repo root, in parallel:
claude -p --agent ui-visual-reviewer "<inputs above>"
claude -p --agent ui-behavior-reviewer "<inputs above>"5. Report (standalone only)
Merge the two lists and drop duplicates, meaning the same element and the same difference. Put the state mismatches from states.json first. Relay the findings verbatim, grouped as high, then med, then low. Add the paths to the screenshots. Offer to fix the high-severity findings.
Lifecycle
Lane: standard, full Writes: nothing Read by: ai-orchestrator, humans Dies: on completion Next: none
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

