Skip to content

Implement insert_asset_clip, the one timeline op that could not run - #12

Merged
dallasbpeters merged 1 commit into
mainfrom
rolemodel/insert-asset-clip
Aug 25, 2026
Merged

Implement insert_asset_clip, the one timeline op that could not run#12
dallasbpeters merged 1 commit into
mainfrom
rolemodel/insert-asset-clip

Conversation

@dallasbpeters

Copy link
Copy Markdown
Member

Every other timeline operation rearranges what is already there: trim narrows a
clip, duplicate_clip copies one, move_clip 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 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. insertClipAt is implemented and wired to
the 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 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 rather than keeping a 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.
  • 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.
  • It throws rather than doing nothing quietly — unknown asset, unknown
    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.

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>
@dallasbpeters
dallasbpeters merged commit 5b7d313 into main Aug 25, 2026
13 of 16 checks passed
@dallasbpeters
dallasbpeters deleted the rolemodel/insert-asset-clip branch August 25, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant