Skip to content
Back to skills

Motion Verify

ASecurity

Verify canvas and UI motion with a real macOS recording, uniform 30fps frames, a visual phase strip, and frame-to-frame pixel-diff statistics.

  • 141 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 2, 2026
developmentpythongobash

Security analysis

A100/100

Scanned September 26, 2026

npx -y skills add wlsdks/ontology-atlas --skill motion-verify --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Motion Verify?

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

Security grade badge for Motion Verify
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wlsdks-motion-verify-ontology-atlas/badge)](https://www.skillsdirectory.com/skills/wlsdks-motion-verify-ontology-atlas)

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: motion-verify
description: Verify canvas and UI motion with a real macOS recording, uniform 30fps frames, a visual phase strip, and frame-to-frame pixel-diff statistics.
when_to_use: Use when pnpm design:route includes motion-verify, or when a canvas or UI animation is suspected of stalls or jank. Not for static layout.
---

# Motion verification from a recording

Screenshots prove only that an animation reaches sampled states. Jank and frozen
frames hide between them. Record the real macOS display, extract uniform frames,
inspect a phase strip, then measure adjacent-frame change.

Run whenever `pnpm design:route` includes `motion-verify`. This is the completion
proof for temporal output, not an optional craft review.

## Preconditions

- The surface is visible on a real monitor. Headless sequential screenshots may
  diagnose a defect but cannot approve motion; if recording is unavailable,
  report the proof as deferred.
- Resolve available `ffmpeg` and `ffprobe` executables; the Homebrew path is
  an example, not a requirement. Report missing instrumentation before recording.
- Put recordings and frames in an external session scratch directory.
- Bind the recording to the reviewed surface with the `/design-build` §0-B
  capture of the same app/window/state (tree + screenshot paths).

## 1. Prepare a deterministic state

Set the exact URL, zoom, and state. The map sleeps while idle, so confirm the
motion keeps it awake and disable simulated reduced motion unless that is the
subject.

Add `?guides=off`. A first-run overlay contaminates the opening frames; closing it
by hand adds its own animation and focus change. Use `?guides=reset` only when the
guide itself is under test.

## 2. Record and extract

```bash
cd <scratch-directory>
screencapture -v -V 4 motion.mov
mkdir -p vidframes
ffmpeg -y -loglevel error -i motion.mov -vf fps=30 vidframes/f%03d.png
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 motion.mov
```

## 3. Find the crop carefully

Page coordinates differ from recording coordinates because of Retina scaling and
window position. Colour can locate candidates but cannot identify motion. A prior
amber-ring search cropped a static project hexagon and almost concluded that the
ring was frozen. Build and inspect a strip for candidate crops before computing
statistics.

## 4. Build a phase strip

Sample six frames 166ms apart and inspect them visually:

```python
from PIL import Image
box = (x0, y0, x1, y1)
strip = Image.new("RGB", (320 * 6, 320))
for k, i in enumerate([1, 6, 11, 16, 21, 26]):
    frame = Image.open(f"vidframes/f{i:03d}.png").convert("RGB")
    strip.paste(frame.crop(box).resize((320, 320)), (k * 320, 0))
strip.save("phase-strip.png")
```

Identify the active transition or continuous-motion interval in the strip.
Expected resting frames before or after a finite transition are not stalls.
Select that active interval for statistics; report its bounds and retain the
full recording so the selection can be checked.

## 5. Measure adjacent-frame change

```python
from PIL import Image
import statistics
from pathlib import Path

# Set start_frame/end_frame from the phase strip (zero-based, end exclusive).
frames = sorted(Path("vidframes").glob("f*.png"))[start_frame:end_frame]
if len(frames) < 2:
    raise ValueError("Active interval needs at least two recorded frames")
prev, diffs = None, []
for path in frames:
    frame = Image.open(path).convert("L").crop(box)
    if prev is not None:
        a, b = frame.tobytes(), prev.tobytes()
        samples = [abs(a[j] - b[j]) for j in range(0, len(a), 7)]
        if not samples:
            raise ValueError("The crop contains no pixels")
        diffs.append(statistics.mean(samples))
    prev = frame

mean = statistics.mean(diffs)
if mean == 0:
    raise ValueError("No change in the selected active interval; verify target and motion")
sd = statistics.pstdev(diffs)
stalls = [i for i, d in enumerate(diffs) if d < mean * 0.25]
spikes = [i for i, d in enumerate(diffs) if d > mean * 3]
print(f"mean={mean:.3f} cv={sd/mean:.2f} min={min(diffs):.3f} stalls={len(stalls)} spikes={len(spikes)}")
```

- `stalls == 0` is the primary pass condition within the declared active interval.
  Do not apply it to an intentional hold or the settled state of a finite transition.
- Consecutive stalls suggest idle-gate sleep or dropped browser frames; inspect
  `src/widgets/ontology-map/model/idle-gate.ts` activity flags first.
- `cv <= 0.4` is usually compression noise. Periodic spikes may be another motion;
  identify them in the phase strip.
- Do not judge pleasing speed from the statistic. Inspect the strip and apply the
  HIG principle that motion must not compete with content. Repeating above roughly
  twice per second is suspicious; this slowed the spotlight orbit to 750ms.

## Report

Open with the verdict in one line (approved, or the stall or defect), then state
app/window/route, Computer Use screenshot path and accessibility owner,
recording duration and fps, crop target, stalls and cv, the visual phase-strip
finding, reduced-motion result, and before/after values when tuned. Keep raw
recordings and frames in scratch, not the repository. No recording means no
motion approval.

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.