The competitive brief sales uses
A competitor analysis that arrives as an eight minute branded film instead of a slide library nobody opens. Claude researches the field, the positioning map draws itself, and every claim on screen is the competitor's own page.
Use /groundslate-competitive-brief-video with the competitive-brief skill from Claude's Marketing plugin. Analyse ropeworks.com and knotandco.com against Acme, at acme.com, which sells rope access safety training to industrial contractors. Brand it as Acme, eight minutes, for Acme's sales team. Bring me the style frames, then the draft.
Works with
- Claude, with the Marketing plugin's competitive-brief skill
- The agent this skill is written for. The research runs Claude's competitive-brief skill, shipped in the Marketing plugin: in Claude Code, open Plugins, Browse plugins, Marketing. Any competitive research skill already installed can stand in. Every competitor claim arrives through Claude; the captures are GroundSlate's own, rendered by WebKit on your Mac under a site policy only you can widen.
- 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.
The competitive brief is written once a quarter, filed, and never opened again. Sales keeps selling against a competitor's old tagline, leadership hears about the landscape secondhand, and the positioning gap found in week one is still unclaimed in week twelve. The same research as an eight minute film gets watched before the pitch, quoted in the deal review, and argued with.
This skill makes Claude the whole production. The competitive-brief skill from Claude's Marketing plugin does the research, Claude Design builds the scene system from your brand, and GroundSlate renders it deterministically, narrates it in three local voices, ducks the music under them and files the finished film.
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: https://claude.ai/design/p/2d05938a-0cd5-497d-b219-1341d2e2ac5e
The film shows competitors' own pages, taglines and marks, so it is internal enablement. Clear it before it goes anywhere a customer can see it.
Install it
Copy or download SKILL.md above.
For Claude Code, save it as ~/.claude/skills/groundslate-competitive-brief-video/SKILL.md.
For claude.ai and the Claude desktop app, put it in a folder named groundslate-competitive-brief-video, zip the folder, and upload it under Settings, Capabilities, Skills.
The research step wants the competitive brief skill beside it. Claude ships competitive-brief in its Marketing plugin: in Claude Code, open Plugins, Browse plugins, Marketing, and it runs as /competitive-brief. Or keep whichever competitive research skill you already use.
The skill
---
name: groundslate-competitive-brief-video
description: Turn a competitive analysis into a branded, narrated video. A competitive research skill (the competitive-brief skill from Claude's Marketing plugin, or whichever is installed) does the research, Claude Design builds the scene system from the brand, and GroundSlate renders every scene deterministically, speaks the narration in three local voices over ducked music beds, and files the finished film. Use when the user wants a competitor analysis, positioning comparison, battlecard or market briefing delivered as a video.
---
# The competitive brief, delivered as a film
You run the whole production. A competitive research skill is the
researcher: use the competitive-brief skill from Claude's Marketing plugin
when it is available, or whichever competitive research skill is installed.
Claude Design is the art department, GroundSlate is the render engine, the
voice and the library, and the user answers three questions at the start,
approves the look on two style frames, and reviews one draft at the end.
Between those moments, proceed on the defaults and your own judgement; ask
only when an answer would genuinely change the film, a competitor behind a
login, a brand font that cannot be found, a claim about a named company too
sharp to narrate unchecked.
## Three questions up front
1. The competitors, and the company they are measured against. Take that
company's positioning too if the user has one written; the brief is
sharper when it knows what you already claim.
2. The brand: a Claude Design brand kit, a brand skill you carry, a folder
of brand assets (logo, fonts, colours), or nothing, in which case you
derive a clean system from the company's own look. The brand may be the
company's or the agency briefing them; ask whose name goes on it, and
hold the logo file before you author a scene. When an agency is making
the film for a client, get both logos, the client's for the verdict and
the agency's for the close. Every competitor's logo is a separate
import, always shown as theirs and never restyled into your system.
The brand lives with you and Claude Design, never in GroundSlate;
GroundSlate keeps the mechanics (fonts in its font library, the logos
in its asset store, approved pages as named kits).
3. Who watches it: the sales team, leadership, or the board. Sales wants
the objection and the answer, leadership wants the opportunity and the
threat, and the board wants the shape of the market.
Everything else is defaulted, and stated once when you accept the job:
1920x1080 at 30fps, eight minutes, narrated by three distinct local
voices, music beds across the whole film ducked beneath every spoken line,
filed in a project named for the company and the quarter.
## 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 queue, voice_status, media policy).
- composition_doctor: the render path (Chromium, ffmpeg) proves itself now,
not at scene twelve. Run the printed fixes if it reports gaps.
- The brief itself is working material, and it is the expensive part. The
research, the claims table, the script and the per-scene briefs are not
media to bind and not a render to commit: write_project_file keeps them in
the project's working folder and read_project_file hands them back to a
later session, which is the difference between re-running an afternoon of
competitor research and picking up where it stopped. project_manifest is
the other half, before you plan the cut and again when a render cannot find
its footage: it copies nothing and names which drive is offline and how
many of this film's clips are on it.
- voice_status for the narration engine; relay its fix sentence verbatim if
weights are missing.
- Fonts: import_fonts on the brand's font folder once, list_fonts for the
families the library now resolves, then check_fonts on each page once it
is written. render_html refuses missing fonts rather than substituting, so
resolve them before authoring.
- Brand media: import_asset every logo the film carries, the company's and
each competitor's, plus any supplied imagery; get_asset resolves them to
paths at build time. Files must sit under a granted folder before import.
- The project: search_projects for one named for the company and the
quarter, and create_project (kind business) when it is not there. Hold
its prj_ id for delivery and pass it on everything that binds, not only
the final film; commit_to_library attaches to an existing project and
refuses an unknown one, so the binder exists before anything renders.
- The project is not just where the film lands, it is where everything the
film is made of and everything it makes lives. 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 quarter. Three doors, by
kind. Media pulled off the web binds as it arrives: pass project_id to
fetch_asset and it is a member in one call. Media you created during the
production, a cutout from remove_background, a frame you pulled from a
clip, binds in two: index_image makes it a catalog row and
add_media_to_project binds it, and that result carries `unresolved`, which
is non-empty when a reference matched nothing and was therefore never
added, so read it rather than assuming. Finished renders go through
commit_to_library with the project. Final outputs only there: a draft scene
render is throwaway and rebuilds from its own page, and committing thirty
of them buries the film they were drafts of.
- 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 project rather than membership of this one. A logo
can want both. Doing one is not doing the other.
## The research is yours; the pages are GroundSlate's
Run the competitive research skill (the Marketing plugin's
competitive-brief when available, otherwise the one installed) across
every competitor: website and pricing pages, recent announcements, content
and thought leadership, review site sentiment, analyst placement, hiring
signals. Record the date the research ran; the film says it at the close,
because a competitive claim is only true as of a day.
Harvest the field while you are there. Target at least sixty graphics
assets pulled from the pages of every competitor and the company itself,
homepage and pricing screenshots, hero shots, product photography, logos,
icons, textures, all saved under a granted folder. index_folder the
captures so they join the library, bind them to the project with
add_media_to_project, and import_asset the ones scenes will reference by
name, the logos and the background plates.
Two doors bring captures in, and which one you use depends on where the
file came from. A file that already exists on a competitor's site, a logo,
a press image, product photography, comes in through fetch_asset with its
URL and the project's id: it downloads, indexes, becomes a searchable clip
and joins the binder in one call, and the source receipt records where it
came from, which is exactly the provenance a claim about a rival needs. Never route a found file through
fetch_media, which is for media you generated at a provider and would
stamp a competitor's own photograph with a generator that never made it.
Screenshots you captured yourself are local files and go through
index_folder as before. GroundSlate signs in to nothing on its own; beyond
the URLs you hand it, everything from outside arrives through you.
Leave fetch_asset's `recognize` off, which is its default. A competitor's
news page is full of photographs of real people, and enrolling their
executives as identities in this profile's People catalog is not something
a brief should do on its way past. Fill in what you actually know on the
receipt, the page you found it on, what the page called it, the credit and
the licence, and leave the rest empty rather than inventing it.
The harvest is the film's art department, and it is spent, not stored.
Every asset you capture earns its way onto the screen: as the page behind
a claim, as the plate a background is built from, as a mark, an icon or a
texture. Every scene carries captured imagery; a flat panel or an invented
graphic standing in for a page you already have is the harvest wasted, and
it is what separates a film about the field from a film of it. Keep the
tally as you author, the asset, the scene it lands in and the moment it
appears, and account for it at the draft. An asset that never reaches the
screen is either placed or it was not worth capturing, and you say which.
## Distill: the brief already contains the film
The research skill returns more structure than a film can carry, so map
its output onto the picture rather than reading it out:
- The executive summary is the cold open: the landscape in a sentence, the
biggest opportunity, the biggest threat.
- Each competitor's narrative analysis, the villain they position against,
the hero of their story, the transformation they promise and the stakes
they set, is that competitor's movement. It is already a story; tell it
as one.
- The messaging comparison becomes a claim held against its proof, never a
matrix pasted on screen.
- The positioning map is the hero chart of the whole film.
- The content gap analysis is the argument for what to publish next.
- Opportunities and threats are two movements, and the threats one is
honest or the film is an advert.
- The recommended actions are the plan: quick wins separated from
strategic moves, because that split is what a viewer acts on.
## The film: a scene system, not a slideshow
Cold open with the landscape, the opportunity and the threat. One movement
per competitor. The positioning map. The gaps. At the midpoint the
opportunity returns, restated as the position nobody has claimed, timed to
a bed change so the film audibly turns toward the answer; eight minutes
needs a second hook. Threats. Quick wins as a rapid sequence. The plan. A
close that names the research date and the next review.
Have Claude Design build the scene system from the brand: a title scene, a
competitor scene carrying their mark and their page, a claim scene, chart
scenes, an evidence scene with a screenshot panel, a list scene.
Consistency of palette, type and logo treatment is what makes it read as
designed rather than generated; inside that system, vary everything else
so the film never settles:
- One statement per scene, set large. The scene's argument is a single short
line at a size you could read from the back of a room, and it is the only
thing on screen the viewer is asked to read. Cut it until it fits that
size; a line that will not cut is two scenes.
- The film never sets prose small. Small type is only ever verbatim
evidence: a filename, a tag, a heading lifted off the page, a column
pulled straight from the source. Evidence is looked at rather than read,
which is why it can be dense. Seven identical filenames stacked in
monospace make their point as a shape, before a word of it is read, so set
it aligned and repeating with the part that matters marked, and the
density becomes the argument. A sentence set small is the failure this
rule exists to stop, and a stack of them behind bullet points is a slide.
- If a line is worth saying but not worth setting large, the narration says
it and the screen stays quiet. Most small type on a scene is the voice's
job leaking onto the picture.
- Fill the frame. A layout that leaves half the frame empty is type set too
small, not a frame too big.
- Motion is how a thing arrives and leaves, never a state it lives in. Type
enters, settles, and is then completely still until it goes. Nothing
breathes, floats, bobs or drifts while a viewer is reading it.
- The layout is fixed before the first frame. Every element the scene 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 scene comes out feeling like it is drifting.
- One thing moves at a time, and it is whatever the narration is on. While
the statement lands, the evidence is still; while a row of evidence is
marked, the statement is still.
- 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.
- Composition varies between scenes, never inside one. A full-bleed word
here, a corner-anchored stat there, an oversized numeral bleeding off the
edge: that is one decision per scene, made before the first frame and
held, so no two neighbouring scenes compose the same and neither one
wanders.
- Imagery has many jobs and a blurred plate behind type is the weakest of
them. Every scene decides how its captures appear, and the treatments are
a vocabulary to spend rather than one move repeated: a competitor's page
as the subject, full frame and sharp, scrolling or pushing into the
tagline under discussion; a capture held in a browser or device frame,
angled and sliding; two rivals' pages side by side with the difference
between them visible; a grid of many captures at once where the repetition
is the finding; a detail crop magnified out of a page with the rest
ghosted around it; a product shot or a mark cut off its background and
composed into the frame; a capture revealed through the type, or the type
knocked out of it. The blurred plate is the fallback, not the default.
- Treat the captures rather than pasting them. list_effects is a catalog of
named looks for one clip, stocks, prints, glass, bloom and camera moves,
each row carrying its own knobs and its cost; apply_effect bakes the chosen
one onto a file. A capture graded into the deck's palette under a glass or
print treatment reads as photographed, and the same capture dropped in raw
reads as a screenshot in a deck, which is the thing this film exists to
stop being. Read the row before you pass a knob, because one that is not on
it is refused rather than ignored, and hold one look across the film rather
than spending a different treatment per competitor. The cutout is
remove_background: Apple's subject lift, on device and near instant, and it
writes 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, a video is refused rather than looped.
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, and an image with no
subject writes nothing rather than handing you an empty cutout. The edge
carries a soft halo at very large sizes, so a cutout is right for a
composite, a layout or an overlay and wrong for a silhouette held full
frame.
- Vary the treatment the way you vary the chart forms, and keep a record of
which scene used which. No treatment carries two scenes running, and a
film where every capture ended up behind the type as wallpaper has thrown
away the harvest even though every asset technically appeared.
- When the narration names a competitor, that competitor is on screen while
it is named, as itself: their page, their mark, their product shot, sharp
and legible and in the foreground. A viewer hearing about Puma should be
looking at Puma. A blurred texture of somebody's photography behind a line
of type is not that, and it is the difference between showing the field
and decorating a slide about it. Their imagery always reads as theirs and
is never restyled into your system.
- Type is still, pictures move. That is the whole motion rule stated once.
When a capture is the subject, the frame moves over it as a function of t,
a push into the detail, a scroll down the page, a pull back to reveal
where it sat, a rack from one crop to the next, and the type holds
perfectly still against it. When the claim is the subject, the type
arrives and the picture holds. A plate behind type drifts slowly, and that
slow ground under still type is what reads as expensive, while type doing
the drifting is what reads as a template.
- A scene whose ground is flat colour is a scene that ignored the capture
sitting in the asset store.
- Mix the chart forms, and let the shape of the analysis pick the form
rather than habit. The positioning map plots each competitor onto a two by
two as it is named and holds on the empty quadrant. The messaging
comparison animates one dimension at a time, each company's line arriving
as the voice reaches it. The content coverage grid fills cell by cell
until the hole is obvious. A share of voice figure is a pie or a donut
drawing itself round, or one huge counter. A ranking that changed is a
slope or a bump chart between two dates. A count is a waffle grid filling
in. A spread is a scatter. Where none of the standard forms fits the
finding, invent the graphic the finding needs; a bespoke picture of one
specific problem is the most memorable thing a film like this can carry,
and two bar charts in a row is the brief again.
- Build charts out of the harvest wherever the data has a face. Competitor
marks are the points on a positioning map, favicons are the units in a
count, real thumbnails are the cells of a coverage grid, and a page
screenshot is the thing a callout points at. A chart made of the actual
brands beats the same chart made of coloured rectangles, and it spends the
assets in the same move.
- Evidence scenes show the real page, and the page obeys the motion rules
too. Scenes are HTML, so the capture drifts, zooms to the headline or
scrolls the page as a function of t, and the mark draws itself on as the
claim is named. Quote a competitor's tagline by showing it where they
wrote it, never by retyping it into your own type system as though they
said it to you. A captured page is evidence, so its own text is not the
film's type and does not answer to the rules above. The framing carries
the load instead: hold it on the line that matters, so what a viewer reads
is the claim and not the whole page.
- Nothing stays on screen for more than ten seconds. The clock is per
element and it starts when that element appears, not when the scene does,
so a headline that arrived at t=2 is due at t=12 even though the scene
runs to twenty. Any element still there at ten, a chart, a screenshot, a
line of type, gets replaced, reframed or moved on, and a scene that has
nothing to change at ten seconds is two scenes.
- And nothing leaves before it can be read. A line of type stays up at
least as long as it takes to say it aloud, and nothing a viewer needs
exits mid-word. The ceiling keeps the film moving; this floor keeps it
legible.
Pace the film as a curve, not a metronome. The cold open is the fastest
sequence in the film, competitor movements get room to breathe, the quick
wins come rapid-fire, and no two adjacent scenes run the same length.
Scenes carry designed content only: the claim, the evidence, the words
being narrated. No numbering of any kind, no slide or scene numbers, no
"competitor two of three", no progress dots, no section labels, no footer
with the company name on every scene, no caption that names the chart it
sits over. That furniture is a deck labeling itself; this film's structure
lives in the narration and the design.
No em-dashes in anything the film sets. Not in a headline, a stat label, a
strap, a chart label or a card. A comma, a colon, or two lines, and most
lines that reach for a dash wanted to be two lines anyway. At headline 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. Verbatim evidence is the exception and is
never edited: a captured page, a quoted tagline or a line lifted off a
competitor keeps whatever punctuation its author used, because the moment
you tidy it, it stops being a quotation.
The film is an argument, so its data is honest. Every number the narration
speaks is the number the screen shows at that moment, and both trace back
to the research; a chart's scale never flatters or exaggerates a gap, and
a competitor's position on the map is defensible from what they publish.
The first inflated bar a viewer catches costs the whole argument. Anything
the research could not confirm is said as unconfirmed or left out, never
smoothed into a claim.
Every scene is a self-contained HTML page obeying the render contract:
window.__duration (or data-duration) set to the scene's planned length, and
window.__seek(t) that places the visual state exactly at time t. The picture
must be a pure function of the timeline: no clocks, no live randomness, no
fetches, data baked into the page. Charts draw as functions of t, so a
counter at t=3.0 shows the same digits on every render, and the kinetic
type obeys the same law: every entrance, settle and exit is computed from
t, never from a running animation clock. That determinism is what makes
drafts honest and re-renders safe.
## Three voices, cast by role
- Cast three voices from list_voices before writing a line, and give each
one a job the audience can follow: a lead who opens the film, holds your
side of the argument and lands the plan; a second who speaks the
competitors' own claims and taglines, so a quoted promise never sounds
like your verdict; a third for the threats and the vulnerabilities, the
voice that says the uncomfortable part. Audition with preview_voice; the
contrast between them should be audible inside one sentence.
- Budget the script before writing it. The local voices read at
documentary pace, roughly 140 to 180 words a minute, so eight minutes
holds around 1,100 to 1,300 words across the whole film. Weigh the
movements inside that budget; a script that ignores it is a twelve
minute film discovered after the narration is synthesized.
- Write the script scene by scene, 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 never reads the screen. The screen carries the claim; the
voice tells the story around it, who is winning which buyer and what
changes when you move, with the research as the proof: "Ropeworks has
said the same eleven words on their homepage for two years. Every deal
you lose to them is lost to a sentence you could answer." A spoken
number always matches the one on screen; a mismatch is a bug, in the
scene or in the script.
- Speak it with synthesize_speech at temperature 0, one file per scene in
that scene's voice.
- Then time the picture to the words. transcribe each narration file with
word timestamps and use them as the scene's cue sheet: the competitor
plots onto the map as it is named, the mark on the screenshot appears
when the claim is named, the next line of type waits for its words. Set
each scene's duration from the timestamps, the last word plus a breath,
then stretched to the bed's next cut point so the scene changes on the
music. This is where the ten second rule is won or lost: the words decide
the length, so a line of narration that runs sixteen seconds has just
bought a sixteen second scene, and that scene owes the viewer a change of
picture before ten. Plan the change into the cue sheet rather than
discovering it at the render.
- Fix the fit before you render. Too loose, dead air after a word while the
screen waits, trim the silence out of the file with render_ffmpeg and
re-transcribe. Too tight, a visual with no room to land before the next
line, rewrite the line shorter or give the scene the extra second. The
cue sheet is only done when nothing on screen leads or trails its words.
## The soundtrack is one mix
- Eight minutes is too long for one track, so the film carries four or
five music beds, each owning a stretch of it: one for the cold open, one
or two across the competitor movements, a faster one under the quick
wins, a closer for the plan. 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 supplies 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. Run audio_beats on each one before
timing a single scene and cut on its suggested cut points, the strongest
downbeats, never on every beat: scene changes, transition moves and the
type's biggest hits all land on the grid of whichever bed is under them.
Change beds at movement 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 alone hold the clock.
- Scenes render silent, so the soundtrack is one continuous mix: narration
laid at each scene's offset, each bed laid over its stretch and ducked
under every spoken line with mix_audio, restored in the gaps, the argv
run through render_ffmpeg, and the finished track handed to the join as
render_sequence's audio_path, one track laid across every seam.
- A transition overlaps its two scenes rather than adding time, so the film
runs shorter than the scenes do by the length of the moves. Take the total
off render_sequence with plan_only, which renders nothing, and build the
mix to that number rather than to the cue sheet.
## Render, join, deliver
- Style frames before the film. Render the cold open and one competitor
movement at draft and show them before authoring the rest: a wrong
direction costs two scenes, not thirty. 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
captured imagery in every layer. A scene
system that breaks those at the style frame breaks them thirty times over.
- Render every scene with render_html at draft while iterating: identical
frames and timing, only compression differs, so the draft is the honest
review copy.
- A run of scenes that shares a ground is one page, not several files joined
afterwards. author_film takes the scenes and the seams between them and
writes the whole self-contained page in one call: the stage, the positioned
scenes, the transition kit wiring and the seek contract. None of that is a
creative decision and every hand-written line of it can break the contract
in the way that renders cleanly and looks right until somebody counts the
frames. Its seams are the free ones, which makes it the natural home for a
competitor sequence; keep render_sequence for the joins between movements,
where a rendered move is the point.
- Join the scenes with render_sequence: the scene files in order, and one
transition entry per seam, N-1 of them or it refuses. Give the seams inside
a sequence "cut" and the movement boundaries a move that matches the film's
energy, so the moves keep meaning. One call encodes every frame once,
however many scenes there are, and quality is a tier there too, so join at
draft while the film is still moving.
- Stay in the light tier. Thirteen of the thirty-one moves are cost: light and
the other eighteen run a per-pixel kernel at five to thirty seconds a join,
paid again on every draft pass. The whole dynamic family is heavy, so spend
one at a couple of real boundaries rather than at every one, and read cost
off list_transitions rather than off a name. There is a second library that
runs inside the page and costs nothing to join, browsable with
list_transitions(engine="html") and vendored with
get_kit("transition kit"); a scene turn is free there and heavy here.
- Sample frames off the joined film and look at them before you call it done.
A path cannot show you a substituted typeface or a claim sitting under the
wrong competitor; a frame can.
- The full draft is the big checkpoint: show the user the draft film with
the script. Claims change wording here, competitors reorder here, and
nothing has been spent on final quality yet. Bring the accounting with
it: the assets that reached the screen and where, the ones that did not,
and any scene that had to set prose small, with what the narration could
have said instead. List the treatment and the graphic form each scene 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.
- On approval: re-render scenes at high, re-join at high with the mix as
audio_path,
commit_to_library into the project, name_video with the company and the
quarter, and confirm with list_project_outputs. What that list should show
is the whole body of work, the captures, the assets the production made
and the film, not one file with everything it was built from left loose in
Scratch Outputs.
- save_kit the approved scene pages as a kit under the company's
name, the competitor scene included: it is the battlecard layout, and a
new competitor next quarter is that kit plus their page. add_project_note a continuity note beside it: the three voice ids,
the beds, each competitor's position on the map and the research date.
Next quarter's brief is the same three questions rebuilt in the same
look and the same voices, with the map showing who moved.
## 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`. The AI
effects run on models the user installs in the app, Models then Effects;
until they are there `apply_ai_effect` answers `effect_not_ready`, so say so
and stay with the graded looks.
- 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 the research and renders run in the background (job_events), keep
building; never make the user wait on a progress bar you could have
worked through.
- Say what resolved and what did not after every batch step; unresolved and
found false are answers, and a competitor whose pricing is not public is
a finding rather than a gap to fill with a guess.
- End with where the film is, what it is called, the position nobody has
claimed, and the one competitor move worth watching, in one sentence
each.