0.7.9.8:0 — bundle Station Master v0.7.9.8
Eight releases of fixes since v0.7.9, most of them multiplayer, which is
what this package is for. Submodule pin and `startos/versions/current.ts`
only — no Dockerfile, main.ts or manifest change, as an ordinary bump
should be.
Bumped in place rather than spun off: v0.7.9's migration body is empty,
which is `versions.md`'s common case, and git history keeps its release
notes.
FOUR-COMPONENT VERSION, CHECKED. Every example in `versions.md` has
three, so `0.7.9.8:0` was parsed with the SDK's own ExVer parser before
being written down: upstream `[0,7,9,8]`, which sorts above `[0,7,9]`, so
a box on 0.7.9:0 takes this as an update rather than refusing it as a
downgrade.
GAMES IN PROGRESS ON THE BOX RESUME, and that was established rather than
hoped for. v0.7.9 broke solitaire saves because it changed a RULE, and
the rule behind that is that a save is a seed plus the moves played,
replayed through the CURRENT rules — so the question for any bump is
whether something became illegal. `git diff v0.7.9..HEAD -- src/engine/`
is, in full: `isExpedited` exported and widened to a structural parameter
type, `isFreight` exported, one new read-only helper
(`freightRuleSpentHere`, which only the blocked panel asks), and
`check('draw.end')`'s inline hand-limit test replaced by a call to
`overHandLimit(state, player)` holding the identical expression. No
predicate changed its answer. The release notes say so in all five
locales rather than leaving it to be discovered.
UPDATING.md CORRECTED: it said a running server's saves "are stamped with
`engineVersion` and refuse to resume under a mismatched one". They are
stamped with it and it is reported, but `src/server/index.ts` decides by
attempting the replay and names the versions only inside the failure
message — its own comment says why, that "some version differs" was never
enough to act on. A doc that sends the next person to schedule downtime
for a bump that needs none costs about as much as the reverse. It now
carries the diff command to ask the question of the code instead.
What players get, briefly: two multiplayer information leaks closed (the
seed in the shared log, and a blind Home Office draw naming its card); a
history panel that came back EMPTY after a mid-game browser reload; the
extended-play vote no longer naming an arbitrary player when the vote is
open to everyone at once; a train held at your Limits by an Interlocking
no longer vanishing off the board until a track frees; trains queued for
a Crew Tray saying so with the free count; a Red Flag drawn on the map; a
spent Telegraph/Telephone/Radio struck through; the Campaign Train saying
whether its speeches are made; and two bugs from the last playtest — the
Express's one-freight-car-per-location rule explained where it refuses
you, and westbound trains drawn in the correct half of a card.
README.md and instructions.md updated in the same change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5boPxP6JHRYMm8adXaF5R
This commit is contained in:
@@ -13,6 +13,59 @@ Station Master is a railroad operations board game with an authoritative multipl
|
||||
solitaire needs no server and is not what this package is for. This package runs that server —
|
||||
the browser client, the lobby, and the intent/SSE API — as a single StartOS service.
|
||||
|
||||
**Bundled version: 0.7.9.8.** Eight releases of fixes since 0.7.9, most of them multiplayer, and
|
||||
**games in progress on this server resume normally** — which was checked rather than assumed.
|
||||
|
||||
**Why saves are safe this time, and how that was established.** 0.7.9's breakage came from a rules
|
||||
change, and the general rule behind it is that a save is a seed plus the moves played, replayed
|
||||
through the *current* rules — so any change that makes a once-legal move illegal stops an older save.
|
||||
The question for this bump is therefore narrow: did anything become illegal? `git diff v0.7.9..HEAD
|
||||
-- src/engine/` is, in its entirety, four things — `isExpedited` exported and widened to a structural
|
||||
parameter type, `isFreight` exported, one new read-only helper (`freightRuleSpentHere`, which only
|
||||
the blocked panel asks), and `check('draw.end')`'s inline hand-limit test replaced by a call to
|
||||
`overHandLimit(state, player)` holding the identical expression. **No predicate changed its answer.**
|
||||
Eight releases, none of them in the rules.
|
||||
|
||||
Note that `engineVersion` is *not* a gate. `src/server/index.ts` attempts the replay and reports the
|
||||
stored and running versions only in the failure message; a game is refused because a move no longer
|
||||
replays, never because the version string differs.
|
||||
|
||||
**Two multiplayer information leaks.** The random seed was announced in the shared narration log at
|
||||
game creation, and a blind Home Office draw resolved the drawn card to its real name for every seat.
|
||||
Both were found by reading a plan rather than by a test, which is why 0.7.9.4 added a systematic
|
||||
redaction net: a seat's Frame, the spectator projection and the narration are serialised and searched
|
||||
for every opponent card id, every card name unique to one hand, the seed, and any private decision
|
||||
data — with an allow-list of every public property that fails the suite when a field is added.
|
||||
|
||||
**The history panel came back empty after a mid-game reload.** `Frame.lines` carried the whole
|
||||
narration log on every push to every seat and nothing read it — `RemoteSession` accumulates from
|
||||
`Push.lines` alone. The waste was masking the fault: `connect()` cleared the frame cache but not the
|
||||
narration watermark, so a reconnecting seat was told "nothing new since your last push" while the
|
||||
browser it was answering had just reloaded from an empty accumulator.
|
||||
|
||||
**Whose turn it is, during the extended-play vote.** The §3.3 vote is parallel — every un-voted seat
|
||||
may vote at once — so there is no actor to be, and the engine says so. The turn chart named the last
|
||||
seat to move anyway, beside a tally correctly showing three seats outstanding. Cause: two functions
|
||||
answering one question, one carrying a status guard and one not; there is one now, and it is the same
|
||||
function that *refuses* an intent, so the screen can no longer name somebody the server would turn
|
||||
away.
|
||||
|
||||
**A train held at the Limits was drawn nowhere.** An Interlocking stops an inbound train on the Limit
|
||||
Track instead of colliding with a full Office. `arriveAtOffice` removes the tray from the Mainline
|
||||
node's `transits` and the Interlocking branch never assigns `tray.position`, so with the map drawing
|
||||
mainline nodes from `transits` and squares from `position.at === 'grid'`, the train was in neither —
|
||||
it vanished off the board until an A/D track freed. Fixed in the view; the engine state was right.
|
||||
|
||||
**Also in this range.** Trains queued for a Crew Tray (a Timetabled departure, a played Extra, an
|
||||
ordered second section) now report themselves with the free-tray count, where two of the three had
|
||||
been waiting invisibly behind an exhausted pool. A Red Flag standing at an Office's Limits is drawn
|
||||
on the map. A spent Telegraph/Telephone/Radio is struck through and says when another district holds
|
||||
the Fedora — it is the Superintendent's own devices that get spent, and the Fedora moves every three
|
||||
Stages. The Campaign Train says whether its speeches are made, which is what decides whether leaving
|
||||
it off the Office square is a fault. Two bugs from the last playtest session: the Express's one
|
||||
freight car per location rule is explained where it refuses you (the panel had been describing the
|
||||
industry instead), and westbound trains are drawn in the correct half of a Mainline card.
|
||||
|
||||
**Bundled version: 0.7.9.** Enforces solitaire's collision limits, which had been offered as
|
||||
settings and never checked — and that is a rules change, so **a solitaire game in progress will not
|
||||
resume if it has had collisions**.
|
||||
|
||||
Reference in New Issue
Block a user