SuperAPI AI Directory

design-review-workflow

Testing & quality

View repository

Updated 10-18 18:01

About this skill

Design review workflow

Once per release, at the end, on a green release build: a capture sweep of every screen and state in both themes, both text directions, the default and the largest text size, on the smallest phone and a large screen of each platform, every motion moment on video, and an on-device pass on real cheap phones. Findings are graded, fixed in exactly one round and verified on new shots, and a dated sign-off in a committed record gates the release. Four zero-dependency scripts prove the plan covers the app, the record is complete and honest, and nothing people see changed after the sign-off.

Rules that must hold

  1. Review once per release, at the end, on a build whose gates are green; never per task. The record names the swept commit and "verify": "pass" (review-record). Why: blocking build tasks on a visual critique slows every task, and a review of a red build re-tests what CI proves instead of judging what only eyes, ears and hands catch.
  2. The plan sweeps the whole app, decided by the app's own facts. Every screen and state of the screen contract (embedded parts and reasoned exclusions aside), every theme userInterfaceStyle shows, one ltr and one rtl locale, default on every device and largest (iOS accessibility-extra-extra-extra-large, Android font_scale 2) on every smallest phone, a smallest phone and a large screen per platform, the large screens in landscape (Android's always, the iPad's unless requireFullScreen), because a portrait lock binds phones only (plan-screens, plan-themes, plan-locales, plan-text-sizes, plan-devices). Why: nobody looks at every screen otherwise, and the worst cell (dark, rtl, largest text, smallest phone) is where most bugs are.
  3. Every state opens by a recorded link. screens.open maps each <screen>.<state> to a debug-link query (parameters from contracts/debug-links.json, never lang, theme or motion) or an app path (plan-open). Why: a cell anyone can re-shoot the same way is evidence; a state reached by tapping through a flow drifts between runs.
  4. Sweep the preview build on simulators and emulators you created and named. preview only (Release JavaScript that keeps the debug link every combination sets language, theme and motion=still through, and the videos motion=system, so the contract must declare those values), each device <project>-<purpose>, the status bar pinned to 9:41, stills captured upright by the runner, never by the flow (plan-build, plan-open, plan-devices). Why: the development client, a shared or "booted" device and a moving clock make captures that differ where the app does not; production strips the link, and the on-device pass judges the store build.
  5. Every cell is a real capture in one folder, and an axis that changed nothing is a failure. One PNG per cell named <screen>.<state>--<theme>--<locale>--<text>--<device>.png, its hash in the record, not blank (at least three colours), the device's size and orientation; two captures that differ only in theme, locale or text size and are identical fail unless the plan declares the screen invariant there (review-cells, review-capture, review-axis). Why: a missing appearance or language switch produces a sweep that looks complete and checks nothing.
  6. Motion is judged on video, at full and reduced motion, per platform. Every moment of the motion catalog is recorded or listed with why; each recorded moment has both videos (plan-motion, review-videos). Why: a still cannot show a skip, a blocked tap or a reduced alternative.
  7. Grade every finding BLOCKER, FIX or NOTE; every accessibility-floor finding is a BLOCKER. Contrast, touch target, text scale, colour alone, direction, reduce motion, screen reader and assistive access, and a failed floor or data step of the device pass, are BLOCKERs however good the screen looks; a BLOCKER or FIX is never deferred (review-findings, review-floor). Why: the floor is what keeps the app usable, and aesthetics never buy it back.
  8. Run the on-device pass on real, cheap phones in real state, every step answered, destructive steps last. One phone per shipped platform with model, OS and day; every core step pass, fail with its finding, or n/a with why, in plan order (plan-device-pass, review-device-pass). Why: screenshots prove layout, never audio, haptics, fonts, memory or upgrades; and upgrade, restore, crash and reinstall destroy the state the other steps need.
  9. Exactly one fix round, every fix verified on its new shot, and verification opens only NOTEs. The round's commit and green gates are recorded, each fixed finding's cells and videos differ from the captures it was seen on, and a finding opened while verifying is a NOTE (review-fix-round). Why: a second round never ends, and a fix nobody looked at again is a guess.
  10. The dated sign-off agrees with the record. Date (local, not future, after the fix round), reviewer, the commit that was looked at, and SIGNED OFF only with every BLOCKER and FIX fixed, every NOTE in the backlog, every cell and video captured and no failed step; otherwise NOT SIGNED OFF with the escalation (review-signoff). Why: a verdict that contradicts the findings is a rubber stamp.
  11. The sign-off gates the release. The newest review of the version is SIGNED OFF, the plan and screen contract are unchanged since, and no user-facing file changed after the signed commit (signoff-missing, signoff-stale, signoff-ui-changed): app code, assets, the entry, the app config and the files it imports, the lockfiles, the build transforms, eas.json, plugins, patches and env files, plus the plan's signoff.watch; a release lane's build-number bump alone does not count. Why: the build people looked at must be the build that ships.
  12. Never narrow the sweep or soften the record to get a pass. The text sizes are fixed values, a sign-off refuses uncaptured cells, and a ship gate never skips. Why: a narrowed or clamped sweep hides exactly the clipping and mirroring the review exists to catch.

Workflow

  1. Trigger. Every build task of the release is done and npm run verify is green on the commit. Read references/record-and-signoff.md ("When a review runs").
  2. Plan, once per app. Copy templates/contracts/design-review.json and its schema to contracts/; fill the devices, the open link of every state and the hardware from references/sweep-matrix.md. Run node ${CLAUDE_SKILL_DIR}/scripts/check-review-plan.mjs . until RESULT: PASS; --list prints every cell. Commit the plan on its own.
  3. Start the record. node ${CLAUDE_SKILL_DIR}/scripts/new-review.mjs . writes design-review/<review-id>/review.json and the capture folders; fill build.commit and "verify": "pass".
  4. Capture. Copy templates/scripts/design-review/review-cells.ts and device-settings.ts (with their tests) into the app; build a runner shaped like examples/capture-sweep.ts and examples/open-cell.yaml (e2e-maestro owns the Maestro runner). Follow references/capture-recipes.md: your own named devices, Release build, clean status bar, the planned orientation, then every combination, then motion=system (VIDEO_QUERY: the stills' motion=still is saved) and every motion video. Then node ${CLAUDE_SKILL_DIR}/scripts/new-review.mjs . --refresh and node ${CLAUDE_SKILL_DIR}/scripts/check-review.mjs . --in-progress until only findings, the device pass and the sign-off remain.
  5. Look and grade. Read every cell and watch every video, following references/grading-rubric.md; write each finding with its exact cell names, lens and grade. Consolidate one finding per cause.
  6. Device pass (human step). Ask a person for it on the store-channel builds, following references/device-pass.md; record every answer as reported, never from memory.
  7. Fix round. new-review.mjs . --refresh (stores each finding's seen hashes); fix every BLOCKER and FIX with a failing test first where a machine can catch it; run the gates; re-shoot only the named cells and videos and re-run failed steps; --refresh; look at each new capture; record the fix round.
  8. Sign off. Write the sign-off (or NOT SIGNED OFF with the escalation), then node ${CLAUDE_SKILL_DIR}/scripts/check-review.mjs . until RESULT: PASS. Any FAIL line: references/failure-messages.md. examples/tasks-review.json is a finished record.
  9. Gate the release. node ${CLAUDE_SKILL_DIR}/scripts/check-signoff.mjs . (in CI with full history, or --changed-from <file> holding git diff -U0 <signed>..<release>). Put the Design review line in the release report (git-commits-and-reporting), deferred NOTEs under "Not tested or not verified", and archive the capture folder with the release.

Definition of done

  • The review ran once, at the end, on a Release build of a commit whose gates were green.
  • node ${CLAUDE_SKILL_DIR}/scripts/check-review-plan.mjs . prints RESULT: PASS. Allowed SKIP lines, only while their owners have not created the file (a review itself needs the screen contract): SKIP contracts/debug-links.json [plan-open] not yet created (debug-menu-and-test-hooks creates it), SKIP src/ui/motion/motion-moments.ts [plan-motion] not yet created (motion-and-animation creates it), SKIP contracts/screens.json [plan-screens] not yet created (screen-contracts creates it), SKIP src/i18n/languages.ts [plan-locales] not yet created (i18n-strings-and-catalogs creates it).
  • Every cell and motion video is captured, every cell and video was looked at, every finding is graded with the floor as BLOCKER, the on-device pass is answered on real phones, and the one fix round is verified on new shots.
  • The record is committed with a dated sign-off; the capture folder is archived with the release.
  • node ${CLAUDE_SKILL_DIR}/scripts/check-review.mjs . prints RESULT: PASS on the machine that holds the captures.
  • node ${CLAUDE_SKILL_DIR}/scripts/check-signoff.mjs . prints RESULT: PASS

Anti-patterns

  • Per-task design review. Critiquing pixels while building blocks every task; note it and keep going, the review looks at everything once.
  • Reviewing a debug build, the development client, or a shared "booted" simulator. Wrong bundle, overlays, someone else's device; sweep the preview Release build on devices you created.
  • A sample instead of the matrix. "I checked the main screens in light mode" finds nothing that breaks; every cell, then the worst cell of each screen.
  • Clamping text or picking a "largest" the layout survives. That hides the bug the cell exists to find; the cap is accessibility-as-code's 200 %, never lower.
  • Skipping right to left because the device locale has none. The in-app language (the debug link's lang) is the path people use and the hardest case.
  • Grading a floor miss as FIX because the screen is beautiful. Floor misses are BLOCKERs.
  • A second fix round, or quiet iteration on a surviving BLOCKER. One round; then sign-off or escalation and a new review.
  • Marking a finding fixed without re-shooting its cells or recording its videos again. review-fix-round refuses it; look at the new capture.
  • Re-testing what CI proves. Lint, types, catalog parity and goldens are the precondition, not the review.
  • A device farm or a flagship instead of a cheap phone in real state. Both hide what the median person hits.
  • Shipping after a change to src/, a lockfile or the build config with the old sign-off. The gate fails it; re-shoot and sign again, or revert.
  • A loose note as the sign-off. It is a committed record the release gate reads.

Files in this skill

File What it is Read/run when
references/sweep-matrix.md The axes and why, cell names and cost, every plan key, devices and models, text sizes, motion, hardware Workflow step 2; any plan-* failure
references/capture-recipes.md Named devices, the capture order, iOS and Android commands, motion videos, pitfalls, what was verified Workflow step 4
references/grading-rubric.md How to look, the five lenses, the accessibility floor, grades, the finding format, examples Workflow step 5
references/device-pass.md The hardware, the eleven core steps, recording results, asking a person Workflow step 6
references/record-and-signoff.md When a review runs, the record's life and format, hashes, the fix round, the sign-off, the release gate, CI, the report line Workflow steps 1, 3, 7 to 9
references/failure-messages.md Every rule id with cause and fix, the ERROR and SKIP lines, the limits of the picture heuristics Any FAIL, ERROR or SKIP line
templates/contracts/design-review.json The plan for the reference Tasks app (2 screens, 4 devices, 48 cells, 8 videos) Workflow step 2 (copy, then fill)
templates/contracts/design-review.schema.json Its JSON schema Workflow step 2 (copy with it)
templates/scripts/design-review/review-cells.ts Cells, capture combinations, open links, files and videos for the app's runner Workflow step 4 (copy with its test)
templates/scripts/design-review/review-cells.test.ts Its test Workflow step 4 (copy)
templates/scripts/design-review/device-settings.ts Appearance, text size, orientation, status bar, upright screenshot, video and animation-scale commands, always on a named device Workflow step 4 (copy with its test)
templates/scripts/design-review/device-settings.test.ts Its test Workflow step 4 (copy)
examples/capture-sweep.ts The shape of a sweep runner built on the two templates: devices in parallel, one capture path Workflow step 4
examples/open-cell.yaml The shape of a Maestro flow that turns the simulator, opens a link and waits for the cell Workflow step 4
examples/tasks-review.json A finished, signed-off record: one FIX fixed and re-shot, one NOTE in the backlog Workflow steps 5 to 8
scripts/check-review-plan.mjs Proves the plan covers the app; --list prints every cell and video Workflow step 2 and before every review
scripts/new-review.mjs Writes the record from the plan; --refresh follows the plan, stores seen hashes, hashes captures Workflow steps 3, 4 and 7
scripts/check-review.mjs Proves one review: captures, axes, videos, findings, device pass, fix round, sign-off; --in-progress Workflow steps 4 and 8
scripts/check-signoff.mjs The release gate: signed off, not stale, nothing user-facing changed since; --changed-from for CI Workflow step 9; before every release upload
scripts/selftest.mjs Proves every script on a reviewed Tasks app and planted bugs; compares the template's cell grammar After changing a script
scripts/lib/review-plan.mjs The plan, the app facts, the cell grammar (this skill's own) Never directly
scripts/lib/review-record.mjs The record, the shared review rules, the Prettier-shaped JSON writer (this skill's own) Never directly
scripts/lib/ts-literal.mjs Reads TypeScript literal data (synced, do not edit) Never directly
scripts/check-lib.mjs Shared script library (synced, do not edit) Never directly
tests/bases/app/ The small Tasks app the fixtures start from When changing a script
tests/fixtures/ Overlay cases per script: good, pass-, bad- (one planted bug per rule), error-* When changing a script
assets/shared.json The shared files this skill syncs When adding a shared file

Related skills

  • design-visual-parity - per-screen match with the approved design baselines while building.
  • accessibility-as-code - the floor's numbers and the screen-reader checklist the device pass runs.
  • screen-contracts - the screens and states the sweep covers.
  • debug-menu-and-test-hooks - the debug link that opens every state and holds motion still.
  • e2e-maestro - the Maestro flows and runner that capture the cells.
  • ios-simulator-build / android-emulator-build - the Release builds on named devices.
  • motion-and-animation - the moment catalog recorded on video.
  • rtl-and-direction, i18n-strings-and-catalogs, adaptive-layout - what the rtl, locale and tablet cells judge.
  • ui-states-and-feedback - the empty, error and offline states swept as their own cells.
  • tdd-workflow - a failing test first for every fix a machine can catch.
  • git-commits-and-reporting - the release report line and the stop-and-ask for the device pass.
  • ci-pipeline-and-gates, ios-release-testflight, android-release-play, eas-build-and-submit - where the release gate runs.
  • run-migration, data-export-and-restore - the upgrade and restore steps of the device pass.