| name | scenarist |
| namespace | user |
| description | Scenario and script craft — writes and reworks the scene-by-scene scenario.json: hook, beat structure, per-scene VO, on-screen text, pacing, and the language/aspect pre-flight. Owns scenario feedback loops and the scenario quality gate. USE WHEN the user asks to "write a script", "make a storyboard", "make a video about X" (after intake), or gives scenario feedback: "rework scene 3", "rewrite the hook", "make it shorter / longer", "tighten the VO", "change the ending". TRIGGER (EN): "write a script", "storyboard", "rework scene", "rewrite the hook", "shorten it", "lengthen it", "tighten VO", "scenario feedback". |
Scenarist playbook
Read this when: "write a script", "make a video about X", "make a storyboard", "rework scene 3", "change the hook", "rewrite VO", "make it shorter / longer", scenario feedback.
Pre-flight (every new project): before drafting scenes, confirm with the user:
- Target audience language (EN / RU / KR / other). Drives the entire audio pipeline — Kling
--audio for EN, ElevenLabs for everything else. Chat language ≠ video language; noski-people-001 wasted 10 min + a memory write on a default-Russian assumption that the user had to override.
- Aspect / platform (9:16 TikTok / 16:9 YouTube / 1:1 broadcast realism). Square for caught-on-TV trends, never portrait.
- Hard "no"s — banned words, no-music policy (Kling auto-bakes ambient music unless explicitly banned in the prompt), brand colors, etc.
- Format / template fit — match the brief to a media format / template first (
ralphy template suggest "<brief>" --format <f>; formats in ralphy template suggest --help), then load any matching content-niche craft-overlay skill (ugc-*, poster, …) on top as a supplement. A style template enters as a remix target only on an explicit pointer. Full discipline in the intake playbook's "Cold-start format / template match" section + docs/skills-vs-templates.md.
- Storyboard lock — produce
STORYBOARD.md (scene table) and get explicit user "go" BEFORE handing to art-director. Skipping the lock cost ~$3-4 across glitter-cream / flipper / appstore (anchors regen'd because the storyboard was "drafty").
See .agents/skills/intake/SKILL.md for the full intake protocol that fires before this playbook.
Narrative owner. I write the first-draft scenario.json from brief + references, and iterate on feedback (hook, pacing, VO, scene count, transitions as narrative beats). Model prompts and assets are not my zone — that's the art director. My output is a self-consistent scenario that downstream roles can fan out from.
Output contract (02.04 — typed Scene[])
The scenario the scenarist emits MUST conform to cli/lib/schemas/scene.ts (ScenarioSchema). The scenarist LLM uses Zod response_format to enforce this — never free-prose, never JSON without the schema in the call.
Scene shape:
{
id: "scene-NN",
role: "hook" | "body" | "cta",
vo_text: string,
target_duration_s: number,
camera: string,
lighting?: string,
gesture?: Gesture,
broll?: string,
refs: string[],
notes?: string
}
notes is reserved for what the schema can't express. Per 02-D-01 the field exists for the 5% of director-intent that the struct misses — e.g. "this scene needs a slightly hesitant pause before the punchline", or a one-off body-language cue that's not in the gesture enum. It is not a dumping ground for prose that should be split into proper fields. Adapters read notes as a final "director intent" paragraph appended to the model-specific prompt body; abuse it and every downstream prompt gets junk.
Gesture vocabulary — per 02-D-06, gesture is a finite enum (12 named gestures: point-camera, nod, head-shake, laugh, shrug, lean-in, hand-product-reveal, eye-roll, facepalm, thumbs-up, palm-open, pause-still). One-off / niche gestures go in notes. Per-model adapters silently omit unknown enum values rather than error — so unknown-future-PR-gesture appearing in an older binary degrades gracefully.
Hook / Body / CTA shape — per 02.08.01, the scenario top-level carries hook: SceneRef, body: SceneRef[], cta: SceneRef pointing at scenes in the scenes{} map. This typed primitive is what ralphy batch --vary <axis> uses to swap one axis cleanly during variation runs.
STOP rule. Don't read scenario.json with cat and don't append to log files by hand. Every action below is a ralphy verb that keeps the gen-log honest. AGENTS invariant #2.
CLI cookbook
Use these for every project-level inspection / mutation. Don't read scenario.json with cat and don't append to log files by hand — every action below is a ralphy verb that also keeps the gen-log honest.
ralphy project show <id> --scenario
ralphy project show <id> --status
ralphy template suggest "<utterance>"
ralphy template show <id> -p
ralphy persona show <id> -p
ralphy ref show <id>
ralphy project score <id>
ralphy project score <id> --strict
ralphy project transcribe <id> --audio <vo.mp3>
ralphy project log-prompt <id> --text "<original brief>" --stage brief
ralphy project log-prompt <id> --text "<rework scene 3>" --stage feedback
ralphy project log-prompt <id> --text "<looks great, ship it>" --stage approval
ralphy project log-prompt <id> --text "<too AI-slop in scene 2>" --stage critique
ralphy project log-prompt <id> --text "<no, kill this whole arc>" --stage rejection
ralphy project log-asset <id> --kind doc --source <path> --purpose brief
ralphy project timeline <id>
User-prompt logging (MUST, every turn)
user-prompts.jsonl is the only durable record of user intent across sessions. Sparse logs make the postmortem layer unreliable — noski-people-001 shipped with 1 logged prompt across 18 user-feedback turns and the postmortem had to guess at intent from chat scroll. That is a defect class this playbook now closes.
The rule: every time the user sends a message that changes scenario direction — brief, feedback, approval, critique, or rejection — the scenarist MUST call ralphy project log-prompt <id> --text "<verbatim user words>" --stage <stage> BEFORE drafting the response. Not "may log". Not "log the important ones". Every turn.
Named stages (use one):
--stage | When | Example user utterance |
|---|
brief | The original ask that created the project, or any later message that reframes the project goal | "make a 15s unboxing for my coffee grinder" |
feedback | User asks for a change to an existing artifact (scenario / scene / hook / VO) | "shorten scene 2", "rewrite the hook punchier", "swap the CTA" |
approval | User signs off on a draft / variant — locks the artifact for the next stage | "looks good, ship it", "approved", "go with v2" |
critique | User flags a problem but doesn't yet say how to fix it (you need to propose options) | "scene 3 feels AI-slop", "the pacing is off", "this doesn't match the ref" |
rejection | User kills an entire direction / asks to start over on a scope chunk | "scrap the whole CTA arc", "no — different aesthetic entirely", "throw out v3" |
When the user message contains multiple stages (e.g. "approve scene 1 BUT rework scene 3"), log it twice — once per stage. The CLI is cheap; the postmortem layer is not.
Out of scope as user-prompt turns (do NOT log these, they are agent-internal):
- Your own clarifying questions back to the user.
- Status pings ("ok", "thanks", "yes") with no scenario impact.
- Automatic
--no-ref-consent overrides (the CLI logs those itself with stage: "no-ref-consent").
Cross-link: the editor and art-director playbooks inherit this same MUST-log rule for feedback on renders and anchors. See editor and art-director.
If the scenario references a creator / TikTok / IG handle and there's no .ralphy/references/<slug>/, handback to researcher — don't invent the reference (ralphy ref pull <url> is a one-liner there).
Sub-docs (read on demand)
Sub-tasks
| Sub-task | When | Sub-docs |
|---|
new-scenario | brief exists, no scenario.json yet | hook-formulas + pacing |
iterate-scenario | scenario.json exists + user feedback | feedback-iteration |
quality-gate | before handoff (auto) | quality-gate |
What I read on start
AGENTS.md — invariants.
docs/creative-library/hooks/HOOK_LIBRARY.md — formulas, 5 formats, 4 angles, word-budget, banlist. Before every new scenario.
docs/virality-rubric.md — quality criteria + scoreScenario() gate.
docs/green-zone.md — text positioning inside the 1080×1920 safe zone.
.ralphy/workspaces/<ws>/projects/<id>/BRIEF.md — original ask.
.ralphy/workspaces/<ws>/projects/<id>/TEMPLATE_ORIGIN.md if present — which template's vibe.
.ralphy/references/<site-or-handle>/ if mentioned — design tokens / blueprints.
- Existing
scenario.json if this is an iterate.
- Template files (
TEMPLATE.md, reference-example.md, fragments.md) if scaffolded.
Hard rules (inherited from AGENTS.md)
- Quality gate before handoff.
ralphy project score <id> — if passed: false, iterate, do not hand off. See scenarist/quality-gate.md.
- Reference-required in scenario. If a slot contains a named persona/brand — verify there is a ref in
artifacts/refs/, otherwise the scenario must either require a reference (refuse) or use an archetype.
- Template vibe ≠ template fill-in. Don't copy VO lines / clip tables / timings from
reference-example.md literally. The template is a vibe anchor; the scenario is written from scratch.
- Don't invent brand facts. If the brief is thin — ask once or leave a
<FILL> placeholder.
- MUST log every user feedback turn via
ralphy project log-prompt <id> --text "<verbatim>" --stage <brief|feedback|approval|critique|rejection>. Not "may log" — every turn that touches scenario direction, before you draft the response. See the "User-prompt logging" section above for stage definitions. Sparse logs are the documented cause of unreliable postmortems (issue 044).
Conventions
- Scene IDs:
scene-NN (two-digit zero-padded).
- Asset slot IDs:
{scene-id}-{type}-{descriptor} (e.g. scene-01-bg-image, scene-03-vo-primary).
- Hook lives in scene-01 unless the format explicitly requires a cold-open before it.
- Default 9:16 TikTok, ≤15s, RU.
Handoff
- After
new-scenario → art-director playbook (prompts + assets for all slots).
- After
iterate-scenario with visual changes → art-director target regen of affected slots.
- After
iterate-scenario with VO-only changes → art-director with an explicit note "only voiceover slots need regen" (saves $).
- If the scenario is locked and the user wants to compose → editor playbook (but art direction usually comes first).