Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

runtime: startResolver only checks the immediate parent for composition attributes, so a mount wrapped by any element is seeked on the root clock

Open
#4,334 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
web-dev

Research direction

Start in packages/core/src/runtime/startResolver.ts, focusing on the no-authored-start branch, then review packages/core/src/runtime/startResolver.test.ts and its existing resolver setup. Add the neutral-wrapper regression matrix for the three composition markers, run bun run --cwd packages/core test src/runtime/startResolver.test.ts, and verify the accepted boundary and timing cases remain intact.

Written by the indexing model from the issue text.

Description

difficulty/medium triage/ready

Found while exporting After Effects comps to data-vfx-chain hosts (hyperframes-ae-mcp, findings §Task 3.14, 2026-09-23).

Symptom. A sub-composition mount whose data-composition-src element sits under a wrapper (here <canvas layoutsubtree class="hf-vfx-src"> > .hf-vfx-in[data-composition-src]) resolves its start to 0 and is seeked on the root clock. Once root time passes the sub-comp's own duration, its layers go visibility: hidden, and drawElementImage returns a transparent bitmap with no error. On retro-wave the mounted Logo comp painted 17,874 / 22,633 / 0 / 0 opaque px at root t = 7.3 / 8.5 / 10.444 / 12.5 s with byte-identical geometry; the threshold is exactly the sub-comp's 10.01 s duration.

Cause. startResolver's walk-up is one level: it fires only if the immediate parent carries data-composition-src / -id / -file. A canvas or any exporter/author wrapper between them breaks the chain.

Ask. Use a closest()-style walk (nearest ancestor carrying a composition marker, stopping at the composition root) so any wrapper is safe. The exporter works around it today by copying data-start/data-duration onto the wrapped element.

Method worth keeping. A DOM probe injected into a copy of the emitted project (rAF overlay drawn into the snapshot PNG, no CDP, no runtime patch) made the per-time paint counts observable under hyperframes snapshot.

Contribution brief — September 23, 2026

Confirmed behavior

Reproduced using the actual createRuntimeStartTimeResolver in Chrome 150.0.7871.24 at source fa4261bee (0.8.68), then rechecked against main 86fa10ced4297bfd9f4fe67b6767afae7a07fd3c (0.8.69): the resolver and its relevant dependencies are unchanged. For a host starting at 5 seconds and an untimed inner composition root:

Host marker Direct child One neutral wrapper Two neutral wrappers
data-composition-src 5 0 0
data-composition-id 5 0 0
data-composition-file 5 0 0

All cases should preserve the same host start. This reproduces the resolver defect; the complete AE export/snapshot/render path has not been rerun.

Minimal regression fixture

Add a test in the existing packages/core/src/runtime/startResolver.test.ts suite, where the resolver import, jsdom environment and cleanup already exist:

it("preserves the host start across a neutral wrapper", () => {
  document.body.innerHTML = `
    <div data-composition-id="root" data-start="0">
      <div data-composition-src="child.html" data-start="5">
        <section><div id="inner" data-composition-id="child"></div></section>
      </div>
    </div>`;
  const inner = document.getElementById("inner");
  if (!inner) throw new Error("Missing fixture root");
  const resolver = createRuntimeStartTimeResolver({});
  expect(resolver.resolveStartForElement(inner)).toBe(5);
});

The browser probe returns 0 for this shape, versus 5 when the section is removed. No media files or exporter are needed for this isolated regression. Expand the test to the full matrix rather than only covering one marker.

Accepted scope and starting points

In the no-authored-start branch of startResolver.ts, find the nearest enclosing composition host across neutral wrappers while preserving composition boundaries and existing timing semantics. Extend startResolver.test.ts.

This is medium work because host offsets, explicit timing, and boundary semantics interact. Keep the fix limited to host-start resolution; do not redesign VFX, playback clocks or media scheduling.

Acceptance checks
  • All nine combinations above resolve to 5; the six wrapper cases fail before the fix.
  • Stop at the nearest composition boundary; do not use an outer host or sibling clock.
  • Preserve explicit authored starts, named/anonymous hosts, reference expressions and unresolved fallbacks.
  • After following CONTRIBUTING.md, run bun run --cwd packages/core test src/runtime/startResolver.test.ts, then the relevant broader core/runtime tests. Use the package's Vitest runner, not bare bun test.
  • Exercise a mounted-composition snapshot/render regression before merge; unit success alone is not end-to-end proof. Include the fixture and observed timing in the PR.
  • Lint and format changed files under the repository guidelines.
Availability and related work

On September 23 there were no assignments, claim comments or directly linked implementation PRs. PR #3826 touches this resolver, but its inspected diff only adds resolveLocalStartForElement; it does not repair this ancestor walk. PR #4330 is adjacent VFX work. Recheck both before starting and coordinate any shared-file changes. Comment with the intended approach before beginning so a maintainer can coordinate ownership.

triage/ready describes this accepted, specified scope. Reviewer/mentor ownership is still being confirmed; this brief does not assign anyone or promise newcomer mentoring.

Dominant language
TypeScript
Stars
54.1k
Forks
4.9k
Avg merge
17h 15m
Merged PRs (30d)
737

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from heygen-com/hyperframes

All issues in heygen-com/hyperframes

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.