Credibility pass: the duels leave the code, staying in the ledgers
Third pass, scoped from 7a32370. Three blind reviewers (engine, web,
server/tools) each concluded the work is coherent engineering with
seam-level tells; every finding was verified before touching a line.
Session biography left the comments: the bot brain's heuristics no
longer cite the opponent who taught them, the RNRX coma parenthetical
and the thief-chase citation are gone, the seat-wallet comments state
their invariants without the war stories, and process-named test
groups now name the behaviors they pin. The incident record lives
where history belongs — commit messages and the ledgers.
Structural dedup: one VISIONSTONE one-edge-sight loop serves both
LOS paths; one creature-arrival touch handler serves walking and
warp-stepping (error text aligned); one facingWedge helper draws both
keymap ribbons; one spriteVisibleInCol rule serves the draw pass and
the hover test (which also stops re-sorting per pointermove); and
deepestFacing joins the director, replacing four copied scans.
Test hardening exposed real rot the tells were hiding: the tight
CreatureState cast caught two literals with a bogus field masking
three missing ones; the number-hoarding rig had NEVER run (its
column didn't exist on seed 42 — it now carves its own geometry);
the bank-guard rig now drives the whole table to an arrival
assertion; the bent-trace test walls off straight sight so the bend
must answer. Silent `return`-on-rig-failure became loud throws, and
can-never-fail assertions were removed.
Sweep-up: the eyeTurn ghost comment, the stacked leave() doc
comments (leave now delegates to leaveLocal), the dead ternary in
the seat client, the kick handler's name-coercion drift, kick ledger
lines gain timestamps, archiveRoomFile reuses fileFor, the RULES_REV
alias retires in favor of the engine constant, hitTest un-exports,
the NUL-sentinel hover shape becomes an honest "none" variant, and
the steering holds get named constants. The bezel's stride cluster
also centers per the table's note.
288 tests, 24 ledgers verified, all workspaces typecheck.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
7bd8eff11c
commit
3bd7e3c81d
@@ -225,7 +225,6 @@ export interface LogLine {
|
||||
* momentSteps, so a chronicle turn number addresses the same commands. */
|
||||
const TURN_BOUNDARY = new Set(["turnStarted", "extraTurnStarted", "turnSkipped"]);
|
||||
|
||||
|
||||
const SEAT_KEY = "wizwar-seat";
|
||||
const SEATS_KEY = "wizwar-seats";
|
||||
const CHAT_SEEN_KEY = "wizwar-chat-seen";
|
||||
@@ -318,7 +317,6 @@ class Net {
|
||||
/** Turns witnessed so far: counts the same boundary events the server
|
||||
* counts, so a chronicle line can name the turn it belongs to. */
|
||||
private turnCounter = -1;
|
||||
/** The turn that already carries an instant-replay eye (one per turn). */
|
||||
/** The turn whose moment reel is open (share links point at it). */
|
||||
private momentTurn: number | null = null;
|
||||
private shareResolve: ((url: string) => void) | null = null;
|
||||
@@ -494,9 +492,8 @@ class Net {
|
||||
// Prune ONLY seats the server proved dead: the room exists and
|
||||
// refused this exact token. A seat merely ABSENT from the reply
|
||||
// stays — a restarting server, a stale restore, or the wrong
|
||||
// backend all answer with ignorance, and treating ignorance as
|
||||
// deletion once cost a live player his seat mid-game. The
|
||||
// wallet is capped by age instead of by trust.
|
||||
// backend all answer with ignorance, and ignorance is not
|
||||
// deletion. The wallet is capped by age instead of by trust.
|
||||
const voided = new Set((msg.voided as string[] | undefined) ?? []);
|
||||
let kept = this.seats.filter((s) => !voided.has(`${s.roomId}:${s.name}`));
|
||||
if (kept.length > 50) kept = kept.slice(kept.length - 50);
|
||||
@@ -510,10 +507,9 @@ class Net {
|
||||
// "Name is taken" means THIS token was tried and refused: the
|
||||
// credential itself is dead, and holding it helps nobody. But
|
||||
// "no such room" proves nothing about the seat — a restarting
|
||||
// server, a stale restore, or the wrong backend all say it —
|
||||
// and burning credentials on a transient locked a real player
|
||||
// out of a live game. The seat stays; the error shows; a later
|
||||
// reconnect against the right server walks back in.
|
||||
// server, a stale restore, or the wrong backend all say it.
|
||||
// The seat stays; the error shows; a later reconnect against
|
||||
// the right server walks back in.
|
||||
if (this.roomIdPending && /name is taken/.test(msg.message)) {
|
||||
localStorage.removeItem(SEAT_KEY);
|
||||
}
|
||||
@@ -668,8 +664,9 @@ class Net {
|
||||
} catch { /* blocked at the OS level; the tab title still shows it */ }
|
||||
}
|
||||
|
||||
/** Forget the remembered seat and return to the lobby. */
|
||||
/** Client-side teardown when the SERVER detached us (kick, abandon). */
|
||||
/** Client-side teardown when the SERVER detached us (kick, abandon).
|
||||
* The chronicle survives: the detachment appended its own explanatory
|
||||
* line, and wiping it would erase the only notice of why. */
|
||||
leaveLocal(): void {
|
||||
localStorage.removeItem(SEAT_KEY);
|
||||
this.roomId = null;
|
||||
@@ -682,18 +679,11 @@ class Net {
|
||||
this.audience = 0;
|
||||
}
|
||||
|
||||
/** Walk away from the table (or gallery) by choice. */
|
||||
leave(): void {
|
||||
this.send({ type: "leave" }); // detach server-side too (frees a gallery seat)
|
||||
localStorage.removeItem(SEAT_KEY);
|
||||
this.roomId = null;
|
||||
this.roomIdPending = null;
|
||||
this.view = null;
|
||||
this.started = false;
|
||||
this.players = [];
|
||||
this.leaveLocal();
|
||||
this.resetChronicle();
|
||||
this.token = null;
|
||||
this.spectating = false;
|
||||
this.audience = 0;
|
||||
}
|
||||
|
||||
start(expansion: boolean): void {
|
||||
|
||||
Reference in New Issue
Block a user