Skip to content

fix(core): prevent double-offset on pip video visibility and media sync#1086

Merged
miguel-heygen merged 5 commits into
mainfrom
fix/pip-video-double-offset
May 26, 2026
Merged

fix(core): prevent double-offset on pip video visibility and media sync#1086
miguel-heygen merged 5 commits into
mainfrom
fix/pip-video-double-offset

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

Summary

Fixes pip-wired media elements being permanently hidden in preview when their host sub-composition starts at a non-zero time. Applies the fix consistently across all three start-time consumers and adds a producer regression test.

Supersedes #1078 — based on @JamesXiaoFF's root cause analysis. Pushed to origin because the fork couldn't accept LFS objects for the regression baseline.

Root cause

resolveStartForElement adds the host composition's global start offset on top of the media element's own data-start. When a pip video has data-start="45.40" inside a host at data-start="45.40", the resolved start becomes 90.80 — well past the host's window, keeping the video permanently hidden.

Media elements authored with explicit data-start use global coordinates (matching the render pipeline's discoverMediaFromBrowser which reads the raw attribute). The resolver's local-to-global accumulation double-counts the offset for these elements.

Fix

For media elements (video/audio) without the data-hf-auto-start marker, read data-start directly as a global timestamp. Elements with data-hf-auto-start (compiler-injected data-start="0") continue using the resolver since their timing is composition-local.

Applied to all three consumers:

  • Visibility loop in init.ts
  • refreshRuntimeMediaCache start/duration resolution in init.ts
  • resolveMediaWindowEndSeconds in timeline.ts

Tests

Unit tests (init.test.ts):

  • Double-offset regression: pip video at data-start="45.40" inside host at 45.40 — visible at t=46, hidden at t=53 and t=44
  • Auto-start guard: video with data-start="0" + data-hf-auto-start inside host at 10 — visible at t=12, hidden at t=5 and t=16

Producer regression test (pip-video-late-host):

  • 6s composition with pip video inside a sub-composition host starting at t=3
  • 100/100 visual checkpoints pass, baseline generated in Docker

JamesXiaoFF and others added 4 commits May 26, 2026 16:03
…y loop

For video and audio elements, data-start is authored in global (composition-root)
time — the same contract used by the render pipeline's discoverMediaFromBrowser,
which reads the raw attribute directly. Previously, the visibility loop called
resolveStartForElement which adds the nearest ancestor composition's global start
on top, causing a double-offset that kept pip-wired media permanently hidden when
the host composition did not start at t=0.

Example: a pip video with data-start="45.40" inside a host composition that also
starts at data-start="45.40" resolved to 90.80, so the video was always hidden
during its actual [45.40, 52.46] window.

Non-media elements (divs, sections, etc.) continue to use the accumulating
resolver because their data-start values are local to their composition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Narrow the raw data-start read to media elements without
data-hf-auto-start (explicitly authored global coordinates). Elements
with auto-injected data-start="0" remain composition-local via the
resolver. Apply consistently across all three consumers:
- visibility loop (init.ts)
- refreshRuntimeMediaCache start/duration (init.ts)
- resolveMediaWindowEndSeconds (timeline.ts)

Add regression test for auto-injected data-start="0" inside a
late-starting host to prove it doesn't regress.
Renders a 6s composition with a pip video inside a sub-composition
host starting at t=3. Verifies the video is visible during the host
window and not double-offset to t=6. Baseline generated in Docker.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 26, 2026

Fallow audit report

Found 62 findings.

Duplication (41)
Severity Rule Location Description
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:53 Code clone group 1 (15 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:100 Code clone group 2 (13 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:100 Code clone group 3 (11 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:104 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:112 Code clone group 5 (14 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:130 Code clone group 2 (13 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:130 Code clone group 3 (11 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:134 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:142 Code clone group 5 (14 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:160 Code clone group 6 (12 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:164 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:183 Code clone group 7 (12 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:202 Code clone group 6 (12 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:206 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:217 Code clone group 7 (12 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:235 Code clone group 8 (13 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:241 Code clone group 9 (23 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:246 Code clone group 10 (8 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:253 Code clone group 11 (8 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:283 Code clone group 12 (37 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:286 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:325 Code clone group 3 (11 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:373 Code clone group 12 (37 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:376 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:480 Code clone group 13 (14 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:480 Code clone group 8 (13 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:542 Code clone group 8 (13 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:542 Code clone group 13 (14 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:609 Code clone group 4 (7 lines, 7 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:659 Code clone group 14 (12 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.test.ts:679 Code clone group 14 (12 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.ts:762 Code clone group 15 (21 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.ts:790 Code clone group 15 (21 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.ts:1625 Code clone group 16 (14 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/init.ts:1902 Code clone group 16 (14 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/startResolver.test.ts:215 Code clone group 10 (8 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/startResolver.test.ts:222 Code clone group 11 (8 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/timeline.test.ts:364 Code clone group 9 (23 lines, 2 instances)
minor fallow/code-duplication packages/core/src/runtime/timeline.test.ts:369 Code clone group 10 (8 lines, 3 instances)
minor fallow/code-duplication packages/core/src/runtime/timeline.test.ts:376 Code clone group 11 (8 lines, 3 instances)
minor fallow/code-duplication packages/studio/src/player/hooks/useTimelinePlayer.test.ts:68 Code clone group 1 (15 lines, 2 instances)
Health (21)
Severity Rule Location Description
minor fallow/high-cognitive-complexity packages/core/src/runtime/init.ts:29 'initSandboxRuntimeModular' has cognitive complexity 22 (threshold: 15)
critical fallow/high-crap-score packages/core/src/runtime/init.ts:263 'applyClipLayout' has CRAP score 567.6 (threshold: 30.0, cyclomatic 49)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:476 'resolveAuthoredCompositionDurationFloorSeconds' has CRAP score 31.6 (threshold: 30.0, cyclomatic 10)
critical fallow/high-crap-score packages/core/src/runtime/init.ts:545 'resolveRootTimelineFromDocument' has CRAP score 385.6 (threshold: 30.0, cyclomatic 40)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:651 'collectRootChildCandidates' has CRAP score 37.1 (threshold: 30.0, cyclomatic 11)
major fallow/high-crap-score packages/core/src/runtime/init.ts:921 'bindRootTimelineIfAvailable' has CRAP score 71.3 (threshold: 30.0, cyclomatic 16)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:977 'emitRootStageLayoutDiagnostics' has CRAP score 43.1 (threshold: 30.0, cyclomatic 12)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:1081 'onError' has CRAP score 43.1 (threshold: 30.0, cyclomatic 12)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:1145 'rebindTimelineFromResolution' has CRAP score 37.1 (threshold: 30.0, cyclomatic 11)
major fallow/high-crap-score packages/core/src/runtime/init.ts:1194 '<arrow>' has CRAP score 79.4 (threshold: 30.0, cyclomatic 17)
critical fallow/high-crap-score packages/core/src/runtime/init.ts:1271 'syncMediaForCurrentState' has CRAP score 224.4 (threshold: 30.0, cyclomatic 30)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:1294 'resolveDurationSeconds' has CRAP score 49.5 (threshold: 30.0, cyclomatic 13)
minor fallow/high-crap-score packages/core/src/runtime/init.ts:1720 'seekStandaloneRegisteredTimelines' has CRAP score 43.1 (threshold: 30.0, cyclomatic 12)
critical fallow/high-crap-score packages/core/src/runtime/init.ts:1808 'transportTick' has CRAP score 482.4 (threshold: 30.0, cyclomatic 45)
major fallow/high-crap-score packages/core/src/runtime/init.ts:1928 'hardSyncAllMedia' has CRAP score 71.3 (threshold: 30.0, cyclomatic 16)
major fallow/high-crap-score packages/core/src/runtime/init.ts:1952 '<arrow>' has CRAP score 97.0 (threshold: 30.0, cyclomatic 19)
critical fallow/high-crap-score packages/core/src/runtime/init.ts:2109 'teardown' has CRAP score 106.4 (threshold: 30.0, cyclomatic 20)
minor fallow/high-crap-score packages/core/src/runtime/timeline.ts:53 'normalizeTrackAssignments' has CRAP score 31.6 (threshold: 30.0, cyclomatic 10)
minor fallow/high-crap-score packages/core/src/runtime/timeline.ts:151 'buildTimelineClipLabel' has CRAP score 31.6 (threshold: 30.0, cyclomatic 10)
critical fallow/high-crap-score packages/core/src/runtime/timeline.ts:177 'collectRuntimeTimelinePayload' has CRAP score 212.0 (threshold: 30.0, cyclomatic 143)
minor fallow/high-crap-score packages/core/src/runtime/timeline.ts:216 'resolveMediaWindowEndSeconds' has CRAP score 31.6 (threshold: 30.0, cyclomatic 10)

Generated by fallow.

Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the full diff + enumerated every resolveStartForElement call site in init.ts to audit intra-file parity. The math in the tests checks out (host[45.40, 52.46], pip[45.40, 52.46]: visible@46 ✓, hidden@53 ✓, hidden@44 ✓), and the render-preview parity restoration to match discoverMediaFromBrowser is the right call. But one parallel media-window site in init.ts looks unfixed.

Potential miss — resolveMediaWindowDurationSeconds in init.ts

This function has the same shape as collectRuntimeTimelinePayload in timeline.ts (the third site the PR did fix):

const resolveMediaWindowDurationSeconds = (): number | null => {
  const mediaNodes = Array.from(
    document.querySelectorAll("video[data-start], audio[data-start]"),
  ) as HTMLMediaElement[];
  ...
  for (const node of mediaNodes) {
    const start = resolveStartForElement(node, 0);   // ← unguarded
    ...
    maxWindowEndSeconds = Math.max(maxWindowEndSeconds, Math.max(0, start) + duration);
  }
  ...
};

It feeds an active code path:

resolveMediaWindowDurationSeconds
  → resolveMediaDurationFloorSeconds
    → resolveTimelineDurationSeconds  // returns Math.max(timelineDuration, durationFloor, fallbackDuration)

With the bug shape (pip video data-start="45.40" inside host data-start="45.40"), start = 90.80, so:

  • maxWindowEndSeconds = 90.80 + 7.06 = 97.86 (should be 52.46)
  • durationFloor becomes 97.86
  • safeDuration = Math.max(authoredTimeline, 97.86, ...) = 97.86 if the authored timeline isn't longer

So the timeline duration floor is inflated by the offset amount — the player would think the comp is ~98s long instead of ~52s. Wouldn't show up in the visibility test (which seeks to specific times and asserts a class), but would surface as wrong timeline length in the scrubber / metadata. Per the PR body, the fix was applied to "all three consumers" of resolveStartForElement on media — this is a fourth, parallel to the one that got fixed in timeline.ts.

Suggested patch — same guard shape as the other three sites:

const start = !node.hasAttribute("data-hf-auto-start")
  ? Math.max(0, Number(node.getAttribute("data-start") ?? 0) || 0)
  : resolveStartForElement(node, 0);

(The selector video[data-start], audio[data-start] already filters to media; no tag check needed inside the loop.)

Soft observation — CSS adapter on media elements

createCssAdapter({ resolveStartSeconds: (element) => resolveStartForElement(element, 0) }) also uses the unguarded resolver. If a pip video has a CSS animation attached (rare but legal — e.g. a fade-in keyframe), the CSS adapter would resolve its start time with the same double-offset. Probably an edge case rarely hit, but if you're patching resolveMediaWindowDurationSeconds anyway, worth checking whether the CSS adapter needs the same media/non-media discrimination. Not blocking.

Positive findings

  • Three patched sites + new test coverage matches the PR body. Math in both new tests checks out.
  • Test 2 (auto-start guard) is the load-bearing assertion that the data-hf-auto-start marker discriminator is what's discriminating. Without it, all media would skip the resolver and the auto-injected case would break.
  • Producer regression test pip-video-late-host + 100/100 visual checkpoints adds end-to-end coverage. Good closed-loop.
  • Render-preview parity is restored — preview now matches discoverMediaFromBrowser's global-coords assumption. This is exactly the kind of parity gap the reference_preview_render_parity_check lens watches for. ✓

Non-blocking observations

  • Four-site (would-be-five with resolveMediaWindowDurationSeconds) duplication of the same guard expression is a refactor candidate — resolveMediaStartSeconds(element, fallbackContext) helper would consolidate. Not for this PR; if more media-time call sites get added, the duplication grows linearly.
  • Fallow audit red but not acknowledged in the PR body. If it's the inherited duplication carried over, fine; if it's new (e.g. the four-site guard duplication tripping a new threshold), worth a sentence in the body.

Verdict

The fix is correct on the three patched sites and tests pin the contract well. The unfixed resolveMediaWindowDurationSeconds is a real-but-non-visibility-critical leftover from the same bug class — would recommend patching before merge for a clean fix, or filing as a follow-up if scope-bound.

— Rames Jusso (hyperframes)

Copy link
Copy Markdown
Collaborator

@vanceingalls vanceingalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review

Strengths

  • init.test.ts:477 pins the exact regression numbers (45.40 + 45.40 → 90.80) as a unit test — the comment is the best kind of commit message. Having the arithmetic of the bug visible in the test makes future archeology obvious.
  • init.test.ts:542 (auto-start guard test) correctly pins the opposite branch: auto-injected data-start=\"0\" + data-hf-auto-start still uses resolveStartForElement and resolves at host time, not t=0. That's the right second test to have here.
  • The producer regression (pip-video-late-host/) is exactly the right kind of coverage for a visibility/sync fix — frame-level checkpoints will catch any backslide.

Findings

blocker — init.ts:460resolveMediaWindowDurationSeconds has the same double-offset, untouched

The PR fixes three consumers of resolveStartForElement on media elements:

  • resolveStartSeconds in refreshRuntimeMediaCache (hunk at @@ -1278)
  • resolveDurationSeconds in refreshRuntimeMediaCache (hunk at @@ -1285)
  • visibility loop (hunk at @@ -1329)

A fourth consumer is not patched:

// init.ts:453
const resolveMediaWindowDurationSeconds = (): number | null => {
  const mediaNodes = Array.from(
    document.querySelectorAll("video[data-start], audio[data-start]"),
  ) as HTMLMediaElement[];
  ...
  for (const node of mediaNodes) {
    const start = resolveStartForElement(node, 0);  // ← double-offset for pip media
    ...
    maxWindowEndSeconds = Math.max(maxWindowEndSeconds, Math.max(0, start) + duration);
  }
  return maxWindowEndSeconds ...;
};

This function queries the same video[data-start] set, calls resolveStartForElement unguarded, and feeds its result into resolveSafeDurationForTimeline via resolveMediaDurationFloorSeconds. For the bug's canonical case (pip video at data-start=45.40 inside host at 45.40, duration 7.06 s), this site would compute floor = 90.80 + 7.06 = 97.86 s — inflating the root timeline's calculated duration floor well past the actual 52.46 s composition end. That makes timeline duration resolution incorrect in the exact scenario the PR claims to fix.

Same contract violation, different code path. Per Rule 2 in the review rubric, a sibling site with the same failure mode is a blocker, not a follow-up.

Fix is the same guard pattern already established in this PR:

const isGlobalMediaStart = !node.hasAttribute("data-hf-auto-start");
const start = isGlobalMediaStart
  ? Math.max(0, Number(node.getAttribute("data-start") ?? 0) || 0)
  : resolveStartForElement(node, 0);

important — CSS adapter at init.ts:1632 — same unguarded resolveStartForElement for any element with CSS animations

createCssAdapter({
  resolveStartSeconds: (element) => resolveStartForElement(element, 0),
}),

createCssAdapter discovers ALL elements with CSS animations (document.querySelectorAll("*")). A pip <video> with a CSS animation and data-start in a sub-composition would get the double-offset start applied to its CSS animation seek. This is narrow (pip videos with authored CSS animations are uncommon) but follows the same contract. Either apply the same guard here, or add a comment explicitly documenting why this path doesn't need it (e.g. "CSS animations on media elements are authoring-time-only and don't appear inside sub-compositions").


important — Helper extraction would have prevented the missed site

The !hasAttribute("data-hf-auto-start") && hasAttribute("data-start") ? Math.max(0, Number(...) || 0) : resolveStartForElement(...) pattern is inlined at four sites across two files after this PR. A named helper — something like resolveMediaElementStartSeconds(el, resolveStartForElement) — would make the contract explicit and make it hard to add a fifth site without the guard. The blocker above is the direct consequence of not having it.


nit — Fallow audit is failing

The new resolveMediaWindowEndSeconds in timeline.ts just ticked over the CRAP-score threshold (31.6 vs. 30.0 ceiling). Not a required check gate, but the signal is real — this function now has both cyclomatic complexity and low test coverage. If you add the fix for the blocker above, consider pulling the guard into a helper to keep the function complexity flat.


Verdict: REQUEST CHANGES
Reasoning: resolveMediaWindowDurationSeconds (init.ts:460) satisfies the same contract as the three patched sites — it queries pip-wired media elements and calls resolveStartForElement unguarded — meaning the double-offset bug survives in root timeline duration computation for the exact case the PR claims to fix. All other CI checks pass (BLOCKED is reviewer-gate only).

— Vai

Fix the 4th unguarded resolveStartForElement call site in
resolveMediaWindowDurationSeconds that inflated the timeline duration
floor for pip compositions. Extract resolveMediaStartSeconds helper
to consolidate the data-hf-auto-start guard across all call sites.
Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed ca39687 ("patch resolveMediaWindowDurationSeconds + extract helper"). Vai's blocker + my consolidation nit both addressed.

Verified

  • resolveMediaStartSeconds helper extracted at init.ts:387 — single source of truth for the data-hf-auto-start guard.
  • Applied at 4 sites in init.ts:
    • resolveMediaWindowDurationSeconds (the blocker Vai caught) ✓
    • resolveStartSeconds callback in refreshRuntimeMediaCache
    • resolveDurationSeconds callback in same ✓
    • Visibility loop, with tag === "video" || tag === "audio" predicate before calling the helper ✓
  • The visibility-loop tag predicate is the right shape — non-media elements (divs etc.) skip the helper and stay on the composition-local resolver.
  • Build / Lint / Typecheck / Test / Studio smoke / CLI smoke / Perf / Preview parity all green on this commit; regression-shards + Windows still in flight but those don't usually go red post-typecheck.

Two carry-over items (non-blocking, follow-ups)

  1. timeline.ts collectRuntimeTimelinePayload still has the inline guard, not the helper. Same logic, just not consolidated through the new helper. Cosmetic; the helper lives in init.ts so an export + cross-file import would be needed to share. Not worth a round-trip on this PR.

  2. createCssAdapter at init.ts:1632 — still calls resolveStartForElement(element, 0) directly. Vai flagged this as "important" (CSS animations on pip media elements would get the double-offset applied to their animation seek). Narrow case (pip video + CSS animation is a rare combination) but if anyone wants a clean five-sites story, this is the fifth site. Easy follow-up.

Verdict

The primary fix is correct and the helper extraction is clean. The unaddressed CSS adapter case is the only remaining same-bug-class site, but it's a different surface (animation timing, not visibility/duration) and Vai's "important" grade was already non-blocking. Fine to ship as-is; CSS adapter can be a separate one-line follow-up.

— Rames Jusso (hyperframes)

Copy link
Copy Markdown
Collaborator

@vanceingalls vanceingalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after push. Both items from the prior review addressed cleanly.

Blocker resolved — resolveMediaWindowDurationSeconds (init.ts:460)

The resolveMediaStartSeconds helper introduced at init.ts:391 is the right extraction: single guard for the data-hf-auto-start / data-start pattern, now called at all four media-start consumer sites. The prior review's blocker (double-offset in resolveMediaWindowDurationSeconds) is confirmed fixed via line 467. James's re-review already verified all four application sites.

Nit resolved — helper extracted

Guard is no longer inlined 4× — resolveMediaStartSeconds is the single definition. Good.

Carry-over — CSS adapter (init.ts:1675-1677)

createCssAdapter({ resolveStartSeconds: (element) => resolveStartForElement(element, 0) }) still passes the unguarded resolver. A pip <video> with CSS animations would still get the double-offset on its animation seek. This was "important" in the prior review, not a blocker — narrow case (pip video + CSS animation), and James's re-review explicitly called it out as a clean follow-up one-liner. Deferring is fine; just want it tracked and not dropped.

CI

All required checks pass. Fallow audit fail is pre-existing complexity on the large init.ts functions, not introduced by this PR. Regression shards pending but not required.

Approving. The primary correctness fix is solid.

— Vai

@miguel-heygen miguel-heygen merged commit c535528 into main May 26, 2026
45 of 46 checks passed
Copy link
Copy Markdown
Collaborator Author

Merge activity

@miguel-heygen miguel-heygen deleted the fix/pip-video-double-offset branch May 26, 2026 18:25
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.

4 participants