feat(core): route motion-path mutations through studio-api + fix clip stamping#1555
feat(core): route motion-path mutations through studio-api + fix clip stamping#1555miguel-heygen wants to merge 1 commit into
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
085862a to
c8aee05
Compare
775d644 to
070799e
Compare
jrusso1020
left a comment
There was a problem hiding this comment.
Holding per two independent verifications (Rames D Jusso + Via) of the same blocker. Calling out one specifically because it's a regression of work that landed earlier today.
🛑 Silent removal of the 5 readiness adapters from runtime/init.ts
packages/core/src/runtime/init.ts:9-13 + :1918-1924 — the five adapter registrations from https://github.com/heygen-com/hyperframes/pull/1548|#1548 (createMapboxAdapter / createLeafletAdapter / createGoogleMapsAdapter / createMaplibreAdapter / createD3Adapter) are removed in this diff. The factories themselves (and their .test.ts siblings) survive in runtime/adapters/, but the wiring at the registry — the thing that actually makes them participate in getReadyPromise() polling — is gone.
#1548 merged at 2026-06-18T05:21:28Z (~10 hours ago) specifically to gate __renderReady on map/viz async asset loading. If #1555 lands as-is, any composition that uses mapbox / leaflet / google-maps / maplibre / d3 will silently never reach render-readiness — the exact bug class #1548 was built to prevent. This is a real production regression, not just a code-style concern.
Most likely cause is a Graphite restack mishap when #1548 merged mid-stack and the conflict resolution dropped the wiring rather than preserved it. The benign path is one rebase + re-add the import + the 5 factory calls; the malignant path would require intentional rationale I can't find anywhere in the PR description.
Ask: confirm intentional (with rationale + regression-window acknowledgement) OR re-restack to preserve #1548's wiring.
🛑 HOLD_SYNC_MUTATION_TYPES set is incomplete
Echoing Rames D Jusso (packages/core/src/studio-api/routes/files.ts:534-548) — the set covers keyframe / motion-path-point mutations + delete but misses 5 mutation types that also change tween start or create a tween at position > 0:
add-motion-path—addMotionPathToScriptauthors a 2-anchor motionPath at caller'sposition; ifposition > 0, fresh tween snaps from CSS-base →(0,0)on start.add(generic) — can create position tweens viaproperties: {x, y}.update-meta—body.updates.positionchanges start; existing hold becomes stale.shift-positions/scale-positions— bulk-shift; pre-existing holds end up at wrong t.split-animations— produces new tweens at new positions.
syncPositionHoldsBeforeKeyframes is idempotent + script-scoped, so an over-broad set just costs one extra parse. Cheap expansion.
Non-blocking notes
Echoing Rames D Jusso:
init.ts:1440-1448—timedClipInFlowWeakMap cachesgetComputedStyle(el).positionlazily, never invalidates. Studio-edit-then-replay round-trip → stale cache picks wrong display branch. Either invalidate on style-position mutation or document the invariant.init.ts:1555-1559— visible branch uses rawtimedClipInFlow.get(rawNode), hidden branch usesisTimedClipInFlow(rawNode)(force-populates). Works by happy accident; align both or comment why.
Plus: PR body is the unfilled template across this whole stack. Worth filling in even a one-paragraph description before merge.
Once the adapter regression is addressed (re-add the wiring OR explicit rationale + downstream owner ack), happy to re-review.
… stamping Wire the new mutations into the file save route. Only authored clips suppress descendant stamping, so auto-stamped animated scenes can inline-expand.
070799e to
227aebe
Compare
jrusso1020
left a comment
There was a problem hiding this comment.
Re-reviewed at 227aebe4. Top blocker closed — adapter wiring restored at init.ts:9-13, :1939-1943, so the 5 readiness-adapter registrations from #1548 are back. Thanks for the fast restack.
Reduced-scope REQUEST_CHANGES on the remaining items, per Via's R2 verification:
1. HOLD_SYNC_MUTATION_TYPES set still incomplete at routes/files.ts:534-548.
7 keyframe-adjacent types added in the restack (good) — remove-all-keyframes, add-with-keyframes, replace-with-keyframes, convert-to-keyframes, materialize-keyframes, delete, delete-all-for-selector. The 5 position-changing-non-keyframe types still need to be added:
add-motion-path—addMotionPathToScriptauthors a 2-anchor motionPath at caller'sposition; ifposition > 0, fresh tween snaps from CSS-base →(0,0)on start.add(generic) — can create position tweens viaproperties: {x, y}.update-meta—body.updates.positionchanges start; existing hold becomes stale.shift-positions/scale-positions— bulk-shift; pre-existing holds end up at wrong t.split-animations— produces new tweens at new positions.
Cheap: syncPositionHoldsBeforeKeyframes is idempotent + script-scoped, so an over-broad set just costs one parse.
2. timedClipInFlow WeakMap stale-cache at init.ts:1445-1452.
Still no invalidation hook. Studio-edit-then-replay round-trip → stale cache picks wrong display branch. Either timedClipInFlow.delete(el) on style-position mutation, OR explicit invariant comment naming the round-trip case as out-of-scope.
3. init.ts:1560-1563 — visible/hidden branch asymmetry.
Visible branch uses raw timedClipInFlow.get(rawNode) (returns undefined for new nodes); hidden branch uses isTimedClipInFlow(rawNode) (force-populates). Works by happy accident — align both or comment why.
Once these three land, happy to re-approve. Also: PR body is still the unfilled template; please fill in before merge.

Stack: GSAP keyframe + motion-path editing — studio-api wiring + runtime clip fixes (#1553 → #1561).
What
Two things:
runtime/init.ts.Why
visibility:hiddenstill reserve their layout box, so a split clip's two halves stacked instead of overlapping.How
sourceMutation.ts+routes/files.ts: dispatch motion-path/keyframe ops through studio-api.init.ts: ancestor-suppression now counts authoreddata-startonly (hasAuthoredTimedAncestor); in-flow timed clips hide withdisplay:nonewhile positioned clips keepvisibility:hidden.Test plan
bun run test(core) greenhdr-hlg-regressionshard fails on the final ~4 frames (PSNR ~9.7 dB). Tracking whether the in-flow-clip hiding change interacts with HDR layered capture.