Commit Graph
22 Commits
Author SHA1 Message Date
Eric WagonerandClaude Fable 5 3308850bb6 Credibility pass: sweep the workshop floor
Scoped to everything since the last pass (695307d). The residue of
fast iteration, removed: a reduced-motion media query that had
swallowed a full copy of the .faq-seal rules; doc comments orphaned
from their functions by inserted methods; the FAQ scrape's seams
(section headings run into ruling bodies under the wrong topics, a
next-page heading shipped as a ruling, an amputated "h", and rulings
filed under alphabetically-nearest strangers — Large Rock/Dagger now
lives on those cards; Book of Spells and Torquemada describe no card
in this set and are gone); the write-only aisle flag left behind by
the reverted rev 7; a linter-silenced dead destructure; a duplicated
median lookup; dead casts; and the fallback path that ignored the
apprentice's one-card draw.

Tests now typecheck (tsconfig includes test/), which surfaced the
missing type imports and a drifted creature literal hiding under an
as-cast. Also: a no-op self-assignment, mid-file imports hoisted, a
dynamic-import habit made static, a hedge comment replaced with a
loud setup failure, the fallback-retries-itself dead rung removed
from both bot drivers, and the twin peek scrims merged.

Deliberately kept: the TIERS lookup guard (ledger JSON is untrusted),
the wand-cost stanzas (they differ on the power-attack trade — a
rules question, not a dedup), and rollDie's coexistence with rollD4
(migrating changes visible logs; future work).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 20:20:37 -04:00
Eric WagonerandClaude Fable 5 73150a89b5 Rev 11: the maze has no wall at zero, and moving sectors carry everything
Relocate Sector could never land a sector west or north of the origin
— placements the physical game allows by simply sliding the whole map
across the table. The coordinate grid still cannot go negative, but
now it does not need to: a sector may land at negative coordinates
and the whole maze renormalizes, zero-anchoring on both axes (which
also pulls the maze snug when the origin corner is vacated, instead
of leaving a blank band). The client offers the new landings as ghost
slots on every side, verified slot-for-slot against engine truth.

The move also closes a real gap: remapState never carried creatures,
boobytrap tokens, glue, open safes, or dimensional warp tokens when a
sector relocated or rotated — they were left hovering at their old
coordinates. Sectors now carry everything standing on them. Both
changes ride rules rev 11; older ledgers replay their flaws intact,
as replay determinism demands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 20:07:01 -04:00
Eric WagonerandClaude Fable 5 ac53773fe4 The dimming aid stops lying about boobytrap, glue, and safe
Three cards sat wrongly in the creation bucket of eligibleCellsFor,
so the targeting dim demanded sighted empty squares the engine never
asks for. Boobytrap tokens go anywhere on the board but solid stone —
no sight required; a trap you can see coming is a poor trap. Glue and
the safe were worse than restricted: inverted. Both seize a square
that HOLDS a loose object or treasure, exactly the squares the empty-
square rule dimmed out. Each now has its own branch mirroring the
engine's actual checks, pinned by tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 19:31:57 -04:00
Eric WagonerandClaude Fable 5 d6d34887e3 The whole punch list: rev 8, general FAQ, and four promoted UX items
Rules rev 8 closes the last two fidelity threads. A SPEED bonus turn
burns a turn of duration spells on the hastened wizard — recipient-
counted, per the FAQ's most obscure ruling — with self-cast durations
already burning through the normal turn-start sweep (expiry extracted
into expireEffect so both paths share the cleanup). And nothing can
be created on a DIMENSIONAL WARP token, as the card face always said.

The general-topic FAQ sections (Combat, Line of Sight, Monsters,
Treasures, and five more) join the rules tab verbatim under a double-
ruled divider, completing the FAQ's absorption: card rulings on the
cards, general rulings in the rules.

The four promoted UX items: cell-target spells now dim ineligible
squares (creations mirror emptySquareTarget from the viewer's
knowledge, summons want clear sighted squares, teleport BFSes its
four spaces exactly as the engine does, stone-to-water lights only
stone, dispel lights only creations); hotseat games get the full
replay reel, each step seen from its actor's own seat; a "stop
announcing attacks on this device" link in the fanfare modal (undo
lives beside the notification toggle in the lobby); the corner
inspector now serves only the selected casting card, with every
examine-a-card peek unified on the centered treatment; and the dev
socket URL keys on vite's port instead of hijacking every localhost.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 15:45:59 -04:00
Eric WagonerandClaude Fable 5 0ebae03b1c The discard pile lies face-up, and the chronicle names what falls
At the table the discards sit face-up for anyone to leaf through. The
view now carries the pile (deck order stays secret), the "discards N"
count in the rail became a link, and it opens a booklet-styled reader:
every cast-away card newest first, tap any to enlarge. And the
chronicle stops mumbling "discards 1 card(s)" — it names names, so a
wraith's theft reads "bob discards Fireball," exactly what a table
would see as the card hits the pile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 13:28:55 -04:00
Eric WagonerandClaude Fable 5 7e3e00bf97 Rules rev 3: Ward is a choice, Chaos honors the shield
WARD's text says "you may play at that time" — under rules revision 3
the choice is made by setting the trap: an armWard command toggles it
on your own turn (your secret; a private wardSet event and a rail
note), and the spring fires only while set, consuming the card and
the arming together. Async games keep their agency without an
interrupt window, exactly as the ambush system solved this before.

CHAOS gains its printed interactions: "FULL SHIELD removes a player
from participation" — a defender's shield sits them out instead of
stopping the spell, and after the counter chain every bystander gets
a shield window in seat order (chaosPending; queue head owes a
response in lobby summaries, the rail says whose hand hangs in the
balance) before the pile forms among the unshielded. "REFLECTIONS
have no effect" — both reflections are refused as counters. ABSORB
SPELL still eats the whole thing through the existing absorb path.

Both changes are frozen behind deckRev 3 so every stored game — and
the live one — replays byte-for-byte under its own rules. Five new
tests cover armed/unarmed wards, shielded defenders and bystanders,
the reflection refusal, and the legacy auto-ward.

Not deployed — a live game is in progress.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 12:55:58 -04:00
Eric WagonerandClaude Fable 5 41c384274d Walls and doors fall to sustained assault
"It is possible, though time-consuming, to punch a wall down. A wall
takes 20 points of damage to destroy; a door takes 15. Any attack
against an inanimate object counts as your one attack for the turn."
Damage accumulates per edge in wallDamage (remapped through sector
rotations, public in the view), fed two ways: a punchWall command for
the bare-fisted (1 point, from a square touching the edge) and attack
spells cast at an edge target — LOS to the wall for L.O.S. cards,
touching it for same-square cards, amplify and power-attack honored,
wand charges spent, no counteractions since stonework plays none.
Thrown daggers and rocks clatter to the floor at the foot of the
wall. At the threshold the edge opens through the same override path
destroy-wall uses.

On the table: damaged walls wear spreading cracks, an attack card's
hint offers "or a wall line to batter it" with the edge layer live,
and a "Punch a wall…" stamp arms a click-the-wall mode. The chronicle
counts the blows: "alice batters the wall with bare fists — 3/20."

Not deployed — a live game is in progress.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 12:48:49 -04:00
Eric WagonerandClaude Fable 5 64454ffc3e Sight travels through the wraparound openings
"If casting a spell, or checking line of sight through the AUTO WARP,
treat it as a straight line, and the two connected boards as though
they were adjacent" — and the lettered openings reconnect edges the
same way. hasWarpLineOfSight models it: the line must run straight
down the corridor, out one mouth, and in through the paired mouth,
with both corridor legs clear and neither mouth filled solid. The new
sightBetween (direct or through-a-warp) is now the game's LOS check
everywhere — spells, ambush triggers, Around The Corner, the
visionstone sweep, and the targeting dim on the client.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 12:43:57 -04:00
Eric WagonerandClaude Fable 5 695307daa8 Credibility pass: one voice, no scars
A three-reviewer sweep for tells of piecemeal machine generation,
every finding verified against the code before touching it. No
behavior changes; the full suite passes unchanged (plus two
strengthened pins).

Engine: removed four void-silenced fossils (a parseEdgeKey call
voided where it stood, stoneEffect's ignored cardId parameter, the
actualTarget remnant in doCast, a voided loop variable in shadow
upkeep); fixed the initialize-then-overwrite narration in
spawnCreature; replaced a filter(() => false) no-op; waterwall now
rides waveFromEdge instead of carrying its own verbatim copy (and the
single-caller washBack wrapper went with it); blind wall-bumps and
LOS blockers each collapsed to one implementation; the wand-id list
and the "permanent" duration sentinel became named constants; the
ambush number local no longer shadows the imported numberValue
function; assorted reviewer-aimed phrasings rewritten as the
constraints they guard.

Server/deploy: the protocol header now documents all eleven message
types; dropped an eslint pragma with no eslint, a test script with no
tests, and an rsync exclude anchored at a path that never existed
(the real data/ dir now excluded); the Caddy vhost has one source of
truth; stale "pending DNS" note removed — the record resolves.

Web: ~90 lines of CSS swallowed verbatim into a mobile media query
deduplicated; the reduced-motion guard on the board now actually
stops the marked-cell pulse; one shared color module replaces two
drifted palettes; an orphaned doc comment rejoined its function.

Tests: the ten-times-pasted helper block became test/helpers.ts;
wave-numbered files renamed for the behaviors they pin; deliberation
comments and void-ed corpses of unwritten assertions deleted; silent
seed-dependent early-returns now fail loudly; one assertion that
compared a value to itself now pins the home-translation it meant to;
the stored-log single-number command form gained the explicit
compatibility test it deserved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 11:56:55 -04:00
Eric WagonerandClaude Fable 5 da4ab03135 The reveal remembers the hand a wizard fell holding
Elimination destroys the evidence: a killed wizard's cards pass to
the killer, a treasure-lost wizard's go to the discard — so the
post-game reveal showed "empty-handed" for exactly the player whose
hand everyone wants to see. Both elimination paths now snapshot the
hand at the moment of death (finalHand), the finished view serves it,
and the gallery marks those rows "as they fell" in script. Because
rooms replay from the command log, already-finished games show their
fallen hands too. Test kills a wizard holding a Fireball and a 6 and
finds them in the reveal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 11:20:10 -04:00
Eric WagonerandClaude Fable 5 e7b17f7643 The finished table lays every hand face-up
Once the game is won, the view stops keeping secrets: revealedHands
carries every player's cards, and the table replaces your hand row
with a face-up gallery — each wizard's name (trophy on the winner)
beside their final hand, tap any card to enlarge, "empty-handed"
written in script for those who died with nothing. In hotseat this is
the thing the winner passes around after dismissing the fanfare; in
async games it greets each player when they open the finished game.
Redaction still guards every phase before "finished."

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 11:17:07 -04:00
Eric WagonerandClaude Fable 5 13aeeea0ef Victory gets its moment: a gold-ringed proclamation
Winning showed only as a small slip in the rail — anticlimactic, as
playtesting put it. The engine now records HOW the game was won
(winReason: treasures carried home, or last wizard standing) alongside
the winner, the view carries it, and the finish opens a gold-ringed
modal: trophy, the winner's name in tall caps, and the manner of
victory in a handwritten line. "Behold the final board" dismisses it
to the finished table. In hotseat the one screen proclaims to the
whole table at once; in async games each player is greeted by it when
they next open the game.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 11:11:24 -04:00
Eric WagonerandClaude Fable 5 4f3083c490 Targeting dims out-of-reach squares; Speedstone pays out immediately
Selecting an L.O.S. card now drops every square you cannot see into
shadow, leaving eligible targets lit — computed by the engine's own
hasLineOfSight over the player's VIEW, so illusion walls you still
believe in block your aim, stone and bushes and the Big Man block
everyone's, and Around The Corner widens the light one bend when
attached. ADJACENT cards light just your square and its four
neighbors. The shade paints over tokens and wizards alike, and
switches off while arming an ambush, since ambushes aim at the
future. A new sightedCellsFor lives in the engine view module so the
client can never disagree with the rules.

Speedstone, meanwhile, only took effect at next turn's allowance
recompute — displaying it mid-turn granted nothing, as playtesting
found. It now bumps the current allowance by one on display (a delta,
so number-card movement already played survives), unless SLOW or a
zeroed allowance says otherwise. Test covers the immediate grant and
the persistence into later turns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 10:33:02 -04:00
Eric WagonerandClaude Fable 5 45666bca16 Ambushes: the async-native form of Interrupt and Opportunity Fire
Eric's diagnosis: "in the moment" interruption cards are worthless in
correspondence play — there is no moment. The answer was already in
the game: WARD is a contingency card, and ambushes generalize it. On
your turn, playing Interrupt or Opportunity Fire now arms an ambush:
commit it with an attack from your hand (plus an optional number
card) and a trigger — an opponent entering your line of sight, coming
beside you, or grabbing a treasure — and it springs automatically
when the condition occurs, whether you are watching or asleep. The
sprung attack opens the normal counteraction stack, so the victim
gets their defense (asynchronously, like any attack). Committed cards
leave your hand until the trap springs or you disarm it; ambushes are
invisible to everyone but their owner (view-level redaction), die
with their owner, stay armed if the shot is momentarily illegal, and
honor the no-combat first round. Live play in the moment still works
too — and the client now actually offers it (the old UI never let
you click those cards out of turn). The rail shows your armed traps
with a disarm control; the chronicle announces AMBUSH! when one
springs. 124 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 01:36:53 -04:00
Eric WagonerandClaude Fable 5 77ae65b263 Pick your standee: hotseat wizards choose their color while naming
The naming round now shows the six real wizard standees; each player
taps theirs before typing their name, claimed standees gray out, and
the next player defaults to the first free one. The choice travels as
an optional colors array in the engine config, the view exposes each
player's colorIndex, and the board, score sheet, treasure chests, and
wizard art all follow the chosen color instead of seat order —
persisting through hotseat saves. Verified: Alice claimed the yellow
standee and marched onto the board as the yellow wizard with yellow
treasure chests. (Online rooms still assign by seat order; a lobby
color picker can reuse the same config field later.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 01:15:07 -04:00
Eric WagonerandClaude Fable 5 06eea72ded Expansion wave 4: 27 combat, curse, and utility cards
Fortune: GIFT FROM ABOVE (+3, no ceiling), GIFT FROM BELOW (a trap in
the deck — 3 damage on the draw, harmless in the opening deal).
Modifiers: POWER ATTACK burns life into any damage spell. Curses:
WEAKNESS (drop your treasure, take double, carry nothing), STRENGTH
(double physical dealt; the two cancel), WALKING DEAD (half a point
per space walked, forever), DISEASE (the victim becomes a carrier who
infects everyone in squares they enter), IDIOT (the victim shambles
toward their nearest own treasure, able only to counteract, until
they stand on it and ask "What am I doing here?"). Defense: EMPATHY
(attacks bite their caster too), FORCE FIELD (spell-stopping
counteraction). Mischief: MENTAL SWAP (trade whole hands), MENTAL
FORCE (march someone three spaces), BUTT-HEAD (become a goat, ram for
the distance charged), HEAVE-HO (throw your carried treasure as a
weapon), THIEF and SWAP-MEET (item larceny), CHAOS (all hands in a
pile, shuffled, redealt), ILLUSIONARY ATTACK (a fake spell that hurts
if believed), WARD (a trapped treasure bites its thief), REMOVE CURSE
(strip any duration spell, rolling to hit the shrunken or invisible),
SWARTHMORE'S ENCHANTMENT (+1 on an enchanted object). Space-time:
DIMENSIONAL WARP (paired step-through tokens), REDIRECTION (swap two
outer exits' wraparounds), BIG MAN (fills the corridor: no entry, no
punches, no casting past him), FEAR (nobody approaches within 3),
and the out-of-turn pair — INTERRUPT and OPPORTUNITY FIRE — which
open a one-action window in another player's turn. Only THUMB OF GOD
remains, awaiting its digital redesign. 117 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 23:01:42 -04:00
Eric WagonerandClaude Fable 5 3a35922a40 Expansion wave 3: twelve terrain cards
KILLER OOZE (1 damage on entry, slip on 1-2: drop treasure, 2 more,
flat on your face until you roll to stand), CREATE PIT (jumps roll a
D4 — clear it on 2-4, fall in on a 1 and climb out on later rolls),
ROSEBUSH (3-point passage, blocks sight), DUST CLOUD (a permanent
zone of blindness: direction rolls inside, no LOS through, defeats
Visionstone), FILL SQUARE WITH SLIME (entering ends your actions,
blocks sight), HANDFUL OF TACKS (adjacent-only scatter, 3 points to
cross), CREATE DOOR (a new locked door in any wall or corridor),
BOOBYTRAP (four face-down tokens, one secretly real — 4 points under
anyone but the caster; the caster's view alone marks the true token),
GLUE (objects pinned for twice the number card), SAFE (items locked
away from everyone but the creator), TRADER (swap two floor items in
sight; glue and safes hold fast), and STONE TO WATER (walls melt into
range-2 waves, stone blocks into range-4 bursts). LOS blocking is now
per-terrain-kind. The board renders all of it, boobytrap placement is
a four-click ritual, and Trader is two. 108 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 22:52:34 -04:00
Eric WagonerandClaude Fable 5 28949bdb7d Expansion wave 2: the magic wand system, plus Deja-Vu
Wands charge on first use from the number card(s) played (Amplify and
Add both work when setting charges), spend one charge per use with a
hard once-per-turn limit, stay displayed while charged, and crumble
to the discard when the last charge goes. They are isolated from
their wielder — usable under NO SPELL — and Absorb Spell cannot eat
them. BLASTER WAND fires 3-point bolts through the normal
counteraction stack; STICKY WAND webs its victim (movement -3 for a
turn, +2 to any fire damage, including hotter firewall crossings);
SHIFT WAND shoves a wizard one space in any direction straight
through stone walls; WARP WAND opens a wall section that snaps back
at the end of the turn. DEJA-VU retrieves any discard except a wand.
The wands' 5e-era "stick" subtype is renamed "wand" per Eric (the 6e
faces say Wand; Exp2 shelf cards keep their period names). Client:
charge badges, shove targeting, retrieve-by-name. 101 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 22:45:51 -04:00
Eric WagonerandClaude Fable 5 df0675c735 Expansion wave 1: the creature system and first eight monster cards
Creatures are first-class citizens: TROLL (D4 punches, 6 damage to
kill, regenerates at its creator's turn end), SKELETON (2-point
punches), WRAITH (walks through one wall a turn; its touch deals 2
and steals a random card), FIRE IMP (a stationary turret scorching
anyone in sight once per turn — including its creator — killed only
by Waterbolt or a Waterwall wave), DEMOCRATIC MONSTER (moved three
spaces by EVERY player on their turn, one claw per round), SHADOW (a
second body costing a life point per turn, destroyed by any damage),
and ALTER EGO (a stationary double). Monsters obey their creators,
move on the controller's turn, attack once per turn but never on
their creation turn (summoning IS your attack), refuse to strike
their creators, and vanish when their creator dies. Attacks can
target creatures directly (no counteraction window — monsters don't
counter); Dispel Creation un-creates them. Plus MEGA-MONSTER (double
a monster's toughness or speed), ADRENALINE (two attacks a turn),
MAD DASH, and LIFESAVER. Expansion Set #2 confirmed by Eric as a
5e-era product — marked historical-only in the data; the 6e game is
exactly base + Expansion #1 (200 cards, all verified). Lobby gains an
"include Expansion Set #1" toggle; the client renders creatures as
diamond tokens with select-move-attack interaction. 95 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 22:41:54 -04:00
Eric WagonerandClaude Fable 5 1924114b6d Final wave: complete the 6th edition basic set (69/69 cards)
The hard six: AROUND THE CORNER attaches to any LOS attack and bends
the sight line through one intermediate cell. BLIND victims lurch in
die-rolled directions (bumping a wall costs the movement point, per
the card) and their attacks fly wherever the die says — hitting
whoever stands that way, or dissipating. UGLY drives every opponent
in sight fleeing along shortest paths (breadth-first, die-broken ties)
until they cannot see the caster. ILLUSION WALL is per-player reality:
each opponent rolls 50/50 the first time it matters and the wall is
real for believers forever — believers' views render it as a wall,
the caster and those who saw through it get a ghostly dashed line,
and Dispel Creation banishes it. ROTATE SECTOR turns a sector 90
degrees with every wall, door, wizard, treasure, object, firewall and
alteration turning in place (the home star, being the exact center,
never moves); RELOCATE SECTOR slides a sector anywhere that keeps all
sectors adjacent, reassembling the map and recomputing wraparounds.

Client: modifier attachment (Amplify/Add/Extend/Around The Corner),
two-stage relocate, rotation direction toggle, dashed known-illusions.
Every card in the 6th edition basic deck is now implemented.
81 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 20:29:09 -04:00
Eric WagonerandClaude Fable 5 2d88b4ab40 Card wave 3: terrain, thrown objects, drag, and control spells
Terrain layer: FILL SQUARE WITH STONE (impassable, blocks LOS via new
cell-blocking sight checks), THORNBUSH (enter = 1 damage + turn ends +
next turn lost; no attacking in or into a bush), WALL OF FIRE (new
firewall edge state — passable for 4 magical damage, blocks LOS,
expires with its duration), WATERWALL (instant wave: players within
two spaces washed back two, 1 damage per blocked space), and DISPEL
CREATION with provenance tracking (only conjured walls/fire/stone/
bushes dispel — printed maze is safe). Objects: DAGGER (3) and LARGE
ROCK (2) are physical throws Full Shield cannot stop; they land on the
floor and anyone may pick them up (ending their turn's actions, hand
limit enforced); DROP OBJECT forces a named object or carried treasure
to the ground; DRAG pulls floor objects, treasures, or players
straight toward the caster. Control: LOCK IN PLACE (no moving or
being moved — teleports, swaps, knockbacks and drags all respect it),
BUDDY (a pact the caster breaks by attacking), MIST-BODY (through
walls and doors, cannot attack or be attacked, still burns in
firewalls), REUSE SPELL (retrieve your last spell). Client renders
terrain, firewalls, and ground objects, with cell/edge/two-stage
targeting and card-name inputs. 40 cards implemented; 63 tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 20:13:14 -04:00
Eric WagonerandClaude Fable 5 36b3ffe9a6 Wire online multiplayer: game rooms, protocol, playable Svelte client
Server: room registry with 4-letter codes, host/join/start flow, the
authoritative command loop (seed + append-only command log per room —
the replay/async foundation), and per-player redacted views and events
broadcast after every change. Client: lobby, SVG board (floors, walls,
doors, homes, color-keyed treasures and wizard tokens matching the
physical set's six colors, warp arrows), click-to-move, click-to-punch,
card hand with tooltips from verified card text, cast flow with number
card attachment and waterbolt split, edge-click targeting for wall
spells, counteract-or-pass prompt, discard flow, end-turn draw
selector, and a humanized event log. Verified end-to-end over real
websockets with two clients: join, start, private deals, moves, turn
sync.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 19:52:10 -04:00