Files
wizwar6e/deploy/replay-verify.mjs
T
Eric WagonerandClaude Fable 5 a1fdb37c54 Credibility pass: the splice marks sanded from the rev-11 batch
The extracted rebuildRoom loop reflowed to the file's indent and its
doc comments unstacked; liftIdiotIfSatisfied moves below idiotBlocked
so each keeps its own comment; the pickup's duplicated owner lookup
folds to one; the cloned grab-refusal chain hoists to grabRefused; a
one-off #8a7a5c rejoins the #8a7a5e palette; an inert overflow-x line
and a duplicate import go; span 6 and the two cache strategies say why;
the reversed walking-dead test moves beside its biting sibling. Also:
the replay harness now honors lobby kicks, which VVZU (five bots
seated, two kicked) was the first production ledger to exercise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
2026-08-30 13:58:02 -04:00

28 lines
1.3 KiB
JavaScript

// Strict full-ledger replay: ANY refused command is a hard failure.
import { readFileSync } from "fs";
import { createGame, applyCommand } from "../packages/engine/src/game.ts";
const lines = readFileSync(process.argv[2], "utf8").trim().split("\n").map((l) => JSON.parse(l));
const meta = lines.find((l) => l.kind === "meta");
const start = lines.find((l) => l.kind === "start");
if (!start) {
console.log(`OK ${process.argv[2].split("/").pop()}: lobby only, nothing to replay`);
process.exit(0);
}
// The lobby roster: joins add seats, kicks remove them, the start freezes it.
const roster = new Set([meta.hostId]);
for (const l of lines) {
if (l.kind === "join") roster.add(l.name);
if (l.kind === "kick") roster.delete(l.name);
if (l.kind === "start") break;
}
const playerIds = [...roster];
let { state } = createGame({ playerIds, seed: meta.seed, sets: start.expansion ? ["basic", "expansion1"] : ["basic"], colors: start.colors, deckRev: start.deckRev });
let n = 0;
for (const l of lines) {
if (l.kind !== "command") continue;
const r = applyCommand(state, l.playerId, l.command);
if (!r.ok) { console.log(`FAIL ${process.argv[2].split("/").pop()} seq ${l.seq}: ${r.error}`); process.exit(1); }
state = r.state; n++;
}
console.log(`OK ${process.argv[2].split("/").pop()}: ${n} commands replay clean`);