Repository navigation
fix(cli): timeline lists clips nested in a timed element and lint flags ones that never show - #5732
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
Edit accuracy: accurate 271 (base branch 271), smooth 154 of thoseThe gate passes. Quarantined, measured but not gated (0) |
jrusso1020
left a comment
There was a problem hiding this comment.
Requesting changes at ef13e87b. The timing and the lint rule are right, but the new nested rows now also feed the timeline edit commands. As a result, the very edit the new warning asks for is refused.
Blocking
-
Edits on a nested clip, or on its wrapper, collide with each other (
timeline/a2Shared.tsoverlapand the duplicate branch ofmutationConflict). Both checks compare against every row fromallRowsin the same file on the sametrackIndex, and wrapper children are now in that list. A child withoutdata-track-indexfalls to track 0, the same lane as a wrapper on track 0. With this PR's own fixture (#shot2at 5–10s on track 0, holding#lostat 0–2s and#seenat 6–8s):timeline move #lost 6, which is the fix the new warning suggests, is refused as "would overlap #shot2": the child collides with its own parent.timeline move #shot2 4is refused as "would overlap #seen". This worked onmain, where children weren't rows. The suggested fix, "move the named neighbour", then points at the wrapper's own child.timeline duplicate #seeninserts at 8, inside#shot2, so it's refused. The duplicate branch has no--overwritebypass.
Skipping ancestor and descendant rows (through
parentRow) in both checks would fix it, along with a move test on a nested clip. -
A sub-composition host inside a timed wrapper produces
children: [null](describeProject.tsflatten).add()recurses only intoclip.inside, and a top-level clip'schildrenare added only in the outer loop. A nested host's sub-composition clips are therefore never added, soat()returnsundefinedfor them, and--jsonlistsnullchildren pointing at rows that don't exist. Example:<div id="shot" data-start="0" data-duration="5"><div data-composition-src="scene.html" data-start="0" data-duration="5"></div></div>. Fix: haveadd()also walkclip.childrenwithhost = clip, or don't read sub-compositions for nested hosts.
Non-blocking
- Nested
<audio>gets the error, but it still plays. The runtime hides a nested element when its parent isn't showing (clipChainVisibleAt), but media playback uses only the clip's own window. A nested<audio>outside its parent's window is still heard. Lint says it "never appears", and Studio treats that as an error. Following the suggested fix would change when the audio plays. Excluding audio clips, or wording this for visual clips only, would avoid that. - Lint ignores
data-hf-media-start-basis="global". In a sub-composition, a legacy root-time mediadata-startis compared against a local parent window. The timeline gets this right throughresolveMediaStartSeconds. - In-point cuts stop at sub-compositions.
cutRowcuts the sub-composition row but passesinsidethrough unchanged. Wrapper children inside a host with an in-point keep their uncut times. - The text view hides nesting. Wrapper children have
nested: false, so the header counts them as top-level. The "no stable name" warning now prints on every unnamed nested row.kind/indexrefs also shift, which is worth a line in the release notes.
Checked and fine
- The body's timing claim holds. In
startResolver.tscomputeStart, a nested numericdata-startcounts from the composition, not from the wrapper. Visibility also needs every timed ancestor visible (clipChainVisibleAt), so "never visible when the windows don't overlap" is the right rule for what shows on screen. resolveRowTimingdescribes inner rows with the same scope and origin. The overlap test matches the runtime's half-open clip windows.- Both checks skip windows they can't resolve. A nested media clip with no
data-startdefaults to 0, which matches the compiler. isSubCompositionHostkeeps both checks from walking into hosts. The new lint rule is its own entry instructureRules.nested,hostandhostRowkeep their meaning, andparentRowis purely additive.
CI is the only run. Not armed or merged.
— Rames
|
Thanks, all addressed at Blocking
Non-blocking
Devbox: each new test fails on the parent commit; the CLI timeline suites (113) and lint (959) pass 3 runs in a row; tsc, the comment ratchet and |
jrusso1020
left a comment
There was a problem hiding this comment.
Approving at 071d68a8. Last time I requested changes at ef13e87b. Both blockers are fixed. The two pushes since fcc274f3 are behaviour-preserving: followsParentVisibility and isTimed replace the two inline guards with the same conditions, in the same order, and one test helper is inlined; 071d68a8 only undoes a stray reformat.
- Nested edits no longer collide with their own parent.
overlapand the duplicate branch ofmutationConflictnow skip rows in the same parent chain (sameLineage, walkingparentRow). The new e2e cases run on the PR's own fixture.move #lost 8succeeds, which is the move the warning suggests.move #shot2 4andduplicate #seenalso succeed. Sub-composition rows are in another file, so thefilecheck still keeps them apart. - A sub-composition host inside a wrapper lists its clips.
flatten'sadd()now walksclip.childrenwithhost = clipat every depth, so a nested host's clips become rows. The new test seesshot → [scene]andscene → [t1, t2], with nonullchildren.
My non-blocking notes are mostly covered too:
<audio>is now excluded, in both the lint rule and the CLI warning.- Lint skips
data-hf-media-start-basis="global". cutRownow carries the cut intoinside, and there's a test for a clip nested in a wrapper.- The header now counts wrapper children as nested.
- The text view prints only the never-visible warning, which also matches
main, where it printed no warnings at all.
kind/index refs still shift for projects with wrapped clips. That's worth a line in the release notes, but it doesn't block.
CI is the only run. Not armed or merged.
— Rames
What
hyperframes timelinenow shows clips nested inside another timed element, and lint reports a nested clip that can never be visible.Before, a project with timed "shot" wrappers holding timed
<video>clips showed only the wrappers, each withchildren: []. Every clip inside was missing from the timeline, so an agent reading it saw empty shots and re-added clips that were already there.There was a second problem behind it. A nested clip's
data-startcounts from the composition's start, not from its wrapper, and the clip only shows while the wrapper shows. Clips written with wrapper-relative times therefore never appear: in a 9-shot fixture, every clip after the first shot rendered black, and nothing said why.How
describeProject): a timed element that is not a sub-composition host now lists the timed elements inside it as rows, recursively, at their real playback time (the same start rule as the runtime).children, and each one points back to its wrapper through a newparentRowfield.nested,hostandhostRowkeep their sub-composition meaning. The edit commands use them to bound a sub-composition clip by its host's length, which would be wrong for a wrapper child, whose times are composition times.never visible: plays 0-2s, but #shot2 only shows 5-10s; a nested data-start counts from the composition, not from #shot2. The text view now prints a row's warnings; before, it dropped them.nested_clip_never_visiblein the structure rules. It is a warning in the CLI and an error in Studio, like its neighbours, and it runs in sub-composition files too. The existingvideo_nested_in_timed_elementandnested_structure_needs_subcompositionwarnings say the pattern is discouraged; this one names the clips that will never be seen.Verification
Tests that fail on main:
describeProject.test.ts"lists clips nested in a timed wrapper at their playback time and says when one never shows".structure.test.ts"flags a nested clip whose window misses its parent's" and "checks sub-composition files too". "leaves a nested clip that plays inside its parent's window" guards against false hits.The CLI timeline suites (108 tests) and the lint package (958 tests, including the catalog check that structure rules stay silent on every shipped registry item and skill example) pass 3 runs in a row.
CLI and lint
tscare clean, as are oxlint, oxfmt and the comment ratchet.Built CLI on a fixture of 9 timed shot wrappers holding 40 timed videos, with wrapper-relative starts:
timeline --jsonvideo rowslintnested_clip_never_visibleRelease notes:
timelinenow lists timed elements nested in other timed elements, sokind/indexrefs such asvideo/3can point at a different clip than before. Use#idrefs in scripts.