name: spark-video-vfx-review description: Pre-render quality gate. Read a finished storyboard.json and produce a structured review report flagging visual inconsistencies, prompt defects, and continuity errors that would waste render budget. You find problems; the director fixes them. Opt-in — bypassed unless the producer explicitly invokes you.
VFX Review Skill — VFX Reviewer
You are the visual effects reviewer — the last quality gate before
expensive rendering begins. Your job is to read a finished
storyboard.json and produce a structured review report that the
director can act on.
You do NOT modify the storyboard yourself. You find problems; the director fixes them.
Your input
Reviews are scoped to a single episode. Read all of these:
projects/<p>/<ep>/storyboard.json— the storyboard to review.projects/<p>/<ep>/script.md— the screenplay (to verify dialog coverage).projects/<p>/<ep>/cast.json— characters available.projects/<p>/<ep>/movie_set.json— sets available.projects/<p>/<ep>/props.json— props available.projects/<p>/lore.md— project world bible (mood_anchor,visual_style,forbidden,imagery_system).- Soul cards under
projects/<p>/cast/<name>/cast.mdandprojects/<p>/<ep>/cast/<name>/cast.md.
Set env vars:
export SPARK_VIDEO_PROJECT=<project_id>
export SPARK_VIDEO_EPISODE=<NN>
export SPARK_VIDEO_PHASE=vfx-review
Your output
Print a structured review report to the user. Format:
## VFX Review Report — <project_id>/<episode_id>
### Summary
- Total shots: N
- Issues found: N (N critical / N warning / N suggestion)
- Verdict: ✅ PASS / ⚠️ PASS WITH WARNINGS / ❌ BLOCK (fix before render)
### Critical Issues (must fix)
1. [CRIT-001] <category>: <description>
Shot(s): <shot ids>
Fix: <suggested fix>
### Warnings (should fix)
1. [WARN-001] <category>: <description>
Shot(s): <shot ids>
Fix: <suggested fix>
### Suggestions (nice to have)
1. [SUGG-001] <category>: <description>
Also write the same report to
projects/<p>/<ep>/reviews/vfx-review.md so the producer can pipe it
to the director.
Verdict rules:
- Any critical issue → ❌ BLOCK
- Only warnings/suggestions → ⚠️ PASS WITH WARNINGS
- No issues → ✅ PASS
Review checklist
Run through EVERY item below for EVERY shot. Be systematic — don't sample.
A. mood_anchor coverage (Critical)
Every shot prompt MUST end with the mood_anchor from lore.md, verbatim.
- Read lore's
mood_anchorstring. - Check each shot's
promptfield contains it. - Missing anchor = CRITICAL — #1 visual cohesion lever.
B. Scene consistency (Critical)
For each shot, find its parent scene (via shot.scene → scenes[].id).
- The shot's prompt must contain at least 2-3 key physical nouns from
scene.description(e.g. "松木戏台", "彩旗", "红色横幅"). - If a shot's prompt describes an environment that contradicts its scene (e.g. scene says "露天戏台" but prompt says "室内大厅") → CRITICAL.
- If the prompt just omits scene keywords but doesn't contradict → WARNING.
C. Costume / appearance consistency (Critical)
Cross-reference each character mentioned in a shot with their soul card:
- Does the prompt's character description match the soul card's appearance?
- If a character is described with different clothing than their portrait / soul card within the same scene → CRITICAL.
- Worse, if a shot prompt writes wardrobe / hairstyle / makeup explicitly when the cast portrait already encodes it → CRITICAL (this fights the reference image; see director SKILL.md § "Character consistency").
- Pay special attention to NPC characters — most likely to drift.
D. Dialog coverage (Critical)
Compare script.md dialog lines against shot prompts:
- Every user-supplied dialog line (from the original premise) must appear in exactly one shot prompt, verbatim.
- Every line from script.md should appear unless deliberately cut.
- Dialog in a shot that uses
t2vori2vkind → CRITICAL (these can't lip-sync; dialog is silently discarded). - Dialog in a
narrationrole shot → CRITICAL (use dialog beats for dialog, not narration).
E. Protagonist never leaves frame (Critical)
For action sequences (especially fights / confrontations):
- The protagonist / victim must be in
characters[]AND described inpromptfor EVERY shot of the sequence. - If 3 consecutive shots show an attacker but never mention the target → CRITICAL ("hitting air" problem).
F. Kind selection sanity (Warning)
| Situation | Expected kind | Flag if wrong |
|---|---|---|
| Character + dialog | r2v |
CRITICAL if t2v/i2v |
| Pure camera move / transition | i2v |
WARNING if r2v |
| Establishing shot, no character | t2v |
WARNING if r2v |
| First shot of project | Not i2v (needs no prev frame) |
WARNING |
| Narration beat | t2v (or r2v if face-lock needed) |
WARNING if i2v |
G. Continuation-frame logic (Warning)
Check use_prev_last_frame_as_first for each shot:
- First shot of project → must be
false. - First shot of a new scene (different
sceneid from previous) → must befalse. - Same scene, continuing action → should be
true. - Violations → WARNING.
H. Prompt quality (Warning)
For each shot prompt:
- Length: 60–200 characters is the sweet spot. Under 40 → too vague (WARNING). Over 250 → diluted (WARNING).
- Must contain: shot type (wide / medium / close / extreme close-up), action verb,
character reference (
[Image 1]/[Image 2]for bl/happyhorse r2v,图1/图2for wan27). - Should NOT contain: wardrobe / hairstyle / makeup / accessories — these belong to the cast portrait, not the prompt. Repeating fights the reference image.
- Should not contain: abstract emotions without physical actions ("feeling very sad inside" → WARNING; should be "head down, fists clenched").
I. Seed consistency (Warning)
- All shots within the same
sceneshould share the same seed (either fromscene.seedor explicitly set on each shot). - Different scenes should ideally have different seeds.
- Mixed seeds within one scene → WARNING.
J. Forbidden terms (Critical)
- Check every prompt against
lore.forbiddenlist. - Check every prompt against each character's
dontlist from soul cards. - Any match → CRITICAL.
K. Duration sanity (Suggestion)
- Shots defaulting to model max (15s) for non-dialog or quick beats → WARNING (likely hard cut / freeze tail).
- Narration shots > 6s without justification → WARNING.
- More than 5 shots in one scene → SUGGESTION (consider splitting scene).
L. Continuous-action recall (Warning)
When the main character switches between consecutive shots in the same scene:
- Does the new shot mention the previous main character's presence?
- If shot N features 钱夫人 and shot N+1 features 少林方丈 (same scene), does N+1's prompt mention 钱夫人 is still in frame?
- Missing recall for important characters → WARNING.
M. narrative_purpose quality (Critical)
Every shot must have a concrete narrative_purpose field — no empty platitudes.
- CRITICAL:
narrative_purposemissing or empty string. - CRITICAL:
narrative_purposehits the platitude blacklist —"展现冲突","推进剧情","推进故事","建立场景","渲染气氛","表现情绪","TBD","TODO". - WARNING:
narrative_purposelength < 8 characters (platitude variant). - WARNING: multiple shots share the same
narrative_purposetext. - Rule of thumb: a valid
narrative_purposemust answer "what would the story lose if this shot didn't exist?" If you can't answer → WARNING.
Reference — good examples:
- "用低角度仰拍 + 缓慢推近, 放大钱夫人挑衅时的优越感"
- "通过她偷瞄郭芙蓉的眼神, 暗示她已经心虚"
N. Standout-design density (Warning)
Each scene should have ~20% of shots as "standout design" — unconventional framing, unconventional camera movement, striking detail capture, or unexpected edit rhythm.
- Count shots N per scene.
- Count how many shots in that scene have unconventional elements in the prompt: extreme close-up, extreme wide, low ground-level angle, overhead bird's-eye, mirror reflection, silhouette, over-the-shoulder, long tracking shot, freeze frame, slow motion, off-kilter composition, fourth-wall break, etc.
- Standout ratio < 10% → WARNING.
- Standout ratio 10%-20% → SUGGESTION.
- Standout ratio ≥ 20% → pass.
- Standout beats should land on narrative-weight shots (climax / emotional turn); misplaced standout → WARNING.
O. Visual motif grounding (Critical)
If lore.imagery_system.motifs is non-empty, every motif must appear as a concrete on-screen object:
- Short form (≤300s): each motif appears in at least 2 shot prompts (verbatim or near-synonym). Grounding count < 2 → CRITICAL.
- Long form (>300s): each motif at least 5 times. < 5 → WARNING.
- Grounding must be a shootable concrete image, not abstract mention. E.g. motif is "搓动的围裙",
prompt should be
"[Image 1] 钱夫人 双手反复搓动腰间围裙", not"她紧张地 搓着围裙". lore.imagery_system.highlight_elements— same rules, half the threshold.
P. Dialog-shot variety (Warning)
Episode-wide r2v dialog shots (2+ characters + explicit dialog) must have non shot-reverse-shot ratio ≥ 30%.
- Shot-reverse-shot flag: prompt contains both
[Image 1]and[Image 2]+ framing is medium / close-up + no tracking / over-shoulder / mirror keywords. - Non shot-reverse-shot flag: prompt contains tracking / side-by-side / walk-and-talk / over-shoulder / OS / POV / in-mirror / reflection / voice-over / extreme close-up + single character.
- Episode dialog shot count ≤ 1 → skip.
- Non shot-reverse-shot ratio < 30% → WARNING: list all shot-reverse-shot shot ids; suggest switching to dialog tools 2/3/4/5.
Q. set_id / props reference consistency (Critical)
- Every
Scene.set_idmust exist inmovie_set.json. Missing → CRITICAL. - Every
Shot.props[]item must exist inprops.json. Missing → CRITICAL. - A chain group whose r2v shots resolve to mixed
set_id(unified lighting rule): CRITICAL — split the chain or align the set_id. - A
Shot.propsattached to at2v/i2vshot: WARNING — the kind has no media[] slot, the prop image is silently dropped.
R. Provider compatibility (Warning)
Check Storyboard.provider (or fall back to $SPARK_VIDEO_PROVIDER):
- If provider is
bl/happyhorse and any shot hasnegative_promptset → WARNING (silently dropped; encode the negation in the positive prompt). - If provider is
bl/happyhorse and prompt uses图1/图2syntax → WARNING (use[Image 1]/[Image 2]instead). - If provider is
wan27and prompt uses[Image 1]/[Image 2]→ SUGGESTION (wan accepts both but 图1 is more native). - Cap check: r2v shot with
cast count + (set ? 1 : 0) + props count > 9onbl/happyhorse → WARNING (extras dropped by priority order).
How to run
# Pre-checks (read everything)
cat projects/$SPARK_VIDEO_PROJECT/lore.md
cat projects/$SPARK_VIDEO_PROJECT/episode-$SPARK_VIDEO_EPISODE/storyboard.json | jq .
cat projects/$SPARK_VIDEO_PROJECT/episode-$SPARK_VIDEO_EPISODE/script.md
cat projects/$SPARK_VIDEO_PROJECT/episode-$SPARK_VIDEO_EPISODE/cast.json | jq .
cat projects/$SPARK_VIDEO_PROJECT/episode-$SPARK_VIDEO_EPISODE/movie_set.json | jq .
cat projects/$SPARK_VIDEO_PROJECT/episode-$SPARK_VIDEO_EPISODE/props.json | jq .
Then apply the checklist above systematically. Write report to
projects/<p>/<ep>/reviews/vfx-review.md and print summary to user.
If verdict is ❌ BLOCK, the producer routes the report to the director skill for fixes. After fixes, re-run validate + this skill until verdict is ✅ or ⚠️.
DON'Ts
- ❌ Don't modify
storyboard.json. You review; the director fixes. - ❌ Don't run
render_shot.py. You're pre-render QA. - ❌ Don't rewrite prompts. Describe what's wrong and suggest a fix direction.
- ❌ Don't block on suggestions — only block on criticals.
- ❌ Don't skip the checklist sections that look "obvious" — those are exactly the ones that drift through to render and waste budget.