The job graph
Jobs, nodes, edges, fingerprints, staleness, approvals, and the planner that grows a video's graph.
A job is a graph of nodes, run like a build system, that the planner grows as the video takes shape.
Jobs
A job is one thing rapid makes: a video, an empty job for nodes added over the API (rapid new), or one command run through a lane (rapid lane). It has a title, a brief, a project folder, a style and format, an error when its plan failed, and a state:
| Job state | When |
|---|---|
running | something is queued or running, or still waiting |
needs_you | any node waits on you |
done | every node is done |
failed | a node failed and nothing else can move |
cancelled | you cancelled it |
Nodes
A node is one unit of work with its own output. Each has a type, a lane, a label, a group (the scene it belongs to), the nodes it needs, its outputs, its state, its attempt count, its timings, and a spec saying what to run.
| Type | What it does |
|---|---|
storyboard | an agent writes storyboard.json |
scene | an agent builds or revises scenes/<id>.html, or builds its key frame |
render | renders a scene to MP4 with its boxes and cues |
check | the code checks, a contact sheet, a micro strip, a key-frame still, or the cut's sheet (rapid video-sheet) |
review | an agent reviews a key frame or a round into marks, or the director judges the storyboard or the video |
approval | waits for you |
listen | hears the video's track and writes its map (rapid listen) |
blender | renders a shot's key stills, a chunk of its frames, or its clips (rapid shot) |
mix | mixes the video's sound from the cues, over the track when there is one |
mux | joins the scenes, or puts the mix under the picture |
phone | makes the phone copy |
scan, extract, custom | other work; custom is what rapid lane runs |
A node is either a process node, which runs a command in its lane, or an agent node, which runs a prompt as a Claude Agent SDK session in the project folder, with the plugin's agent types and skills, a limited set of tools, and no permission prompts.
| Node state | Means |
|---|---|
waiting | some node it needs isn't done |
queued | ready, waiting for a slot in its lane |
running | in a slot |
done | made its outputs |
failed | its command or session failed; the error is on the node |
stale | something upstream changed; it will run again |
needs_you | an approval, waiting for you |
cancelled | its job was cancelled |
Edges
Edges are data: a node runs once every node it needs is done. The planner names a node's needs as it adds it, and the graph draws them as edges.
Fingerprints and staleness
A node's fingerprint is a hash of what its output depends on: its type and spec, what each node it reads made, and the engine version. A done node whose fingerprint still matches keeps its output and isn't run again.
When a node finishes with outputs that differ from what it made before, everything downstream of it goes stale. When a stale node's needs are done again, it goes back to done if its fingerprint still matches, and otherwise runs again. So when one scene's render changes, that scene's checks, sheet, and review run again, then the video's last steps, and nothing else.
A fingerprint covers a node's spec and its inputs' outputs, not the files a command reads by itself. After you edit scenes/<id>.html by hand, rapid redo that scene's render node; what depends on it follows.
A node that makes no files (an approval, a check that only passes) hands on its own fingerprint, so a change upstream of it still reaches what comes after.
Approvals
An approval node does no work. When its needs are done it goes to needs_you, and the job with it. rapid approve <node> (or Approve in the pane) completes it, and what waits on it moves on.
Retries
A node that fails for a transient reason (a network error, or an overloaded or rate-limited service) is tried again in the same run, after 5 s and then after 15 s, and each retry is logged as it happens. Any other error fails the node at once.
Redo
rapid redo <node> [--note <text>] runs a node again whatever its fingerprint says. The note is added to the node's spec, and an agent node reads every note in its prompt under "Notes on the last attempt". Whatever was waiting on the old outputs waits again; a cancelled branch comes back with it. A running node can't be redone.
Cancel
rapid cancel <job> stops the job's running nodes and marks it cancelled. A done job can't be cancelled.
The planner grows the graph
A video job starts small. The planner reads the project's files and the graph, and adds whatever comes next. It runs whenever a node in a video job finishes, and once for every running video job when the daemon starts, so a restarted daemon picks up where it was. Adding a node twice does nothing.
a look to finish finish (agent) → style check → [finish again with its reasons …] → pin in rapid.lock
a track listen, before the storyboard
no storyboard.json storyboard (agent) → [direct (agent) → revise (agent) → direct …] → approve the storyboard
per Blender shot stills → review (agent) → [revise the recipe → stills …] → frames → clips
per scene, key frame key (agent) → still → checks → review (agent) or approve (person)
per scene, round n [build (agent)] → render → check, sheet, micro → [review (agent)]
a round that fails round n + 1 builds from the review's marks, until the rounds run out
out of rounds an approval: accept the scene as it is, or redo it
every scene accepted join → [video sheet → direct (agent)] → mix → mux → phone
the video sent back the scenes the director names get a round more, then join again
In detail:
- The look. A video made in a look (
--look,lookinCreateFilm) starts with it:finish the look t<n>(agentrapid-extractor, lanethink) finishes the draft without a person (a face that isn't installed gets a stand-in, noted intaste.md), thencheck the look t<n>(rapid style check --write --out .rapid/look-<k>-t<n>.checks.json). A check that fails sends its reasons to another finish, three tries in all; then the job fails with them. A check that passes is followed bypin the look(rapid style use --look), and nothing else is planned until it is pinned. A lookrapid.lockalready pins as it is (a replan, or a later video in the same look) is not finished again; one that changed since its pin is, under keys of its own. - The storyboard. If
storyboard.jsonis missing, astoryboardnode (agentrapid-storyboarder, lanethink) writes it, and an approval follows. Nothing else is planned until you approve it. - The track. A video with
--music(musicinCreateFilm) starts withhear the track(alistennode, lanecpu), which writes the map the storyboarder reads. With no director, a storyboard that misses the beat goes back once to be cut to it. See music. - Directing the storyboard. With
--review agentand--director agent(the defaults), adirect the storyboard d<n>node (agentrapid-director, lanethink) judges the plan first and writesreviews/storyboard-d<n>.json, a Direction: the hook, the rhythm, each scene's move, camera, and secondary motion, variation, the redesign of every source section, and generated visuals where photos are thin. Onrevise, astoryboard v<n+1>node has the storyboarder answer its notes, and the director looks again, three looks in all. Code sends the plan back too, whatever the director said, while a scene names no primary move, camera, layout slot, scale, or transition out, has nothing alive while it holds, or shares its layout, primary move, or camera move with the scene before it; and while the plan is thin: a scene with no picture and no generated visual (a ground behind more than a third of the scenes doesn't count) that isn't the video's onebreath, fewer than half the scenes with a visual where photos and clips are fewer than half the scenes, a screenshot of the source shown as it is, a scene showing the source's interface that noredesignnames, or a key frame that doesn't say what fills its lower half (key.lower). The approval waits on the last look; with--stops nonethere is no approval, and the scenes wait on the last look instead. - Shots. Each shot in the storyboard's
shotsrenders once the storyboard is settled: stills in thegpulane, a review of them, a revised recipe if it's sent back (two tries), its frames in chunks, then its clips. A scene that shows a shot isn't planned until the shot settles, and is built once its clips exist. See Blender shots. - Key frames. With
--keys agent(the default), a scene built fresh first gets akeynode (agentrapid-builder) that writes the scene with its hero complete atmeta.keyand no motion, then astillnode (rapid still --key, writingrenders/<id>/key-k<n>.png), then achecknode (rapid check --still, writingrenders/<id>/key-k<n>.checks.json, every scene but the storyboard's onebreathheld to 40% empty field whatever its meta'sroomsays), then areviewnode (agentrapid-reviewer, writingreviews/<id>-k<n>.json), which must answer the checks' marks and read the frame into itsframebefore its verdict.passlets the scene move, unless the checks hold a blocker or major or the review never read the frame: then it is arevise;revisemakes another try, which builds from the review's marks, three tries in all; a third revise, orneeds_you, adds an approval to accept the frame. With--keys person, an approval on the still replaces the review. With--keys off, or--review noneunderagent, there are no key frames. The first motion build waits for the key frame and is told to keep it. - Builds. A scene is built (agent
rapid-builder) on round 1 only when its file is missing, you passed--rebuild, or a key frame was built (the motion is still to build), and on every later round. - Render, check, sheet, micro. Process nodes in the
weblane:rapid render, thenrapid check,rapid sheet, and (with agent review)rapid sheet --micro, a strip of frames 0.3 s either side of the key and of every mark the review must answer, side by side. - Review. With
--review agent, areviewnode (agentrapid-reviewer, lanethink) reads the sheet, the micro strip, the checks, and the previous scene's sheet and writesreviews/<id>-r<n>.json. Its verdict decides:passaccepts the scene;revisestarts round n + 1 while rounds remain (4 by default);needs_you, orreviseon the last round, adds an approval. A review must list every earlier mark it was handed (the last round's, the key frame review's, or the director's) inanswers; a pass that leaves onecarried, or leaves one out, counts as a revise. With--review none, a scene whose checks pass is accepted, and one whose checks fail goes straight to an approval. - The video. Once every scene is accepted:
join the scenes, drawing each hand-off with the transition the storyboard names (out: a cut, or one of the named moves, from a dissolve to a glyph swallow, drawn frame by frame in Chrome from both scenes and overlapping them by its duration). Then, with the director, avideo sheet d<n>node (rapid video-sheet,renders/video-d<n>.sheet.png: every scene's first, key, and last frames and each hand-off as a pair) and adirect the video d<n>node writingreviews/video-r<n>.json. Its notes name scenes: each scene arevisenames gets one more round (built from the notes, its review answering them), the video joins again, and the director looks again, two looks in all; after the last look's notes are built, the video goes on without another. A person's note after the video (rapid revise,revise_video) or a replan starts the looks afresh, filed asreviews/video-v<n>-r<d>.jsonorreviews/video-p<n>-r<d>.json. A scene that doesn't converge in a round the director asked for takes its best round like any other, with no stops. Thenmix the sound(each scene's cues where its picture starts, overlaps included),the video(the mux), andthe phone copy. - Stops.
--stops(stopsinCreateFilm) says which approvals wait for you:all(the default forrapid videoand the API),storyboard, ornone(the default fornew_video). Without a stop, the storyboard goes straight on, and a key frame or a scene that would ask for you takes its best try or round instead: the least-bad verdict (pass, thenrevise, thenneeds_you), then the lightest marks (a blocker outweighs any number of nits), the later one on a tie. Its scene file, kept per try (renders/<id>/key-k<n>.html,renders/<id>/r<n>.html), is put back. Each choice is recorded in.rapid/film-<job>.choices.json, andvideo_statusandrapid jobname them.--keys personstill asks for each key frame.
Keys, joins, and retired nodes
A scene's nodes are keyed by a hash of its storyboard entry. When an entry changes, the scene builds again from its key frame, and the builder is told why. The video's join, mix, mux, and phone copy are keyed by the renders they join, so a scene that passes a late round joins the video again. A node the plan no longer wants (a gate for a round that was redone, or a scene a new storyboard dropped) is retired: it is cancelled and does not count against the job.
rapid replan <job> --note <text> (or POST /api/videos/:job/replan, or the replan_video tool) asks the storyboarder for the storyboard again. The new storyboard waits for approval when the video has stops; scenes whose entries change build again.
rapid revise <job> --note <text> (or POST /api/videos/:job/revise, or the revise_video tool) acts on a note on a video, done or not, and sets its stops to none. A scene and a time add a person's mark and start a run of rounds for that scene alone; a scene alone starts that run with the note; no scene replans. The scene's new rounds are numbered after its earlier ones (a scene that passed in round 1 revises as round 2) and keyed apart from them, so its renders stay and the video joins again.
Watching
Every change is an event in the daemon's SQLite event log. The pane, the screening page, and rapid events all read the same stream. See the HTTP API.