From d70f00f707593f767174fd6bebd759862175fcff Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Sat, 22 Aug 2026 11:59:52 -0400 Subject: [PATCH] docs: say one paused ROOT timeline, not "timelines must be paused" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `skills/hyperframes-core/SKILL.md` has always been right: "Each composition registers exactly one gsap.timeline({ paused: true })... Don't manually nest sub-timelines into the host." The four compressed copies dropped both halves and said only "GSAP timelines must be paused and registered on window.__timelines". Plural, with no cap and no warning against nesting. An author following that writes a paused timeline per scene and combines them, which is precisely the shape that renders black: a paused child never advances when the root is seeked, so every frame is the t=0 state, and lint, check and validate all pass because none looks at pixels. This is the drift the skill-catalog rule exists to prevent — a compressed copy asserting something the skill does not. The runtime now repairs this shape (#3427), so nobody is stuck. This closes the door on authoring it in the first place. Both template files kept byte-identical, as required. --- AGENTS.md | 2 +- CLAUDE.md | 2 +- packages/cli/src/templates/_shared/AGENTS.md | 6 +++++- packages/cli/src/templates/_shared/CLAUDE.md | 6 +++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6e2159ef13..584fd61149 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,7 +80,7 @@ skills/ → AI agent skill definitions - **Package manager**: bun (not pnpm, not npm for workspace operations) - **Commit format**: Conventional commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`) - **TypeScript**: Avoid `any` and `as T` assertions. Prefer type guards and narrowing. -- **Compositions**: HTML files with `data-*` attributes. Clips need `class="clip"`. GSAP timelines must be paused and registered on `window.__timelines`. +- **Compositions**: HTML files with `data-*` attributes. Clips need `class="clip"`. Each composition registers **exactly one** paused GSAP timeline on `window.__timelines`. Don't nest your own paused sub-timelines into it: a paused child never advances when the root is seeked, so the render comes out blank. - **Frame Adapters**: Animation runtimes plug in via the seek-by-frame adapter pattern. GSAP is the primary adapter. - **Deterministic rendering**: No `Date.now()`, no unseeded `Math.random()`, no render-time network fetches. diff --git a/CLAUDE.md b/CLAUDE.md index f46ed0d658..97beeb04a0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -111,7 +111,7 @@ skills/ → AI agent skill definitions - **Package manager**: bun (not pnpm, not npm for workspace operations) - **Commit format**: Conventional commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`) - **TypeScript**: Avoid `any` and `as T` assertions. Prefer type guards and narrowing. -- **Compositions**: HTML files with `data-*` attributes. Clips need `class="clip"`. GSAP timelines must be paused and registered on `window.__timelines`. +- **Compositions**: HTML files with `data-*` attributes. Clips need `class="clip"`. Each composition registers **exactly one** paused GSAP timeline on `window.__timelines`. Don't nest your own paused sub-timelines into it: a paused child never advances when the root is seeked, so the render comes out blank. - **Frame Adapters**: Animation runtimes plug in via the seek-by-frame adapter pattern. GSAP is the primary adapter. - **Deterministic rendering**: No `Date.now()`, no unseeded `Math.random()`, no render-time network fetches. diff --git a/packages/cli/src/templates/_shared/AGENTS.md b/packages/cli/src/templates/_shared/AGENTS.md index 31ae625c33..d7d3a2e69a 100644 --- a/packages/cli/src/templates/_shared/AGENTS.md +++ b/packages/cli/src/templates/_shared/AGENTS.md @@ -90,11 +90,15 @@ Fix all errors before presenting the result. Warnings should be reviewed before 1. Every timed element needs `data-start`, `data-duration`, and `data-track-index` 2. Elements with timing **MUST** have `class="clip"` — the framework uses this for visibility control -3. Timelines must be paused and registered on `window.__timelines`: +3. Register **exactly one** paused timeline per composition on `window.__timelines`: ```js window.__timelines = window.__timelines || {}; window.__timelines["composition-id"] = gsap.timeline({ paused: true }); ``` + Only that registered timeline is paused. Don't build scene timelines as + `gsap.timeline({ paused: true })` and `.add()` them into it — a paused child + never advances when the root is seeked, so every frame renders the t=0 state + and the video comes out blank with no warning from lint, check or validate. 4. Videos use `muted` with a separate `