Skip to content

feat(skills): spring registers, bakeSpring for the CSS/WAAPI lanes, follow-through + inertia-chain - #3779

Open
jbernard077 wants to merge 1 commit into
heygen-com:mainfrom
jbernard077:feat/spring-registers-and-bake
Open

feat(skills): spring registers, bakeSpring for the CSS/WAAPI lanes, follow-through + inertia-chain#3779
jbernard077 wants to merge 1 commit into
heygen-com:mainfrom
jbernard077:feat/spring-registers-and-bake

Conversation

@jbernard077

@jbernard077 jbernard077 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Extends the spring lane of skills/hyperframes-animation on top of the springEase helper that
already ships in adapters/gsap-easing-and-stagger.md, and adds two secondary-motion rules.
Everything was validated in one deterministic reference build (24 s, 4 scenes) plus a three-lane
parity composition, both through the local gate (hyperframes check, which includes lint): 0 errors —
the reel carries one pre-existing structural warning, called out below — double-render frame hashes
bit-identical, and shuffled-vs-ascending direct seeks bit-identical on both (9/9 on the reel, 8/8 on the parity composition).

What's added

  1. Named registers (adapters/gsap-easing-and-stagger.md → Spring Eases → Named Registers) — a
    feel-word lookup over the existing springEase: snappy and heavy-settle for entrances and
    settles, and a separate Recovery Registers table (bouncy, wobbly) scoped to impact
    recovery only. The "< 0.55 — Don't" row is amended to name that single exception; the entrance
    doctrine (ζ ≥ 0.8, smooth beats bouncy) is untouched and restated beside the table. The
    durations quoted are what the helper returns for each pair.
  2. Duration is an output — the greppable criterion — the existing prose rule ("take both the
    ease and the duration from the helper") gets a mechanical audit: a spring tween's duration:
    carries no arithmetic; a longer flight scales response.
  3. bakeSpring() — bakes the closed-form spring into a CSS linear() easing
    (curvature-adaptive, at most 75 stops by default) for the css and waapi adapters, with a measured
    parity table (the error scales with travel) and one-line pointers from css-animations.md and
    waapi.md.
  4. rules/follow-through.md — a velocity-continuous ring-out composed into any ease that
    arrives with speed: the base curve's arrival velocity is measured numerically and a decaying-sine
    tail proportional to it extends the window. It explicitly does nothing on out eases (they
    arrive at rest — that is the existing doctrine); the C¹ default amplitude makes the ring size
    predictable (≈ 0.68 · v · amp of the travel).
  5. rules/inertia-chain.md — follow-the-leader secondary motion: every follower runs the
    leader's identical tween time-shifted by a couple of frames, so a stack or trail reads as one
    body with drag. The slide-in runs an entrance register; only a post-contact settle-back may use a
    recovery register, whose overshoot ripples down the chain. Longer-travel followers scale
    response, never the duration.

Plus two rules-index.md rows, a pointer in spring-pop-entrance.md's exact-physics variation, and
the hook-regenerated skills-manifest.json.

Validation

Evidence Result
hyperframes check reel: 0 errors (one pre-existing structural lint warning — four scenes on one track); parity composition: 0 errors, 0 warnings
Double-render frame hashes (PNG sequence, static-frame dedup off) reel 720/720, parity composition 120/120 bit-identical
Seek-shuffle (shuffled-order direct seeks vs ascending order) reel 9/9 (one seek per scene boundary and interior, including t = 17.0), parity composition 8/8 — bit-identical
Register durations from the helper snappy 0.29 s · heavy-settle 1.18 s · bouncy 0.81 s · wobbly 1.90 s
Stretched-duration audit grep -nE 'duration\s*\*' → 0 hits on spring tweens (the trail's longer flight is response-scaled)
bakeSpring parity in the render (wobbly register, maxPts: 200; CSS and WAAPI lanes vs the GSAP analytic ease, 1-px edge scan on every frame) ≤ 1 px over 220 px of travel, ≤ 2 px over 900 px, both lanes
Follow-through ring on the reel (power1.in, 700 px travel; 1-px edge scan, rest baselines differ by up to 5 px between the two panels) bare: 0 px overshoot · composed: +109 px at 0.5 s (15.6%), +54 px at 1.0 s (7.7%) against the formula's 14.5% / 7.2% — the halving with arrival speed holds

Fit against current HEAD

Every insertion anchor was re-verified against main @ 250afc3 before cutting this branch. Two
things worth flagging to reviewers:

  • The registers are a lookup over the existing helper, not a new signature —
    springEase({ response, dampingFraction }) is unchanged; SPRING_REGISTERS[feel] feeds it.
  • The runtime's Studio spring(bounce) ease token (packages/core/src/parsers/springEase.ts, a
    single-parameter damped-cosine curve) and the parsers package's SPRING_PRESETS
    (mass / stiffness / damping presets for CustomEase generation) are untouched and unrelated: the
    registers here are { response, dampingFraction } pairs for the adapter doc's closed-form helper,
    which predates this PR.
  • The follow-through rule is scoped by measurement: every out ease arrives at zero velocity, so
    the rule applies to arrivals that carry speed (none, in eases) and says so, rather than
    claiming a ring on the house power3.out entrance.

Preview media

(reference reel: the feel table — every card arrives on an entrance register, the two recovery
registers appear only as the spring-back after a contact drop — with the baked-vs-analytic parity
pair on the same recovery, follow-through at full then half speed, the inertia chain with a snappy
arrival and a bouncy settle-back; the pennant in the last scene is the sibling baked-sim PR)

pr-a-spring-reel.mp4

🤖 Generated with Claude Code

…ollow-through + inertia-chain

Extends adapters/gsap-easing-and-stagger.md → Spring Eases on top of the existing springEase:
named registers as a feel-word lookup (snappy / heavy-settle for entrances; bouncy / wobbly as a
separate impact-recovery table, with the "< 0.55 — Don't" row amended to name that exception),
the greppable duration-is-an-output criterion, and bakeSpring() emitting a CSS linear() easing for
the css and waapi adapters with measured parity. Adds two rules — follow-through (a velocity-
continuous ring composed into any ease that arrives with speed) and inertia-chain (followers replay
the leader's identical tween, time-shifted by frames) — their rules-index rows, and one-line
pointers in spring-pop-entrance.md, css-animations.md and waapi.md.
@jbernard077
jbernard077 force-pushed the feat/spring-registers-and-bake branch from 9318ba9 to 885224f Compare September 8, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant