Credibility pass: the reel's scars sanded, the veil finally hung

Three blind reviews over the first-person arc, every finding verified
against the source. History-narrating comments made timeless or cut;
the stacked BUDDY comment collapsed to one voice. Dead code out: the
orphaned FACE copy, the DIR_ANGLE duplicate, the dead loop-counter
poke, the impossible-state sentinel. The never-produced "warp" hit
kind resolved the right way — warp mouths now hang a translucent veil
of the painted warp texture, so art that never rendered finally does.
Types tightened (SlabStrike named once, ShareData rides CatchUpStep,
botTier loses its casts), the gallery reads MATERIALS instead of a
hand-copied list, the chronicle resets through one helper, a
superseded share mint rejects instead of stranding, and the conjured
safe gains the growth key its siblings had. Tests lose a triple
assignment, a tautology, and two self-swallowing regex alternatives.
The sprite spec — which still told the artist to paint for additive
compositing the renderer no longer uses — now describes the renderer
that exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-23 21:41:11 -04:00
co-authored by Claude Fable 5
parent 88994f18a2
commit 7a32370ccb
16 changed files with 111 additions and 105 deletions
+18 -10
View File
@@ -325,6 +325,7 @@ class Net {
/** The turn whose moment reel is open (share links point at it). */
private momentTurn: number | null = null;
private shareResolve: ((url: string) => void) | null = null;
private shareReject: ((e: Error) => void) | null = null;
private seen: Record<string, number> = loadSeen();
/** Room whose live stream this connection has already shown once: states
* after the first mark themselves seen while the tab is visible. */
@@ -430,6 +431,7 @@ class Net {
case "share":
this.shareResolve?.(`${location.origin}/watch/${msg.id}`);
this.shareResolve = null;
this.shareReject = null;
break;
case "events": {
let talk = 0;
@@ -527,9 +529,7 @@ class Net {
/** Take a seat in the Peanut Gallery: watch a game with no name and no voice. */
watch(roomId: string): void {
this.you = null;
this.log = [];
this.turnCounter = -1;
this.eyeTurn = -1;
this.resetChronicle();
this.send({ type: "watch", roomId: roomId.toUpperCase() });
}
@@ -549,9 +549,7 @@ class Net {
this.spectating = false;
this.token = seat.token;
this.roomIdPending = seat.roomId;
this.log = [];
this.turnCounter = -1;
this.eyeTurn = -1;
this.resetChronicle();
this.send({ type: "join", roomId: seat.roomId, name: seat.name, token: seat.token });
}
@@ -658,9 +656,7 @@ class Net {
this.view = null;
this.started = false;
this.players = [];
this.log = [];
this.turnCounter = -1;
this.eyeTurn = -1;
this.resetChronicle();
this.token = null;
this.spectating = false;
this.audience = 0;
@@ -698,6 +694,13 @@ class Net {
this.markSeen();
}
/** The chronicle and its turn count reset together, always. */
private resetChronicle(): void {
this.log = [];
this.turnCounter = -1;
this.eyeTurn = -1;
}
/** Summon one turn's reel by its chronicle turn number. */
requestMoment(turn: number): void {
this.momentTurn = turn;
@@ -705,15 +708,19 @@ class Net {
}
/** Mint a public link: the open moment's turn, or -1 for the whole
* finished game. */
* finished game. One mint in flight at a time — a newcomer supersedes
* a stranded predecessor rather than leaving it pending forever. */
requestShare(turn: number | null = this.momentTurn): Promise<string> {
return new Promise((resolve, reject) => {
if (turn === null) return reject(new Error("no turn open"));
this.shareReject?.(new Error("superseded"));
this.shareResolve = resolve;
this.shareReject = reject;
this.send({ type: "share", turn });
setTimeout(() => {
if (this.shareResolve === resolve) {
this.shareResolve = null;
this.shareReject = null;
reject(new Error("share timed out"));
}
}, 10_000);
@@ -722,6 +729,7 @@ class Net {
closeMoment(): void {
this.moment = null;
this.momentTurn = null;
}
command(command: Command): void {