Implement insert_asset_clip, the one timeline op that could not run - #12
Merged
Conversation
Every other operation rearranges what is already on the timeline: trim narrows a clip, duplicate copies one, move reorders them, drop_range cuts a span out. None of them can introduce footage. So an agent asked to put a sting on the front or cut to the B-roll had no operation that could do it — and the operation that was supposed to, `insert_asset_clip`, existed only as a line in the schema. It could be described, parsed, and then silently not performed. The recipe already existed twice over. useTimeline's drop handler inlined it (splice, resequence, rederive) while the comment on its own `moveClip` explains why that belongs in document/timeline.ts: two façades over one recipe is how the two drift into disagreeing about clip widths and anchored pills. So the pure `insertAssetClip` goes there, the op dispatcher calls it, and the drop handler now delegates to it rather than keeping its own copy. Details worth stating: - Neighbours, not an index. The schema names beforeClipId/afterClipId, which is the right contract for a model: "after the intro" survives the list changing under it and a number does not. `insertIndexFor` resolves the pair, preferring `before` as the more deliberate of the two. - It returns the new clip's id beside the document, unlike its neighbours here which return a bare one, because the caller needs it — the drop handler selects what it inserted and corrects its length when the duration probe lands. Stapling the id onto the document would put a field on it the schema does not have, and that document gets parsed, and saved. - An unprobed asset takes the placeholder duration, not zero: resequenceClips floors a clip at 0.001s, which is a clip you cannot see, select or drag. - The clip is marked `agent`. The timeline shows the origin, and "user" would make a model's proposal look like a cut somebody made on purpose. - An edit that cannot be performed throws instead of doing nothing quietly — unknown asset, unknown neighbour, empty source range. Doing nothing quietly is what this op did for its entire existence. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every other timeline operation rearranges what is already there:
trimnarrows aclip,
duplicate_clipcopies one,move_clipreorders them,drop_rangecuts aspan out. None of them can introduce footage. So an agent asked to put a sting on
the front or cut to the B-roll had no operation that could do it — and the one
that was supposed to,
insert_asset_clip, existed only as a line in the schema.It could be described, parsed, and then silently not performed.
Worth being precise, because I had this wrong myself at first: the editor's
drag-and-drop insert has always worked.
insertClipAtis implemented and wired tothe timeline's drop handler. It was the agent path that had nothing behind it.
Where it lives, and why
The recipe already existed twice over.
useTimeline's drop handler inlined it —splice, resequence, rederive — while the comment on its own
moveClipexplainswhy that belongs in
document/timeline.ts: two façades over one recipe is how thetwo drift into disagreeing about clip widths and anchored pills. So the pure
insertAssetClipgoes there, the op dispatcher calls it, and the drop handler nowdelegates rather than keeping a copy.
Details worth stating
beforeClipId/afterClipId,which is the right contract for a model: "after the intro" survives the list
changing under it and a number does not.
which return a bare one, because the caller needs it — the drop handler selects
what it inserted and corrects its length when the duration probe lands. Stapling
the id onto the document would put a field on it the schema does not have, and
that document gets parsed, and saved.
resequenceClipsfloors a clip at 0.001s, which is a clip you cannot see,select or drag.
agent. The timeline shows the origin, and "user" wouldmake a model's proposal look like a cut somebody made on purpose.
neighbour, empty source range. Doing nothing quietly is what this op did for its
entire existence.
Verification
305 tests pass across 18 files, six of them new. Checked against the real
schema: a sting inserted at the front pushes the interview to 4s; a trimmed
B-roll insert (source 40–50s of a 90s file) lands at the right place; the document
stays
documentSchema-valid throughout; all three refusals fire.