584 Commits
Author SHA1 Message Date
Eric WagonerandClaude Opus 5.5 3368a92cf5 A seat link is cut from a report to the end of its string, so a name with a quote, an ampersand or a hash in it cannot end the cut before the token
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
2026-10-17 20:14:41 -04:00
Eric WagonerandClaude Opus 5.5 6606853332 A seat link's token is cut from an error report and its breadcrumbs before it goes to Sentry, since the history breadcrumb for taking the link out of the address bar still names it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
2026-10-17 20:12:49 -04:00
Eric WagonerandClaude Opus 5.5 c984bb4b56 A crash report's strings reach the log on one line: anyone may post one, and a line break could otherwise forge another log line
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
2026-10-16 17:06:24 -04:00
Eric WagonerandClaude Opus 5.5 956c908867 Chromium's crash reports reach the server, which logs each and files it in Sentry as a warning, and the page's own errors name the room and seat and leave extensions' failures out
A tab that crashes takes the page's error reporting down with it, so the
page never says so. Every page now names a default Reporting API endpoint,
/api/reports, where Chromium sends a crash report after the fact; the
server logs the room, the reason when one is given, and the browser, and
files a warning that rings no bell. Other report types are ignored, and an
address may send ten an hour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
2026-10-16 17:03:14 -04:00
Eric WagonerandClaude Opus 5.5 9a1c98ca55 The host's phrase button says it makes a transfer phrase, and its tooltip says who it is for and how the player uses it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
2026-10-16 15:54:54 -04:00
Eric WagonerandClaude Opus 5.5 4b7e05713d The host can give a stuck player's seat to the clockwork and make a phrase that brings a seat back, and a socket in a background tab no longer drops every minute
A "seats" button beside "transfer seat" opens the host's panel. In a game
under way, "give to the clockwork" lets an automaton play a person's seat
from the next beat, with their hand, treasures and place untouched; a
standIn line on the ledger records it, the chronicle says so, the
stand-in never talks under the person's name, and the person's token
opens nothing after. "Make a phrase" mints the four-word phrase for any
person's seat; claiming it re-seats on a new token, and a seat the
clockwork stood in for goes back to its person mid-turn. A rematch holds
a stood-in seat for its person. The gallery now has its own claim box,
for a player who opens the invite link in a fresh browser.

The client's watchdog pinged and then closed a socket quiet for 45
seconds. A background tab's timers run about once a minute, so the last
pong was always a minute old when it looked, and idle tabs reconnected
every 58 seconds. It now closes only when its own ping went unanswered.
The server pings every socket at the protocol level every 30 seconds and
drops one that left the last ping unanswered, so a crashed browser's
socket no longer lingers until TCP gives up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
2026-10-16 15:43:24 -04:00
Eric WagonerandClaude Opus 5.5 7ef0c1bc14 On a phone, the table fits the screen and another wizard's turn says whose it is
The masthead's links never wrapped, so a game widened a phone's page to
nearly 500px: the page scrolled sideways and the opening roll-off sat off
its centre. And while an automaton's opening turn played back, the rail
that says "Automaton is taking their turn" sat below the fold, leaving a
board that moved on its own. Of 132 bot-first games, 13 humans never made
a move. Now the links wrap, and a caption over the board names the wizard
whose turn it is, and says when yours is next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:35:39 -04:00
Eric WagonerandClaude Opus 5.5 5ea0d4fdec The keeper can bring back a seat a browser lost: a reseat line on the ledger gives that wizard's seat a new token and the old one opens nothing after, wizwar-reseat.sh on the host asks for it through a keeper door that listens on the loopback alone and opens only to a key the deploy makes once, and the link it prints carries the seat in the fragment, which leaves the address bar at once and is kept only when no seat held in this browser still opens and the server takes it; a gallery watching a game in play is told both ways back, the front page asks before forgetting a game not yet finished, and the server's tests now run with the rest
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MbtUPJ24P6vc6tE1x6RS3m
2026-10-13 18:33:04 -04:00
Eric WagonerandClaude Opus 5.5 1b9acfd7c4 The family list carries the kit's current pitches
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MbtUPJ24P6vc6tE1x6RS3m
2026-10-13 09:29:58 -04:00
Eric WagonerandClaude Opus 5.5 6f86076712 The hosting line says what it promises: chipping in unlocks nothing, and nothing is held back without it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MbtUPJ24P6vc6tE1x6RS3m
2026-10-13 09:23:44 -04:00
Eric WagonerandClaude Fable 5.1 636d97d5c1 The nightly rollup and backup say by their exit status whether they managed, and the deploy leaves the cron file off a host the hall schedules
On the shared host the hall's hall-nightly.sh (game-kit, gamehall/ops) runs
both scripts for every game and checks in with Sentry Crons once for all,
so this game's own check-in files are absent there and its exit status is
the word. A box of its own keeps its cron and check-ins as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-12 10:07:06 -04:00
Eric WagonerandClaude Opus 5.5 c64ff70ed4 The table speaks plainer, and keeps its whimsy
Wording throughout the app, the server's messages and the engine's
refusals trades its stacked dashes for sentences, while the maze still
trusts you to honor its curses, the gallery still listens, and the
clockwork still learns its best tricks from the humans at the table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:29:07 -04:00
Eric WagonerandClaude Opus 5.5 ad23c83b8a The rollup and the backup check in once, when they end, with the run's duration
A start and a finish sent seconds apart can reach Sentry in either order,
and a start that lands second is never closed, so a fast rollup could be
reported as a timeout on a night it succeeded. Hnefatafl's monitor did so
nine nights in fifteen on the shared host. One check-in at the end cannot
race; a run that hangs sends nothing and is marked missed. Installed on
the host by hand; the next deploy installs the same files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwFKMuQnPAEHJ5yA1q4orh
2026-10-10 17:50:55 -04:00
Eric WagonerandClaude Opus 5.5 aeb58bdf4a A treasure carried home says so, and a turn out of steps points at End turn
A first-time player banked a stolen chest, stepped off with no moves left,
and left (NQ6S): the score changed only in the turn bar's quiet tally, and
a still board with no word read as a game that had stopped. Now a slip
announces the score for the rest of the turn, and once the steps are
spent the turn bar says to cast or end the turn while End turn beckons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:36:27 -04:00
Eric WagonerandClaude Opus 5.5 ceb22a9898 A stale tab's reload no longer throws: a retired chunk resolves to nothing, and nothing is mounted
The preload-error handler claims the failed import and reloads; the import
then resolves empty, and destructuring its default threw (WIZWAR-X).

Fixes WIZWAR-X

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZtFMp1AtjXPBY4Z69Tx81
2026-09-30 12:06:34 -04:00
Eric WagonerandClaude Opus 5.5 cbf897ff13 Pages show the hall-wide notice, when there is one, at the top
The keeper's hall-announce writes one file on the shared host; the site
serves it at /hall/announcement.json, and the banner shows it with the time
in the reader's own clock, dismissable one notice at a time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 13:03:37 -04:00
Eric WagonerandClaude Opus 5.5 397c68a1c8 Wiz-War lives on the shared hall host: its scripts, skills and docs name it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 12:52:36 -04:00
Eric WagonerandClaude Opus 5.5 56ea593e07 A deploy ships the engine's own data: only the top-level ledger folder is left behind
The exclusion for local game data matched any folder named data, so the
cards and boards the server reads never shipped after the droplet's first
setup; the live copy of cards.json had drifted to August's (text of FAQ
rulings, and rows of a set this edition does not deal). All 198 production
ledgers replay clean with the current data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 12:48:04 -04:00
Eric WagonerandClaude Opus 5.5 811d5f84cb Wiz-War's host follows the hall's shared layout: its own Caddy site file, its own access log, a memory cap for a shared box
The host's Caddyfile gathers each game's site from /etc/caddy/sites/;
Wiz-War's is rendered from deploy/Caddyfile.tmpl and logs to
wizwar-access.log, which the rollup and the pulse read. The server's memory
cap drops from 700M to 350M (it runs in about 125M), so a runaway cannot
starve other games sharing the box. Applied on the live droplet with its
logs renamed in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 12:37:06 -04:00
Eric WagonerandClaude Opus 5.5 d5b92d9a63 The about panel no longer credits its making
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-27 20:58:56 -04:00
Eric WagonerandClaude Opus 5.5 a4196480ce A socket's own error closes that socket, not the server
A message over the size limit or a malformed frame raised an error on
the socket, which had no listener, and Node ended the process: one
message from anyone could take the server down until systemd restarted
it. The socket is terminated instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-27 01:21:45 -04:00
Eric WagonerandClaude Opus 5.5 3a6b0ff43e Credibility pass: the illusion tests roll both ways, and the seams from the last batch are sanded
Scope: 66b5c06..HEAD.

- The rev-27 illusion tests search seeds for a believed and a doubted
  roll and assert fixed life totals; seed 42 alone never believed, so
  the BLUNT pricing went unchecked.
- Three docblocks stranded above newly inserted functions are back on
  their own (openCreatureStack, resolvedBlow, castTrace).
- POWER ATTACK's life trade is one helper instead of three copies; the
  goat's charge distance is one helper for its validator, its ram and
  its pricing.
- The family list loads once into a shared store; the lobby and gallery
  share one talk filter; Board uses the engine's neighbor().
- A creature's blow shows the card that summoned it by the creature's
  kind, not by matching the blow's display name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-26 00:22:20 -04:00
Eric WagonerandClaude Fable 5.1 e97deb8d6f A commanded troll lights only the walls and doors beside it, and so does a punching wizard
Every interior line lit whenever an edge was wanted; the troll can strike
only the four sides of its own square, so only those light now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 21:37:13 -04:00
Eric WagonerandClaude Fable 5.1 7a0a972452 A creature's blow is named on the stack: the counter is played against the fire imp's scorch, not a punch (SC59)
The caster whose creature is countered now sees "your attack, answered"
and the name of their own blow, instead of an incoming punch with the
opponent's counter card standing in the attack slot.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 21:32:34 -04:00
Eric WagonerandClaude Fable 5.1 c3f63d4eb7 Rev 27: an ILLUSIONARY ATTACK is priced as the spell it fakes, so BLUNT and the rest meet it (UPJE)
The believed illusion was dealt after the counter trail had already
spoken over a zero, so a BLUNT trailed for nothing and the full points
landed. Now the fake carries its spell's points through the pipeline and
the belief roll decides whether the weighed blow lands. Games dealt under
rev 26 and before replay as they were.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 20:40:47 -04:00
Eric WagonerandClaude Fable 5.1 991a6a0443 ROTATE SECTOR asks which way: the tap marks the sector, a button turns it (UPJE)
The clockwise checkbox sat in the hint strip and defaulted on, so a
sector could spin the way nobody meant. The turn is now its own decision,
in the dock beside the board like the teleport confirm.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 20:30:37 -04:00
Eric WagonerandClaude Fable 5.1 6c29f750fc A waterwall tapped onto a slime washes it: the tap picks the face across the caster's approach (B8G9)
The flash for a corridor-line card no longer names wizards, bushes and
slimes as its targets; it gives the card's own line hint.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 22:59:14 -04:00
Eric WagonerandClaude Fable 5.1 0244cffb4b The family list knows the hall: about panels link to gamehall.kestrelsnest.social, and a new game gets a card there
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 21:04:31 -04:00
Eric WagonerandClaude Fable 5.1 9f1358496d The about panel says the games are free and where the hosting tip jar is
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 20:25:05 -04:00
Eric WagonerandClaude Fable 5.1 c79fdb4adb The collection is Kestrel's Hall
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 19:51:06 -04:00
Eric WagonerandClaude Fable 5.1 9d087ccaa1 The front page and the about page point to the other games of the Kestrel's Nest
The list is the kit's family.json, shipped as /family.json and refreshed
at deploy when the kit is beside this checkout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 12:26:49 -04:00
Eric WagonerandClaude Fable 5.1 13a6fc2603 The host may let the Peanut Gallery talk
A gallery line wears the eye and a name that no wizard at the table
holds; the host opens or hushes it from the lobby or the mast, on the
ledger, and the gallery is reined per address.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 09:47:26 -04:00
Eric WagonerandClaude Fable 5.1 f68b3cef06 The desk's replies no longer ring the bell: reports and players' answers do, the desk's own mail does not
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 08:54:08 -04:00
Eric WagonerandClaude Fable 5.1 35d805fda3 The lobby tells a caller what hour it is where the keeper lives, and that other games can go on in another tab
WIZWAR_KEEPER_TZ names the zone (Eastern by default); the room carries it
and the client words the hour by the minute.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 08:49:37 -04:00
Eric WagonerandClaude Fable 5.1 31bfcf7bc0 Rev 26: BUTT-HEAD's ram is priced into the blow, so STRENGTH, AMPLIFY, and the counters weigh it (KWUZ)
Ramses cast STRENGTH, then an amplified BUTT-HEAD three squares off, and
the goat dealt three: the ram was applied in onResolved, past the pipe
that doubles, soaks, and adds. Older games keep the bare distance.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 08:16:30 -04:00
Eric WagonerandClaude Fable 5.1 5193b12b8e Rev 25: a bush or the ooze is attacked like a wall — POWER ATTACK counts, thrown weapons land at its foot
Older games took neither; both sides pinned.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 12:19:15 -04:00
Eric WagonerandClaude Fable 5.1 66b5c06f17 Credibility pass: one teleport step, one bell, one step type, and the comments that argued are gone
Since 6e49fc9. Engine: the teleport BFS in the view and the engine's
wallIgnoringDistance share teleportStep; the counter trail is weighed
between steps instead of on six arms; the bush attack takes its
adjacency from SIDES like the wall does; a dead redirected clause, a
one-member set, an identity ternary, and a stray try/catch are gone;
two tests now assert what their names promise. Server: KEEPER and
MAX_SEATS live in rooms.ts, the three Sentry bells ring through one
helper, the unread reply field is dropped, actingSeat comes from the
engine, and the protocol header names every message. Web: ReplayStep
is one type, cardName one helper, the say box and the reference section
one snippet each, the keeper's name arrives from the server rather than
the source, and the lifesaver ruling that ruled nothing is out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:56:49 -04:00
Eric WagonerandClaude Fable 5.1 c4a555f8df Fuller banter pools, and the blow's own names decide who dealt pain and who killed
Damage lands on the defender's step, so a trigger keyed to the actor
never credited the attacker: across thirty three-bot games the kill line
fired zero times and the dealt-pain line five, against 328 takes. Both
now read the attackResolved, punched, and died events themselves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:39:05 -04:00
Eric WagonerandClaude Fable 5.1 be96dd6047 The archmage cuts off a winning delivery and aims at the leader when no kill is on the table
Reuben's three wins today were walked home unseen: the clockwork
fought whoever stood in front of it. Now a delivery that would end the
game pulls every automaton toward that wizard's home (where the banked
gold is lifted off the doorstep) or the road to it, and among visible
targets the thief still dies first, a kill is still taken, and only then
does the aim shift to whoever has more treasures banked. Measured with
deploy/brain-trial.mjs, which seats the working tree's brain against an
older checkout's at one table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:11:34 -04:00
Eric WagonerandClaude Fable 5.1 1b18dffd28 sentry-slack-alert.sh parses again
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 15:26:42 -04:00
Eric WagonerandClaude Fable 5.1 46c345dff4 deploy/sentry-slack-alert.sh routes every wizwar issue to a Slack channel, token from the shell
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 15:18:08 -04:00
Eric WagonerandClaude Fable 5.1 11e9f950c6 Reports are threads, and every turn of one rings the desk's bell
A player answers the desk under its reply from their lobby, proven by
the seat the report was filed from; the lobby shows the exchange in
order and says whose word is pending. A new report, a player's answer,
and a desk reply each raise a Sentry issue on the keeper's phone — the
first two from the server, the last from the reply script itself,
straight to Sentry from the droplet. The Desktop digest lists the
answers, and the desk's rule reads a report as reopened when the last
word is the player's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 12:08:55 -04:00
Eric WagonerandClaude Fable 5.1 ffbca5bfb9 deploy/pull-feedback.sh mirrors reports, replies, and screenshots to the Desktop with a digest
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 11:11:42 -04:00
Eric WagonerandClaude Fable 5.1 071e7ce988 A permanent spell settles 'for good' in the chronicle and the receipt, not for a billion turns
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 11:09:01 -04:00
Eric WagonerandClaude Fable 5.1 48350a3686 A report may carry a screenshot
The 🐞 form takes a picture beside its words — PNG, JPEG, or WebP, under
2.5 MB, previewed before sending. The socket's message cap is far too
small for one, so the picture goes through a plain HTTP door after the
report is filed, addressed to the report's id, one per report within
the hour, checked by its own first bytes, and kept in feedback-images/
beside the reports with a line on the report saying so. The desk's
skill knows where to look.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 11:02:59 -04:00
Eric WagonerandClaude Fable 5.1 d76a18d5e6 A seated wizard leaves the room's expected list, live and on rebuild
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 23:45:36 -04:00
Eric WagonerandClaude Fable 5.1 1ebd6dbe47 A refused seat is logged, and the wallet drops a seat only on the second refusal in a row
A lost seat mid-game is the costliest quiet failure this table has: one
refusal around a restart cost Kestrel PRPM's seat with nothing in the
journal to say why.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 23:22:00 -04:00
Eric WagonerandClaude Fable 5.1 f738957100 Rev 24: a REFLECTION against a permanent curse afflicts both wizards
"If this spell is REFLECTed, both players take 1/2 point of damage per
space moved" (WALKING DEAD); "In case of REFLECTION, both players are
affected" (IDIOT); SLOW DEATH follows REFLECTION's own rule that a
spell works for both parties. A permanent curse has no duration for
the reflection's split to halve, so the caster went untouched; the
curse is now laid on them as well, as if cast back. Older games replay
as they were; PRPM, reflected at seq 108 with no move since, was
re-stamped to 24 at its table's request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 23:07:41 -04:00
Eric WagonerandClaude Fable 5.1 f26893f45b The reel measures its padding inside its width, so it stays within the share page on a phone
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 21:18:35 -04:00
Eric WagonerandClaude Fable 5.1 942e04c821 The reel fits a phone: title on its own line, a smaller caption, controls that stay on screen
The shared replay page had no rules for a narrow screen: the reel's
header stacked into a column, the caption ran large, and the controls
ran off the right edge. Under 640px the title takes its own line with
the count and buttons beneath, the caption reads smaller, and the
controls wrap. The share page also pins its text size against
Safari's inflation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 21:11:48 -04:00