The render harness: every screenplay's beats pinned as golden frames

deploy/verify-scenes.sh replays each screenplay to its authored beats
under a paused Playwright clock — pulses, tweens, and fx advance only
on the harness's schedule, so the same beat renders the same bytes
every run — screenshots the reel, and diffs pixels against the goldens
in deploy/scene-goldens (30 frames: warp transits, impacts, curses
landing, in both views). A channel may drift 6 before a pixel counts,
0.2% of pixels before a beat fails; --update blesses intended changes.

Proven both ways before landing: a clean double-run reproduces all 30
goldens exactly, and resurrecting the warp-smear cutaway bug fails the
warp-transit beat at 61% pixel drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
Eric Wagoner
2026-09-01 16:58:43 -04:00
co-authored by Claude Fable 5
parent 6c48174376
commit 58d1d34cb0
35 changed files with 212 additions and 0 deletions
+27
View File
@@ -28,6 +28,13 @@ export interface Screenplay {
* instanceIds are `<cardId>#rig<n>`. */
rig?: Record<string, string[]>;
moves: ScreenplayMove[];
/** Step indices the render harness pins as golden frames, first-person:
* the scene's money shots — a warp transit, an impact, a curse landing.
* deploy/verify-scenes.sh screenshots each beat and diffs it against
* the committed golden. */
beats?: number[];
/** One step pinned from the board view. */
boardBeat?: number;
}
export interface ScreenplayStep {
@@ -116,6 +123,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Nine strides on a number card: through the south mouth, around the back row, out with a treasure.",
pov: "Rival",
rig: { Rival: ["number-6"] },
beats: [5, 10],
boardBeat: 5,
moves: [
{ seat: "Rival", cmd: { type: "playNumberForMovement", instanceId: rigId("number-6") } },
{ seat: "Rival", cmd: { type: "move", direction: "W" } },
@@ -138,6 +147,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Line of sight threads a wormhole: a fireball cast into one mouth arrives through the other.",
pov: "Wanderer",
rig: { Wanderer: ["number-3", "fireball"], Rival: ["number-3"] },
beats: [6, 16],
boardBeat: 16,
moves: [
{ seat: "Rival", cmd: { type: "playNumberForMovement", instanceId: rigId("number-3") } },
{ seat: "Rival", cmd: { type: "move", direction: "W" } },
@@ -168,6 +179,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "An ambush watches its corridor through a wormhole — and fires the moment a wizard crosses the far sightline.",
pov: "Rival",
rig: { Wanderer: ["opportunity-fire", "fireball"] },
beats: [5, 6],
boardBeat: 5,
moves: [
{ seat: "Rival", cmd: { type: "move", direction: "W" } },
{ seat: "Rival", cmd: { type: "move", direction: "S" } },
@@ -187,6 +200,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "A pit yawns in the corridor — but the die says the intruder sails clean over it, onto the trapper's doorstep.",
pov: "Rival",
rig: { Wanderer: ["create-pit"] },
beats: [8, 9],
boardBeat: 8,
moves: [
{ seat: "Rival", cmd: { type: "move", direction: "W" } },
{ seat: "Rival", cmd: { type: "move", direction: "S" } },
@@ -209,6 +224,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Mental Force walks the enemy to exactly where you want them — which has its risks.",
pov: "Wanderer",
rig: { Wanderer: ["mental-force"], Rival: ["number-2"] },
beats: [10, 13],
boardBeat: 10,
moves: [
...RIVAL_TO_NORTH,
{ seat: "Rival", cmd: { type: "endTurn", draw: 0 } },
@@ -229,6 +246,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Medusa freezes a wizard solid — and stone, inconveniently, cannot be hurt.",
pov: "Rival",
rig: { Rival: ["number-2", "medusa", "number-5", "fireball"] },
beats: [10, 14],
boardBeat: 10,
moves: [
...STANDOFF,
{ seat: "Rival", cmd: { type: "cast", instanceId: rigId("medusa"), numberInstanceIds: [rigId("number-5")], target: { kind: "player", playerId: "Wanderer" } } },
@@ -247,6 +266,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Go Away hurls a wizard down his own corridor, as straight a line as the maze allows.",
pov: "Rival",
rig: { Rival: ["number-2", "go-away", "number-5"] },
beats: [4, 11],
boardBeat: 11,
moves: [
...STANDOFF,
{ seat: "Rival", cmd: { type: "cast", instanceId: rigId("go-away"), numberInstanceIds: [rigId("number-5")], target: { kind: "player", playerId: "Wanderer" } } },
@@ -261,6 +282,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Blast the wall between you — the rubble bloodies both sides of it — then step through the breach.",
pov: "Wanderer",
rig: { Wanderer: ["number-2", "destroy-wall"] },
beats: [6, 7],
boardBeat: 6,
moves: [
{ seat: "Rival", cmd: { type: "endTurn", draw: 0 } }, // stands his ground at home
{ seat: "Wanderer", cmd: { type: "playNumberForMovement", instanceId: rigId("number-2") } },
@@ -283,6 +306,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "Five points of fire meet a Full Shield, and the shield wins.",
pov: "Wanderer",
rig: { Rival: ["number-2", "fireball"], Wanderer: ["full-shield"] },
beats: [11, 12],
boardBeat: 11,
moves: [
...STANDOFF,
{ seat: "Rival", cmd: { type: "cast", instanceId: rigId("fireball"), target: { kind: "player", playerId: "Wanderer" } } },
@@ -298,6 +323,8 @@ export const SCREENPLAYS: Screenplay[] = [
blurb: "The Sticky Wand binds a wizard in silk — and fire burns twice as hot in a web.",
pov: "Rival",
rig: { Rival: ["number-2", "sticky-wand", "fireball"] },
beats: [11, 14],
boardBeat: 11,
moves: [
...STANDOFF,
{ seat: "Rival", cmd: { type: "cast", instanceId: rigId("sticky-wand"), target: { kind: "player", playerId: "Wanderer" } } },