mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
Extend `inspect` to verify motion intent against the same seeked timeline
the renderer uses, catching render-≠-preview bugs that layout sampling can't:
entrance reveals the seek skips, broken stagger order, off-frame drift, and
frozen shots.
A `*.motion.json` sidecar next to the composition opts in (auto-discovered,
no flag, no authoring-framework changes); without one, inspect is unchanged.
inspect seeks a dense grid over the asserted selectors, builds an
element × time matrix of {rect, opacity, visible} plus per-scope liveness
signatures, and evaluates four assertions in Node:
appearsBy -> motion_appears_late
before -> motion_out_of_order
staysInFrame -> motion_off_frame
keepsMoving -> motion_frozen
A selector matching nothing is reported as motion_selector_missing rather
than silently passing. Findings reuse the LayoutIssue shape and flow through
the existing dedupe/collapse/limit/format pipeline and JSON envelope; they
are errors by default, so a failed assertion fails the run.
The motion pass runs in the same Chrome session as the layout audit (no extra
launch) and only when a sidecar is present.
This commit is contained in:
@@ -21,9 +21,9 @@ Everything runs through `npx hyperframes` unless project instructions specify a
|
||||
- CI / cross-host repro: `npx hyperframes render --docker --strict --output out.mp4`
|
||||
- Cloud (long / large): `npx hyperframes lambda render ./my-project --width 1920 --height 1080 --wait` (see Lambda below)
|
||||
|
||||
Run lint, validate, and inspect before preview. `lint` catches missing `data-composition-id`, overlapping tracks, and unregistered timelines. `validate` loads the composition in headless Chrome and reports runtime console errors plus WCAG contrast issues. `inspect` seeks through the timeline and reports text spilling out of bubbles/containers or off the canvas.
|
||||
Run lint, validate, and inspect before preview. `lint` catches missing `data-composition-id`, overlapping tracks, and unregistered timelines. `validate` loads the composition in headless Chrome and reports runtime console errors plus WCAG contrast issues. `inspect` seeks through the timeline and reports text spilling out of bubbles/containers or off the canvas — and, when a `*.motion.json` sidecar is present, verifies motion intent (entrances firing under seek, stagger order, in-frame, liveness) against that same seeked timeline.
|
||||
|
||||
For motion-heavy work, prefer snapshot-driven iteration — see `references/lint-validate-inspect.md` for the discipline.
|
||||
For motion-heavy work, prefer snapshot-driven iteration and a `*.motion.json` sidecar — see `references/lint-validate-inspect.md` for the discipline and motion-verification spec.
|
||||
|
||||
## Agent Conventions
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ When the composition is animation-driven, run the checks before you reach for `p
|
||||
- Capture `snapshot` at meaningful timeline states; look at the PNGs.
|
||||
- Inspect snapshots _before_ tuning automated warnings — your eye catches what the auditor misses.
|
||||
- Treat layout warnings as defects unless a snapshot proves the overflow is intentional, in which case mark it with `data-layout-allow-overflow`.
|
||||
- State motion intent in a `*.motion.json` sidecar so `inspect` checks it automatically — entrances firing under seek, stagger order, in-frame, liveness. This is the closest automated proxy for "watch the MP4" and catches render-≠-preview bugs the eye misses (see **Motion verification** below).
|
||||
|
||||
## lint
|
||||
|
||||
@@ -82,6 +83,33 @@ Errors should be fixed before rendering. Warnings are surfaced for agent review;
|
||||
|
||||
`npx hyperframes layout` remains available as a compatibility alias for the same visual inspection pass.
|
||||
|
||||
### Motion verification (`*.motion.json` sidecar)
|
||||
|
||||
`inspect` also checks **motion intent** against the same seeked timeline the renderer uses — the closest automated proxy for "render the MP4 and watch it". It catches render-≠-preview bugs layout sampling can't: an entrance reveal the seek lands past, a broken stagger order, an element drifting off-frame mid-tween, a frozen shot.
|
||||
|
||||
Drop a `*.motion.json` sidecar next to the composition (matching the html basename when several compositions share a dir). `inspect` discovers it automatically — no flag, no authoring-framework changes. With no sidecar, `inspect` behaves exactly as before.
|
||||
|
||||
```json
|
||||
{
|
||||
"duration": 6,
|
||||
"assertions": [
|
||||
{ "kind": "appearsBy", "selector": "#headline", "bySec": 0.5 },
|
||||
{ "kind": "before", "a": "#headline", "b": "#cta" },
|
||||
{ "kind": "staysInFrame", "selector": ".card" },
|
||||
{ "kind": "keepsMoving", "withinSelector": ".scene" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Assertion | Fails (code) when |
|
||||
| ------------------------------ | --------------------------------------------------------------------------- |
|
||||
| `appearsBy(selector, bySec)` | not visible (opacity ≥ 0.5) by `bySec` — `motion_appears_late` |
|
||||
| `before(a, b)` | `a` does not first appear strictly before `b` — `motion_out_of_order` |
|
||||
| `staysInFrame(selector)` | once visible, its box leaves the canvas — `motion_off_frame` |
|
||||
| `keepsMoving(withinSelector?)` | a fully-static window exceeds `maxStaticSec` (default 2s) — `motion_frozen` |
|
||||
|
||||
`duration`, `withinSelector`, and `maxStaticSec` are optional. Findings are **errors by default** (a failed assertion fails the run, like a layout error — `--strict` still gates warnings) and appear in the same human and `--json` output as layout findings. A selector that matches nothing is reported as `motion_selector_missing` rather than silently passing — so a typo'd selector fails loudly. Use this in the feedback loop instead of eyeballing the render: assert what the motion is supposed to do, and let `inspect` tell you when the seek diverges from intent.
|
||||
|
||||
## snapshot
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user