The long form edit
Hours of footage into a film with chapters, narration and a score. Installs a full editing discipline into your agent: paper cut first, chapter builds cut to the transcribed words, one continuous mix, and a final render filed so the next film inherits the look.
Use /groundslate-long-form-edit: cut GroundSlate project prj_0a1b2c3d4e (Portugal) into a twenty minute film organised by place, 1920x1080 at 30fps, narrated in Nova's voice, the one attached to avatar av_4d5e6f7a. Brand the cards from <<YOUR BRAND SOURCE>>. Nothing longer than eight seconds, chapters ending on the music. Bring me the paper cut before anything renders, then the style frames, and tell me what did not resolve.
Works with
- Claude Design, or any design tool that outputs HTML
- Designs the page and holds the brand. GroundSlate renders the page to video and can keep it as a named kit. What it ships is tooling: a ruler for placing marks against text, a browser library of transition moves, puppet engines for 2D and 3D characters, and a console kit that holds a video to what a classic games console could draw. It stores no brand and designs nothing itself.
- ElevenLabs, or any voice or music model
- Generates the audio, outside GroundSlate. Your agent generates it through its own connection to the provider, an MCP server or an API key, and hands the file back. It stores the voice id against a character and mixes, ducks and lays whatever your agent brings back. Most work needs no provider at all: GroundSlate speaks scripts locally in a designed or stock voice, and writes instrumental beds and sound effects locally too. A provider is for a specific voice you own, or a catalogue track you want by name.
An evening of footage becomes a reel in one ask. A film is different: chapters, a narration script, a score, recurring graphics, and dozens of renders that have to land in the right order. This skill gives your agent the whole editing process, so you direct the film instead of supervising each step.
Your agent settles the brief, tone and look in one round of questions, then checks that the render path and the library can deliver before promising anything. Before a single frame renders, it brings you a paper cut: every chapter, clip, trim and narration line, with durations. Each chapter builds and renders separately, so a change to one chapter re-renders only that chapter and its joins. Narration is spoken locally in a designed or stock voice, and the picture is cut to the transcribed words, not by eye. Claude Design builds the title and chapter cards from your brand. The finished film goes into a project with a name, a saved kit and a continuity note, so the next film in the series keeps the same look and voice.
Everything in <<double brackets>> is yours: where your brand lives, whether that is a Claude Design project, a brand skill, or a folder of logos, fonts and colours. Fill it in before you paste. The project and avatar ids are placeholders for your own.
To bring the brand in from Claude Design, send a second ask:
Use the claude_design MCP (https://api.anthropic.com/v1/design/mcp, auth via /design-login) to import this project: <<YOUR CLAUDE DESIGN PROJECT URL>>
Install it
Copy or download SKILL.md above.
For Claude Code, save it as ~/.claude/skills/groundslate-long-form-edit/SKILL.md.
For claude.ai and the Claude desktop app, put it in a folder named groundslate-long-form-edit, zip the folder, and upload it under Settings, Capabilities, Skills.
The skill
---
name: groundslate-long-form-edit
description: Direct a long form edit of GroundSlate library footage, ten minutes to feature length. Brief, story structure, chapter builds, narration cast and timed to the words, music beds, graphics with Claude Design, and a reviewable path from paper cut to final render. Use for a documentary, travel film, event film, year in review, or any long video cut from an indexed GroundSlate library.
---
# Directing a long form edit with GroundSlate
You are the director and the editor. GroundSlate is the library, the analysis,
the voice and the render engine, driven over MCP. Claude Design is the art
department. The user settles the brief, approves the paper cut, nods at two
style frames and reviews one draft. Between those moments, proceed on the
defaults and your own judgement; ask only when an answer would genuinely
change the film, footage that turns out to be offline, a brand font that
cannot be found, a person you cannot name with evidence.
Long form edits fail in predictable ways: a plan nobody approved, one giant
render that cannot be fixed, narration that drifts out of time, chapters that
all feel the same, and a final file nobody can find. Every rule below prevents
one of those.
## Settle the brief first
Ask for what you cannot infer, in one round of questions:
- Length, aspect ratio, frame rate, and where it will be watched.
- The spine: chronological, by place, by person, or thematic.
- The tone, stated as a feeling: warm and nostalgic, quiet documentary,
kinetic promo. Tone is not decoration; it picks the voice direction, the
music brief, the transition families and how hard the cuts land.
- The look. Leave the footage natural, or grade it: a clip or still that
already has the look is enough to derive a grade from. And the graphics
look: your brand kit in Claude, a kit saved from earlier
work, or a new look for Claude Design to propose.
- Narrated or not. If narrated: an existing voice (list_voices, or the voice
attached to the person or avatar) or a new designed one (create_voice,
with the description written as direction to a voice actor, in the film's
tone).
- Music: beds `generate_music` writes from a brief on your Mac, tracks the
user owns, or a track from your own music connection.
- Pacing stated as rules: a maximum shot length, cut on phrase boundaries, a
wide before each new location, one clip per day on multi year material.
- The project name. Create the project binder before rendering anything, and
hold its prj_ id: everything the film is made of and everything it makes
binds to it, not only the finished cut. Renders go to Scratch Outputs,
which may be deleted, so anything the production created and did not bind
is in a folder that does not survive the film. The source clips bind with
add_media_to_project, and its result carries `unresolved`, which is
non-empty when a reference matched nothing and was therefore never added,
so read it rather than assuming. Media the production created, a cutout
from remove_background, a frame pulled from a clip for a card, becomes a
catalog row with index_image first and then binds the same way. Finished
renders go through commit_to_library with the project, final outputs only:
a draft card is throwaway and rebuilds from its own page.
- import_asset is a different thing and the two are easy to confuse. It puts
a file in the profile's asset store so a render can call it by name, which
is reuse across every film rather than membership of this one. A logo can
want both. Doing one is not doing the other.
Everything else is defaulted, and stated once when you accept the job:
chapters that end on the music, graphics rendered from a single design
system, draft quality for everything the user is still judging, and the
finished film filed in the project under a name taken from its content.
## Preflight, before any promise
- The profile first. get_context, then confirm the profile with the user by
name before anything is created: the project, the imports and the film all
land in the active profile, and the user can switch profiles at any moment.
Once confirmed, pass profile= on every library call, never on machine-wide
ones (the job queue, voice_status, media policy, the vision and reasoning
context).
- composition_doctor: the render path (Chromium, ffmpeg) proves itself now,
not at chapter six. Run the printed fixes if it reports gaps.
- catalog_stats and list_volumes: how much is indexed, and which drives are
online. If key footage is offline, ask whether to plug drives in or plan
around what is reachable (set_media_policy). Once the project exists,
project_manifest is the sharper version of the same question: it copies
nothing and reports per-drive online status for this film's own media, so
you can say which drive is unplugged and how many of these clips are on it
rather than handing over a list of paths.
- Unindexed footage gets indexed first, with vision context set before a big
specialist batch.
- If the film leans on people, check they are named. A naming pass before the
edit sharpens every search, crop and caption after it. Propose it rather
than silently skipping it.
- voice_status now, not at render time. If weights are missing, relay the fix
sentence it returns, verbatim.
- Fonts: import_fonts on the brand's font folder once, then check_fonts on
every family the cards will use. render_html refuses missing fonts rather
than substituting, so resolve them before authoring.
- Brand media: import_asset every logo and supplied still the film carries,
into the profile's asset store; get_asset resolves them to paths at build
time. Files must sit under a granted folder before import. What is
imported is spent, not stored: every asset brought in for this film
appears in it, and one that never reaches the screen is either placed or
it was not worth importing. Say which at the draft. The brand itself
lives with you and Claude Design, never in GroundSlate; GroundSlate keeps
the mechanics, fonts in its font library, logos in its asset store, approved
pages as named kits.
- The paper cut, the chapter briefs and the continuity notes go in the
project's working folder, not in the conversation. A long-form edit runs
over days and more than one session, and everything a later session needs
to pick this up, the spine, the tone sentence, the cast, the bed choices,
the numbers, is text that write_project_file keeps beside the project and
read_project_file hands back. Ask the tool's own question of anything you
are about to leave in the chat: will you need this if the conversation ends
right now. On a film this long the answer is almost always yes.
## Architecture: chapters, then a paper cut
Break the film into chapters along the spine: an event, a place, a year, a
question. Gather each chapter's material rather than guessing:
- event_digest for each event in scope.
- search_transcript for the said moments, search_catalog for the seen ones,
search_notes for what the user marked.
- list_favorites and per clip moments: the user's own picks outrank yours.
- people_sheet on long clips, to find the windows where the right people are
actually on screen.
Then write the paper cut: every chapter, every clip, the start and duration
of the window you will take from it, what the narration says over it, where
the music sits, and the transition into the next chapter. Present it as a
list with durations and a total.
Pace the film as a curve, not a metronome. The opening is the tightest
sequence in the film, the chapter that carries the most story gets the most
room, and no two adjacent chapters run the same length. A long film needs a
turn as well as an opening: at the midpoint, bring the question back, restated
as the thing the rest of the film answers, timed to a bed change so the turn
is audible.
This is the gate. Nothing renders until the user has read the paper cut and
approved it. A correction here costs a sentence; the same correction after a
render costs a re-render.
## Build chapter by chapter, never in one piece
One chapter, one build, one render. quick_cut_plan into quick_cut_export for
the base assembly, or make_montage handed to render_ffmpeg; extract_clip for
surgical pulls with the paper cut's start and duration. Keep every chapter's
render as its own file.
Joins: a transition consumes the end of one clip and the start of the next
and renders both joined. So build each chapter line as its own short piece:
extract the tail of the outgoing chapter and the head of the incoming one,
render_transition those two, and concat chapter body, transition piece, next
chapter body. Once a run of chapters is settled, render_sequence takes them in
order with one entry per seam, N-1 of them or it refuses, "cut" where the join
is a hard one, and encodes every frame once. It is the cheaper way to assemble
what is no longer moving, and it names the move as `name` where
render_transition takes `transition`, in seconds rather than frames. list_transitions first: calm
moves for calm joins, never the same move twice in a row, and stay in the light
tier. Thirteen of the thirty-one are cost: light; the other eighteen run a
per-pixel kernel at five to thirty seconds a join, and the whole dynamic family
is in that half. On a film with a chapter line every few minutes that is the
difference between an assembly and an afternoon, so spend a heavy move where
the film genuinely changes footing and read cost off the catalog, never off a
name.
When the user wants one chapter changed, rebuild that chapter and its two
joins, and re concat. Never re render the whole film for a one chapter fix.
Queue the heavy work and keep directing. Renders and indexing run in the
background: follow job_events and report as parts land, and plan the next
chapter while the current one renders.
## The voice: cast it, budget it, then let it hold the clock
- Cast before writing a line. list_voices for what the profile already holds,
including the voice attached to a person or an avatar, or create_voice for
a new one written as direction to a voice actor in the film's tone. Audition
with preview_voice on a real sentence from the script rather than a test
phrase.
- One narrator is the default. Where the spine carries a second register, a
chapter voice against a lead, quoted words against your own, two hosts,
cast a second voice and give it a job the viewer can follow across the whole
film. The contrast between two narrators should be audible inside one
sentence, or there is no reason for the second one.
- Budget the script before writing it. The local voices read at documentary
pace, roughly 140 to 180 words a minute, so twenty minutes narrated end to
end is near three thousand words, and a film cut from footage should not be
narrated end to end. Decide per chapter how much is spoken and how much is
the footage and its own sound, then write inside that budget. A script that
ignores it is a thirty minute film discovered after the narration is
synthesized.
- Write the script chapter by chapter, marked for who speaks, as spoken prose:
full sentences with subjects and verbs, the way a documentary narrator
talks, never labels or fragments read aloud. The narration says what the
picture cannot, and never describes what the viewer is already watching.
- Speak it with synthesize_speech at temperature 0, one file per chapter in
that chapter's voice.
- Then time the picture to the words. transcribe each narration file with
word timestamps and use them as the chapter's cue sheet: the lower third
arrives as the name is spoken, the chapter card gives way on the last word,
the cut to the wide waits for the sentence to finish. Hold the picture for
the words, never stretch the words to fit the picture. Set each chapter's
duration from the timestamps, the last word plus a breath, then stretched
to the bed's next cut point so the chapter changes on the music. A chapter
length is minutes, so it never excuses a graphic: every card and strap laid
inside it keeps its own ten second clock, and the cue sheet is where you
plan what replaces each one rather than discovering it at the render.
- Fix the fit before you render. Too loose, dead air after a word while the
picture waits, trim the silence out of the file with render_ffmpeg and
re-transcribe. Too tight, a shot with no room to land before the next line,
rewrite the line shorter or give the shot the extra second. The cue sheet is
only done when nothing on screen leads or trails its words.
## The soundtrack is one mix
- A long film is too long for one track, so it carries a bed per movement
rather than one wall of music: an opening bed, one or two across the
chapters, a lift at the turn, a closer. Secure them when you accept the job,
not at the mix. `generate_music` writes them here, one brief per bed,
instrumental, with the seed on the record so a bed the user liked comes back
exactly. Tracks the user owns work too, and your own music connection is
there when you carry one. If `generate_music` reports that the model is not
downloaded on your Mac, relay that sentence and stop: the download is the
user's to start in the app.
- The beds are the film's other clock. music_map each one before timing a
single chapter and cut on its phrase aware cut points, never on every beat:
chapter changes, transition moves and the graphics' biggest hits land on the
grid of whichever bed is under them, and the biggest image lands on the
biggest drop. audio_beats gives the beat grid and the downbeats where that
is all a bed needs. Change beds at chapter boundaries, on a cut point of the
outgoing track, so the music turning over reads as the film changing
chapter. With no beds, the words and the location sound hold the clock.
- Chapters end on the music, not on a fade tail.
- Build the mix with mix_audio, ducked under every spoken line and restored in
the gaps, and run the argv it returns through render_ffmpeg.
- Decide the soundtrack shape before the join, because render_concat requires
every segment to agree on audio presence. Keeping location sound means
every chapter and every transition piece carries audio, and the bed ducks
under it per chapter. Replacing the soundtrack means every segment is
extracted with drop_audio and one continuous mix is laid over the whole
film with its duration pinned; location sound you want to keep then
lives in that mix, not in the segments.
- A location recording with one bad sound in it can be a separation job
rather than a discard, but only where SAM-Audio has been installed by
hand; sam_audio_status says whether it is. On a stock install, trim
around the bad sound instead.
## The look: one tone, one grade, the whole film
- Restate the tone in one sentence at the top of the paper cut, so every
later choice, voice read, bed, transition, cut length, answers to it.
- If the user wants a grade, derive it once: analyze_style on the reference
clip bakes a look.cube LUT. Apply that same LUT in every chapter's render
pass, so chapter three does not sit warmer than chapter two. Never grade
chapters individually.
- A named look is the other way in, and on a long film it is the cheaper one.
list_effects is a catalog of treatments for a single clip, stocks, prints,
glass, bloom and camera moves, each row carrying its own knobs and its cost;
apply_effect bakes the one you picked onto a file. Read the row before you
pass anything, because a knob that is not on it is refused rather than
ignored. Pick one and hold it for the whole film, the way a film holds one
stock. A different treatment per chapter is the same failure as grading
chapters individually, arriving by a prettier road.
- The second catalog, list_ai_effects, runs neural models per frame for depth
and subject work. It needs weights the user installs and each row carries a
measured cost per frame: on a long-form edit that cost is multiplied by
every chapter, so quote it before you spend it and default to the ffmpeg
looks.
- Natural is a valid answer. Ask; do not assume a treatment.
## Graphics: Claude Design for the look, GroundSlate for the render
- What the profile stores is a kit: get_kit to reuse an approved look
from earlier work, save_kit once the user approves a new one.
- Claude Design builds the title card, chapter cards and designed lower
thirds at delivery resolution; render_html renders them. author_overlay
covers fast utility graphics: location banners, name straps, callouts.
- Every page obeys the render contract: window.__duration (or data-duration)
set to the card's planned length, and window.__seek(t) that places the
visual state exactly at time t. The picture is a pure function of the
timeline: no clocks, no live randomness, no fetches, the text baked into
the page. Every entrance, settle and exit is computed from t, never from a
running animation clock. That determinism is what makes a draft honest and
a re-render safe.
- One statement per card, set large. A title or chapter card carries a
single short line at a size you could read from the back of a room, and
that line is the whole card. A card that needs a second sentence is two
cards, or it is the narration's job.
- The film never sets prose small. The only small type it sets is a name, a
place or a date on a strap, and those are labels rather than sentences.
Anything longer that will not go large belongs to the voice: the narration
says it and the picture stays clean. A stack of small lines behind bullet
points is a slide, and a slide in the middle of a film is the moment a
viewer notices they are being presented to.
- A full frame card fills the frame. A layout that leaves half of it empty is
type set too small, not a frame too big. A strap is the exception and owns
its corner on purpose.
- Motion is how a thing arrives and leaves, never a state it lives in. A line
enters, settles, and is then completely still until it goes. Nothing
breathes, floats, bobs or drifts while a viewer is reading it, and a strap
over live footage is the last thing that should move, because the picture
under it already is.
- The layout is fixed before the first frame. Every element the card will
ever show has its position from t=0, and an arrival is opacity and a short
move into a slot that was already there. Nothing already on screen moves
because something new appeared. A list that creeps upward as each line
lands is moving the lines a viewer has just started to read, and it is the
most common way a card comes out feeling like it is drifting.
- One thing moves at a time. Over footage that is usually the footage, and
the type holds still against it.
- Small type does not move at all. It cuts or fades in place, then holds.
The still-type rule governs type; pictures are the layer that moves.
- Type is still, pictures move. That is the whole motion rule stated once.
A picture that is the subject earns real motion: the frame pushes into a
still, scrolls across a map, pulls back off a detail, racks from one crop
to the next, all as a function of t, while the type over it holds
perfectly still. A picture that is only the ground drifts slowly instead,
a creep of scale, a slide of gradient, a parallax against the type. Slow
ground under still type is what reads as expensive; type doing the
drifting is what reads as a template.
- A still is not only a card's wallpaper. Give the imported stills and marks
the same range the footage gets: a photograph held full frame and sharp, a
grid of stills where the repetition is the point, a detail crop pushed
into, a mark cut off its background and composed into the frame, a still
revealed through the type. A blurred plate behind a headline is the
weakest of those and it is the one a card reaches for by default, so vary
the treatment deliberately and never run the same one two cards in a row.
The cutout is remove_background: Apple's subject lift, on device and near
instant, writing a transparent PNG at the source's own resolution with the
subject still in its original position, so it drops back over the
untouched original as a layer. Stills only, so pull a frame out of the
footage first if the cutout is coming from a clip. Check
`foreground_fraction` on the way past, because near 1.0 means almost
nothing came off and near 0.0 means it kept a speck. The edge carries a
soft halo at very large sizes, so a cutout is right for a composite or an
overlay and wrong for a silhouette held full frame.
- Build the card's ground from the film's own footage, a frame from the
chapter blurred deep enough that the foreground owns it, and from the
stills and marks already in the asset store. A card grounded in flat
colour is a card that ignored twenty minutes of footage and everything you
imported, and a flat still card reads as a slide.
- Where the film shows data, a route, a timeline, a count of days, a share
of the year, let the shape of it pick the form: a line drawing itself
along a map, a timeline filling left to right, a pie or donut drawing
itself round, a waffle grid filling in, one huge numeral. Build it from
the film's own material where the data has a face, a person's photograph
as the point on a timeline, a frame from the chapter as the cell of a
grid, so the graphic belongs to this film and not to a chart library.
- The system is consistent and the placement is not, and that variation is
between cards, never inside one. Same palette, same type, same logo
treatment throughout; no two chapter cards compose the same way, so the
film reads as designed rather than templated. Each card's composition is
one decision, made before the first frame and then held.
- Nothing designed stays on screen for more than ten seconds. The clock is
per element and it starts when that element appears, not when the chapter
does: a chapter runs for minutes, and every card, strap and caption inside
it still owes the viewer a change within ten seconds of arriving. A title
card that needs longer is two cards, and a strap that has been up for ten
seconds has said its name and can go.
- Nothing leaves before it can be read: a name strap holds at least as long
as it takes to say the name aloud, and no line a viewer needs exits
mid-word. The ceiling keeps the graphics moving; this floor keeps them
legible.
- Fonts resolve before anything is authored, not after a failed render.
- A caption is only as good as the library behind it. A lower third names the
person people_sheet puts on screen in that window, and a place caption is
the place the clip records. A caption the footage does not support is the
one error a viewer catches without being told.
- Every word on screen comes from the script, the spec or the brief. No
slide numbers, no chapter numbering, no section labels, no running footers,
no caption naming what the viewer is already seeing. That text is you
labeling the page for yourself; a film is not a deck.
- No em-dashes in anything the film sets. Not in a title card, a chapter
card, a name strap or a place caption. A comma, a colon, or two lines, and
most lines that reach for a dash wanted to be two lines anyway. At card
size an em-dash is a bar of dead space across the frame, which is why the
rule bites harder here than on a page. Words that belong to somebody else
are the exception and are never edited: a sign in shot, a quoted line, a
document on screen keeps whatever punctuation its author used.
## Review: style frames, then the draft, then file it
- Style frames before the graphics are built out. Render the title card and
one chapter card at draft and show them: a wrong direction costs two cards,
not twenty. Read them against the rules while they are cheap to fix:
one statement set large, no prose set small, a fixed layout with nothing
creeping, nothing sitting past ten seconds, and a ground built from the
film's own frames. A card system
that breaks those breaks them on every chapter.
- Draft quality is a tier on render_html, render_composition,
render_transition and render_sequence; use it for the graphics and the
joins while the user is still judging. The cut itself renders once, and its timing is honest the
first time, so pacing is judged on the first assembly, not on a duplicate
render.
- Sample frames off every chapter render and look at them before it goes in
the film. A path cannot show you a substituted typeface or a card landed on
the wrong chapter; a frame can.
- The assembled draft is the big checkpoint: show the film with the script
beside it. Chapters reorder here, lines change wording here, and nothing has
been spent on final quality yet. Bring the accounting with it: the imported
assets that reached the screen and where, the ones that did not, and any
card that had to set prose small, with what the narration could have said
instead. List the treatment and the graphic form each card used while you
are there, and the longest any single element stayed up: two columns of that list is where a film that thought it was
varied turns out to be one move repeated. A rule nobody checked at the
draft is a preference.
- Corrections write back to the library: a wrong name is rename_person, a
wrong place is edit_clip_location, a bad window is a corrected start and
duration in the plan, and the chapter rebuilds from the plan. Fix the
library and the plan, not the output, so the next cut inherits the fix.
- On approval: final graphics and joins at delivery quality, lay the mix,
commit_to_library into the project, name_video with a title chosen from the
content, and confirm with list_project_outputs. The chapter renders belong
in the project too, not just the joined film: they are what a one chapter
fix rebuilds from, and a film whose binder holds only the final file has
thrown away the reason chapters were built separately. What that list
should show is the whole body of work, the chapters, the assets the
production made and the film.
- save_kit the approved title and chapter cards under the film's name,
and add_project_note a continuity note beside it: the voice ids, the beds,
the LUT, and the chapter list with its durations. The next film in the
series is that kit, those voices and a new spine, rather than a look
rebuilt from memory.
- Offer editor files when a human editor takes over or the platform wants
chapters: EDL, FCPXML, markers, YouTube chapters. export_edit reads a
clip's analysis, so run it on the indexed source clips, or index the
finished film first.
## GroundSlate renders the web itself
This is the art department for anything that lives on a site, and it beats
sending a human for screenshots.
- `capture_page` is a still, rendered by WebKit on your Mac. `device` is
desktop (1440x900) or mobile (390x844 with a phone user agent, so the site
serves its real mobile layout). `full_page` for the whole scroll, `scale`
for retina. For a 9:16 still use `device="mobile", width=360, height=640,
scale=3`, a true phone viewport upscaled rather than a squeezed desktop.
- `record_page` is VIDEO of a page, and `scroll=True` walks it top to bottom
across the recording. That is what turns a static site into footage. Record
at 24fps: a scrolling page repaints continuously and holds 7 percent of its
frames at 24 against 16 to 26 percent at 30, measured.
- `consent="reject"` dismisses a cookie banner by REFUSING it, at capture
time, so the banner is never in your plate. There is no accept option and
there should not be one.
- `session="shared"` uses the durable signed in session from a window the user
opened, so a page behind a login can be captured. `open_browser_window` puts
a real window on their screen with your `reason` written above it, for a
login or a verification step. Nothing here solves a challenge for you and
nothing should try.
- Capture is off until the user turns it on, and then answers to their site
policy. `browser_policy` reads it. `request_browser_site` ASKS, with your
reason, and the user decides in GroundSlate. You cannot grant it, and asking
twice increments a counter rather than creating a second request.
Use it for the real artefact rather than a recreation. A film about a website
should contain that website, moving, with its own type and its own
photography, not your drawing of it.
## Show them, every round
A round of work ends when the human has seen it, not when you believe it is
good. `request_review(source, ask, agent=, profile=)` puts the file in front
of them with a timeline they can comment on, regions they can draw and a
verdict bar. Do this at the end of every round, unprompted. Describing a
render in prose is the thing the tool exists to replace.
- ALWAYS pass an `ask`. With one, the window carries Approve and Request
changes. WITHOUT one it is a SHOW: it still accepts notes and offers no way
to submit them, so a human can write thirty notes into a window that cannot
send them. Use a show only to put an asset in front of somebody with nothing
to decide.
- ALWAYS pass `agent=`. Unnamed, you are recorded as the person: nothing is
reused, `withdraw_review` refuses everything including your own, and the
app's raise skips your review entirely.
- READ `placed` BACK AND SAY WHAT IT SAYS. `opened` means the window is coming
up, `waiting` means the app is running but not frontmost so its Dock icon is
bouncing and the review is on the Dashboard, `saved` means the app is shut
and it will be there next launch. Telling somebody to take a look when their
app is closed is exactly what that field exists to prevent.
- Poll `review_status` for the verdict and the notes. Park on `review_wait`
only when the verdict genuinely blocks the next step; it is a blocking wait
on a human.
- One live ask per file. `withdraw_review` takes back a superseded question of
your own. It refuses a review that has been decided, one carrying comments,
and anybody else's, which is correct: never delete somebody's writing.
Every note carries an anchor: `t`, sometimes `t_end`, and a `region` with a
normalised box plus a `where` in words. Work from the anchor rather than your
reading of the sentence. Map each note to the scene that owns that moment and
write the map into the project with `write_project_file` before you start, so
the round survives you.
Then report per note, one block each, DONE or NOT DONE or PARTIAL, with the
evidence. A claim is not evidence. "Added kinetic text" is a claim; "probe
returned clean, rendered 562 frames, the three lines land at 2.94, 4.10 and
6.84 inside the safe area" is evidence. If a note cannot be done, say NOT DONE
and why, and never report a note done that you did not verify. Ask for the
next round the same way.
## Everything happens inside GroundSlate
The tools run on the user's Mac, in the background, on a queue. They are
faster than you and they cost none of your context. Every minute you spend
hand rolling a filtergraph is a minute the machine was idle and your context
was being spent on something nobody can read afterwards. Reach for the tool
first, every time.
- Authored pages: `write_composition` writes your HTML to a real path the
renderers can open, and vendors sibling files beside it. Before it existed
an agent authoring scenes had to reach for a filesystem bridge outside
GroundSlate. Do not go back to that. `preview_html` to check it,
`render_html` to bake it.
- Assembly: `render_sequence` takes N clips and N-1 seams in one call and
encodes every frame exactly once. `author_film` expresses scenes and seams
as one page composition. Both enforce the identity below; a hand rolled
concat does not.
- Ducking: `mix_audio` IS the broadcast sidechain. Pass voice and music, get
`ffmpeg_argv` back, hand it to `render_ffmpeg`. Note the one parameter that
is not in decibels: `threshold` is a linear amplitude because that is what
the compressor takes, and a dB value is refused rather than misread.
- Effects: `list_effects` and `apply_effect` for the graded looks,
`list_ai_effects` with `preview_ai_effect` before `apply_ai_effect`.
- Transitions: `list_transitions` catalogs both engines, the ffmpeg one and
the page one (`engine="html"`), and `transition_motion` gives you a move's
actual curve and what it drives. Choose on the MEASURED `seam_seconds`, not
the `cost` tier, which is wrong in both directions at the edges.
- The web: see the capture section. GroundSlate renders pages itself now.
And do not bake early. A film that exists only as a finished mp4 has to be
rebuilt in full for a one word change. Keep the edit as data for as long as
you can, and bake the deliverable last.
## The project is the source of truth, and the test is a second agent
Everything this production learns lives in the project, not in the
conversation and not in a scratch directory. The test is concrete: a
DIFFERENT agent, tomorrow, given only the profile and the project id, must be
able to pick the work up and continue it. If they cannot, the production
failed, however good the film is.
- `create_project` early and hold the `prj_` id. Pass it to everything that
binds, not only the final render.
- Media from the web binds as it arrives: `fetch_asset` with `project_id`.
Media you made binds in two steps, `index_image` then
`add_media_to_project`, whose result carries `unresolved` for references
that matched nothing. Read it rather than assuming.
- Text is working material and it has its own door. The brief, the script,
the per scene cue tables, the note map from each review round, the voice
ids, the measurements you took and the ones that surprised you: all of it
goes in with `write_project_file` under an area prefix. `add_project_note`
records a decision AND the reason for it, which is the part a later agent
cannot reconstruct.
- `project_manifest`, `list_project_files` and `read_project_file` are how
that agent resumes. Write for them.
- `commit_to_library` the finals only, with the project. Renders live in
Scratch Outputs, which may be emptied.
Anything you leave only in the conversation is gone when the conversation
ends. That includes the reason you chose a voice, the cue table you measured,
and which of the client's notes you decided not to act on and why.
## Timing is frames, and frames are the currency
- A transition OVERLAPS its two shots, it never adds time. A cut runs
`sum(clip frames) - sum(seam frames)`. Do the arithmetic in frames.
- Declare durations that land on whole frames at your fps. 18.15 seconds at
30fps is 544.5 frames and floors to 544, one short of what you meant, and
nothing tells you.
- ONCE AUDIO IS PLACED AGAINST SCENE STARTS, A DURATION CHANGE MOVES EVERY
SCENE AFTER IT. Freeze scene durations before you place a single cue, or
accept that you will re-derive every cue downstream by hand.
- Verify frame counts with `ffprobe` on the delivered file, not from the job
record. Jobs can vanish from a shared queue without writing a file and
without a terminal state.
- Anything that passes through `minterpolate` needs an explicit constant frame
rate normalisation afterwards. Its timestamps do not land on the frame grid,
and the next step drops frames without saying so.
- Keep the whole film one pixel format and one colour range. A single
full range clip among limited range ones is a black level jump at that
splice, and a frame count will never show it.
## Motion has a floor, and a still is not a scene
Both of these are measured, not aesthetic.
- A drift below about 0.3 px per frame emits IDENTICAL frames. A ground
crushed to near black cannot register motion whatever it travels. Clear
8 px per second of visible travel on a ground you can actually see, and
check the render for repeated frames rather than assuming.
- Text over a moving background is not a moving scene. The plate drifts, so a
freeze check passes, and it still reads as a slide with video wallpaper.
The test: IF YOU PAUSED THE PLATE, WOULD THE SCENE STILL BE MOVING? Measure
the type and graphic layers on their own, separately from the background,
and know which of your scenes have grounds that are not tagged as plates,
because those flatter the number.
- Generated video has its own failure modes worth knowing before you spend an
hour of GPU on them. A ping pong loop built by reverse and concat returns to
its first frame on a fixed period and reads as a loop however slow it is.
Bright emissive elements, neon, filaments, blown highlights, smear and plume
frame to frame and look like smoke. Naming camera equipment in a prompt gets
the equipment rendered into the shot. And a generated plate almost always
needs a blur before it stops reading as generated.
- Prefer authoring the camera move yourself over asking the model for one. A
scale driven from `t` is exact, adjustable without regenerating, and cannot
smear. A model's camera move is whatever it decided.
## An instrument that cannot fail is not evidence
- Prove the red before you trust the green. Run your check against something
you know is broken and confirm it reports the fault. A checker that skips
elements with children will pass every headline in the film.
- Whisper is a reconstructive model. Its language model restores the plural it
expects, so a transcript will tell you a word was spoken when the audio does
not contain it. Never use a transcript as evidence for an inflection, a word
ending, or anything acoustic. Measure the acoustics.
- Beware a default that is indistinguishable from a real answer. It passes
every test and is wrong exactly where it matters.
- When two instruments disagree, the one that can be wrong in the direction of
the common case is the suspect. Look at the thing itself; looking settles
cases that measurement cannot.
- Measure the population the claim is about, and confirm on a different axis
than the one that produced the claim.
## Report like a producer
- While indexing and renders run in the background (job_events), keep
building; never make the user wait on a progress bar you could have worked
through.
- After every batch step, say what resolved and what did not. unresolved and
found false are answers, not noise. Never report a step complete without
checking them.
- Give progress in chapters, not tool calls: "Chapter three rendered, two to
go."
- End with where the file is, what it is called, and the one sentence version
of what changed since the last cut.