asymmetric_cast_function — failed 3× (severity 15). Rewrite at least one character's function field as appears X / actually Y (e.g., 'appears the deferential subordinate / actually orchestrating the entire scheme'). The two-hander engine breaks if both characters' functions are flat declaratives. Bake the asymmetry into the cast sheet.
beat_why_it_works_nontrivial — failed 3× (severity 15). Each beat's why_it_works must be ≥30 chars of comedic mechanism — name the device.
direction_notes_density — failed 3× (severity 15). Add 8-15 specific performance direction notes — pauses, swallowed punchlines, register pivots.
has_brilliant_ending — failed 3× (severity 15).
late_identity_reveal — failed 3× (severity 15). Plant a beat in the final third whose description names a specific identity or relationship reveal — the imposter, the twin, the secret child, the same person all along. This is distinct from the status flip: status flip changes who's in control; identity reveal changes WHO they are. Both can co-exist.
tonal_shift_present — failed 3× (severity 12). Land one moment in the final third where laughter falls quiet. Cite a specific timestamp in analysis.standout_moments. The 'vinegar in the sponge cake' beat.
all_plants_pay_off — failed 3× (severity 9). Every setup/runner beat must be load-bearing. If a plant has no matching payoff/callback later, either engineer the payoff or cut the setup — decorative plants break the long-fuse form.
cast_size_2_to_4 — failed 3× (severity 9). Cut to exactly 2 named speaking characters (+ optional Announcer).
duration_within_band — failed 3× (severity 9). Aim for 28-30 minutes total runtime.
finite_isolation_trap — failed 3× (severity 9). Rewrite premise.machine so it literally names the trap: a confined location (lift/carriage/compartment/cabin/lighthouse/waiting room) AND/OR a real-time deadline (the train arrives in 22 min, the bell rings at 7am, only 4-min windows). Without a named trap, the dialogue stops being the action.
genre_register_collision — failed 3× (severity 9). Name the collision in premise.hook. High register × small situation.
has_premise — failed 3× (severity 9). Write logline, machine, hook as three sentences. Machine is the constraint that generates the comedy — mechanical not vibey.
has_snowball_lie_pair — failed 3× (severity 9). Plant a polite minor falsehood in act 1 (a beat tagged 'setup' or 'runner' whose description references a lie/fib/pretense/deception). Detonate it in act 3 (a 'payoff' or 'callback' beat that also references the lie). Distance ≥2 min. The Snowball Lie is the most programmable Finnemore engine — a polite lie the other character believes, then keeps building on, until the liar can't retract without confessing.
inter_line_pacing — failed 3× (severity 9).
narrative_function_coverage — failed 3× (severity 9). Cover ≥3 of {setup, escalation, twist, callback, resolution, interlude} across scenes.
no_explain_the_joke_meta — failed 3× (severity 9). Let the joke land — no character names the device. No 'as if to say', 'lampshading', or 'breaking the fourth wall' in beat descriptions or why_it_works.
no_gratuitous_swearing — failed 3× (severity 9). Strong swears (fuck/shit/cunt/wanker/etc.) below 0.5%% of lines — Radio 4 register. Restraint reads as character, not mealy-mouthed.
no_modern_slang_in_period_episode — failed 3× (severity 9). If style.vocabulary_register is period (1950s/Edwardian/etc.), strip modern slang (yeet, rizz, lowkey, cringe, etc.) from transcript lines. Use period-appropriate idiom.
no_on_the_nose_lines — failed 3× (severity 9). Cut lines that NAME the emotional stakes ('I know you're scared', 'It's okay to be sad', 'I just want you to know...'). Replace with a sideways move that talks about something concrete (the radiator, the brush) while the underlying_motivation captures the avoided thing. Finnemore = deflection, never admission.
no_unearned_sentimentality — failed 3× (severity 9). Earn pathos with a setup beat ≥5 min before the sentimental moment. If standout_moments mentions tears/grief/heartbreak, plant the cause earlier.
period_register_strictness — failed 3× (severity 9). When the scene is set in a period (1820, 1934, Victorian, wartime), style.vocabulary_register MUST name the era so the model sources vocabulary from it (e.g., 'period 1934 — middle-class English diction; no modern colloquialisms; Edwardian-influenced vocabulary'). Without naming the era, the transcript drifts to modern register and the rule_no_modern_slang_in_period_episode lint will catch it later.
setup_to_payoff_distance_min — failed 3× (severity 9). At least one setup→payoff pair must span ≥15 min — the long-fuse signature. Plant in act 1, pay off in act 3.
sfx_count_within_band — failed 3× (severity 9). Cut SFX events to ≤4 for episodes ≤12 min, ≤8 for full-length. Corpus uses foley as a scene-setter at the top of a scene, then drops it so dialogue carries the air. Continuous ambient texture is wrong.
signature_devices_count — failed 3× (severity 9). Name ≥3 specific signature devices in style.signature_devices. Concrete ("false-deference status games") not vague ("British politeness").
third_act_status_flip — failed 3× (severity 9). Place a beat in the final third (after ~2/3 of duration) whose description names the status flip explicitly: the apparently low-status character is revealed to be driving the situation. Use 'reveals', 'drops the mask', 'takes control', 'all along' phrasing in the beat description so the rule can detect it.
plant_payoff_pairs_at_least_three — failed 3× (severity 6). Plant ≥3 innocuous lines in first 5 min that detonate as payoffs in last 5. Tag in beats[] with setup/payoff and cross-ref by timestamp.
Most recent — specific issues to fix next
[sev 5] asymmetric_cast_function — Rule asymmetric_cast_function failed (no character's function names a surface/actual status asymmetry) score 0.00.
Try: Rewrite at least one character's function field as appears X / actually Y (e.g., 'appears the deferential subordinate / actually orchestrating the entire scheme'). The two-hander engine breaks if both characters' functions are flat declaratives. Bake the asymmetry into the cast sheet.
[sev 5] beat_why_it_works_nontrivial — Rule beat_why_it_works_nontrivial failed (0/8 beats >= 30 chars (0%)) score 0.00.
Try: Each beat's why_it_works must be ≥30 chars of comedic mechanism — name the device.
[sev 5] has_brilliant_ending — Rule has_brilliant_ending failed (fewer than 2 dialogue lines — no closer to evaluate) score 0.00.
Try: Address this rule's pass condition.
[sev 5] late_identity_reveal — Rule late_identity_reveal failed (no act-3 beat names an identity/relationship reveal) score 0.00.
Try: Plant a beat in the final third whose description names a specific identity or relationship reveal — the imposter, the twin, the secret child, the same person all along. This is distinct from the status flip: status flip changes who's in control; identity reveal changes WHO they are. Both can co-exist.
[sev 4] tonal_shift_present — Rule tonal_shift_present failed (no final-third tonal moment found in standout_moments or beats — consider tagging the third-act emotional pivot in standout_moments with a timestamp) score 0.20.
Try: Land one moment in the final third where laughter falls quiet. Cite a specific timestamp in analysis.standout_moments. The 'vinegar in the sponge cake' beat.
[sev 3] all_plants_pay_off — Rule all_plants_pay_off is fully passing (all 2 plants pay off).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] cast_size_2_to_4 — Rule cast_size_2_to_4 is fully passing (2 characters).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] duration_within_band — Rule duration_within_band is fully passing (29.0 min ideal).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] finite_isolation_trap — Rule finite_isolation_trap is fully passing (machine names trap: lift (also reinforced elsewhere)).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] genre_register_collision — Rule genre_register_collision failed (low situation present (lift) but no high-register frame) score 0.50.
Try: Pair a high-register frame (diplomatic / military / theological / boardroom / treaty / espionage) with a low-stakes situation (wallpaper / tea / queue / bin day / school run). The funniness sits in the gap. Either lift the situation register (treat the wallpaper job as a peace negotiation) OR drop the situation (the diplomats are actually fighting over biscuits).
[sev 3] has_premise — Rule has_premise is fully passing (all non-empty).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] has_snowball_lie_pair — Rule has_snowball_lie_pair is fully passing (no snowball-lie required; pattern is one option among many).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] inter_line_pacing — Rule inter_line_pacing is fully passing (<4 dialogue lines, no signal).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] narrative_function_coverage — Rule narrative_function_coverage is fully passing (4 distinct: escalation, resolution, setup, twist).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] no_explain_the_joke_meta — Rule no_explain_the_joke_meta is fully passing (no meta-comedy).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] no_gratuitous_swearing — Rule no_gratuitous_swearing is fully passing (no transcript).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] no_modern_slang_in_period_episode — Rule no_modern_slang_in_period_episode is fully passing (not period).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] no_on_the_nose_lines — Rule no_on_the_nose_lines is fully passing (0 talky admissions).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] no_unearned_sentimentality — Rule no_unearned_sentimentality is fully passing (all earned).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] period_register_strictness — Rule period_register_strictness is fully passing (not a period setting — rule N/A).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] setup_to_payoff_distance_min — Rule setup_to_payoff_distance_min is fully passing (longest gap 27.3 min ≥ corpus p25 (4.5 min)).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] sfx_count_within_band — Rule sfx_count_within_band is fully passing (0 sfx events / 29 min = 0.00/min ≤ corpus p75 (1.05/min)).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] signature_devices_count — Rule signature_devices_count is fully passing (5 devices).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] third_act_status_flip — Rule third_act_status_flip is fully passing (act-3 flip beat: 'Anna takes control' (takes control)).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 3] tone_arc_within_character — Rule tone_arc_within_character is fully passing (no delivery_note.tone signal yet — skip).
Try: Preserve this. Don't sacrifice while fixing other axes.
[sev 2] plant_payoff_pairs_at_least_three — Rule plant_payoff_pairs_at_least_three failed (2 setups, 2 payoffs) score 0.67.
Try: Plant ≥3 innocuous lines in first 5 min that detonate as payoffs in last 5. Tag in beats[] with setup/payoff and cross-ref by timestamp.