0.7.9:0 — bundle Station Master v0.7.9

Submodule pinned to v0.7.9 (6058f6c), current.ts bumped in place, release
notes rewritten in all five locales, README.md and instructions.md
updated. No new version file and no migration: the outgoing 0.7.8:0's
`up` was empty, which is versions.md's common case.

GAMES IN PROGRESS DO NOT CARRY OVER, and both docs lead with it.

v0.7.9 changes a rule. advance.ts gated §3.4's collision check on
`mode === 'competitive' || mode === 'coop'`, while SOLO_CONFIG carried
both limits (3 a Day, 5 total) and the setup screen offered them as live
settings with "the game ends in a loss" printed beside them. A solitaire
player could set a limit of 1 and crash all game. Jesse's ruling was that
the settings do what they say, so the gate went rather than the controls.

A solitaire save is { seed, history, rules? } where `rules` is the house
rules only — the collision caps are NOT in the save, so a restore takes
today's defaults. A 0.7.8 save therefore replays under live caps and
stops at the move that crossed one.

MEASURED WITH A CONTROL, because two earlier attempts at measuring it
were wrong. With the caps disabled, 1200 of 1200 generated solitaire
saves replay every intent — that is the control. Of those, 74 games
crossed the 5-collision total and 70 of the 74 truncate once the caps
are enforced; one replays 141 of its 532 intents and stops. So it is
"will break for anyone who crashed", not "may break". The earlier run
that reported no breakage had in fact been failing every replay at
intent 2 on an unrelated house-rules mismatch, and said nothing at all —
the control is the only reason that was caught.

It fails safe: the save is left untouched and the game declines to open
rather than loading a position the rules could not have produced, so a
player who cares can put 0.7.8 back and finish. Nothing in this package
can act on it either way — a solitaire save lives in the player's own
browser, not on this server. MULTIPLAYER GAMES ARE UNAFFECTED:
competitive and coop have been inside that gate all along.

TWO THINGS FIXED IN PASSING, both pre-existing and both in the way of
the release check. UPDATING.md was not prettier-formatted. And there was
no .prettierignore, so `prettier --check .` walked the bundled
application — a separate repo with its own style, which this package does
not own and does not commit — and reported 171 warnings it could do
nothing about. That check now passes clean, which is the point of having
it in the release sequence at all.

Verified: npm run check clean, prettier clean, make x86 packs as
v0.7.9:0. NOT yet installed on a box and NOT played.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YTaNBL1jVxNqgFdjHkHoo3
This commit is contained in:
Jesse
2026-08-30 20:41:27 -04:00
co-authored by Claude Opus 5
parent 3b7b334968
commit bd802cb512
6 changed files with 169 additions and 67 deletions
+9
View File
@@ -0,0 +1,9 @@
# The bundled application is a separate repository with its own formatting, checked out here as a
# submodule. Formatting it from the wrapper would rewrite files this repo does not own and does not
# commit — and leaving it in scope meant `prettier --check .` reported 171 warnings it could do
# nothing about, which is a check nobody can read.
station-master/
# Build output.
dist/
*.s9pk
+37 -6
View File
@@ -13,7 +13,38 @@ 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.8.** Makes the solitaire setup screen reachable at all. 0.7.5 skipped it
**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**.
`advance.ts` gated §3.4's check on `mode === 'competitive' || mode === 'coop'`, while `SOLO_CONFIG`
carried both limits (3 a Day, 5 total) and the setup screen offered them as live settings with "the
game ends in a loss" printed beside them. A solitaire player could set a limit of 1 and crash all
game. Jesse's ruling: the settings do what they say, so the gate went rather than the controls.
**Why saves break, and how it was measured.** A solitaire save is `{ seed, history, rules? }` where
`rules` is the house rules only — **the collision caps are not in the save**, so a restore takes
today's defaults. A 0.7.8 save therefore replays under live caps and stops at the move that crossed
one. Measured with a control, because two earlier attempts were wrong: with the caps disabled 1200
of 1200 generated saves replay every intent; of those, 74 crossed the 5-collision total and **70 of
the 74 truncate** once the caps are enforced, one at 141 of its 532 intents. An earlier run that
reported no breakage had in fact been failing every replay at intent 2 on an unrelated house-rules
mismatch — the control is what caught that. It fails safe: the save is untouched and the game
declines rather than loading a position the rules could not have produced. **Multiplayer games are
unaffected** — competitive and coop were always inside that gate.
**Also in 0.7.9.** The end-of-game dialog now asks whether to play one more Day; the buttons existed
but were written into `#actions` _underneath_ a modal whose only control was Close, so a solitaire
player reaching the end was never offered the extension — and the Gitea#11 verification missed it
because it drove the HTTP API, which renders no dialog. `Frame.actor` carried `clock.currentActor`,
null for the whole Mainline Phase, so all three interruptions reported that nobody was holding the
game up; it carries `actingPlayer` and an `awaiting` field now. The game settings moved off the top
line into a **This Game** card drawn by the same renderer as the lobby's join preview, with the
running collision counts taking their place on the top line. The Office Area's auto-hide button was
a cycle that could not reach every state and is now three controls. The history reads newest first.
A Heavy Grade card draws which way it climbs.
**Bundled version: 0.7.8.** Made the solitaire setup screen reachable at all. 0.7.5 skipped it
whenever `load()` found a saved game — reasoned as "a saved game is a game to resume" — and a browser
that has ever played solitaire always has one, so the door could never reach the screen again. The
door (`?solitaire`) outranks a save now; a bare reload still resumes. Since dealing calls
@@ -117,7 +148,7 @@ same server it always was.
Built from source with a custom `Dockerfile` — there is no published Station Master image.
| What to Document | Value |
| --- | --- |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Image source | Custom multi-stage `Dockerfile`: `node:*-slim` builder runs `npm run build:web` to produce the static client, then a second `node:*-slim` stage copies only `package.json`, `src/`, and the built `dist/` — no `node_modules` in the runtime stage, since the server has zero runtime dependencies |
| Architectures | x86_64, aarch64 |
| Entrypoint | `node src/server/index.ts` — runs straight from TypeScript source; no compile step, see Limitations |
@@ -129,7 +160,7 @@ One subcontainer: `station-master-sub`, running the single daemon `server`.
One volume, `data`, mounted at `/data` (`DATA_DIR`).
| What to Document | Value |
| --- | --- |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Volume names | `data` |
| Mount points | `/data` |
| StartOS files | `store.json` — holds the join and admin secrets (see File Models) |
@@ -179,7 +210,7 @@ has been retrieved and shared with them.
**Updating the package keeps games in progress, unless the rules actually changed.** On boot the
server replays each saved game's moves through the current engine and resumes it if they all still
apply — the version that wrote the file is recorded and reported but decides nothing. When a move
*is* rejected, that game is refused and the log names it: `move 3 of 8 (localOps.choose) is
_is_ rejected, that game is refused and the log names it: `move 3 of 8 (localOps.choose) is
rejected by the current rules with OPTION_ALREADY_CHOSEN`. A refused game is never modified or
deleted, so reinstalling the previous version makes it loadable again and it can be played out.
@@ -225,8 +256,8 @@ answer.
## Health Checks
- **Multiplayer Server** — fetches the server's own `/api/health` and reports what it says:
*"Multiplayer server is ready — 3 games in progress"*, with *", 1 waiting to start"* appended
only when a lobby exists, and *"no games in progress"* on an idle server. So the check that
_"Multiplayer server is ready — 3 games in progress"_, with _", 1 waiting to start"_ appended
only when a lobby exists, and _"no games in progress"_ on an idle server. So the check that
proves the server is answering also says how much is going on.
A server that does not answer is reported as **starting, never failed**. The server replays its
+3 -3
View File
@@ -37,13 +37,13 @@ change is packaging-only and the bundled game has not moved.
> The initial release shipped as `1.0.0:0` — the scaffold's placeholder, left in by mistake while
> the game was at 0.5.1. It was corrected to `0.5.2:0` before the package was ever published
> anywhere, which is the only reason a downgrade was harmless: `0.5.2:0` sorts *below* `1.0.0:0`,
> anywhere, which is the only reason a downgrade was harmless: `0.5.2:0` sorts _below_ `1.0.0:0`,
> so an installed copy had to be removed rather than updated over.
## Building a test package from work that is not pushed yet
The Dockerfile copies `station-master/` out of the build context, so what is packed is whatever is
in that directory — the submodule's *pin* only matters for reproducibility, not for `make`. That is
in that directory — the submodule's _pin_ only matters for reproducibility, not for `make`. That is
what makes it possible to put a build on a test box before the game is committed, tagged or pushed,
which is how v0.7.0 was played before release:
@@ -62,7 +62,7 @@ cd .. && make x86 && make install
update, not a re-install, so a rebuild at the same version has nothing to install over; and the
downstream half is exactly the right one to move, since the upstream game has not been released
again between two test packs. Whichever digit the box ends up on is the one the real release should
carry: publishing a *lower* one afterwards is a downgrade the box will refuse.
carry: publishing a _lower_ one afterwards is a downgrade the box will refuse.
**Before committing the wrapper**, put the pin back on a real tag — a submodule pointing at a commit
that only exists on one machine is a package nobody else can build:
+21 -1
View File
@@ -35,6 +35,26 @@ watches the table — there is nothing else to open.
Solitaire runs entirely in your own browser and needs nothing from the server, so it works here
exactly as it does on the public Station Master site.
**What changed in 0.7.9. Read this part first: your saved solitaire game may not reopen.** Solitaire
has always had two collision limits — 3 in a Day and 5 in a game — and the setup screen has always
offered them and said that reaching one ends the game in a loss. They were never actually checked.
They are now. A saved solitaire game in which trains have collided will therefore refuse to reopen,
because the moves it recorded are no longer all legal. **Nothing is destroyed:** the save is left
exactly as it was and the game simply declines to load it, rather than opening something the rules
could not have produced. If you have a solitaire game you care about, finish it before updating.
**Multiplayer games on this server are not affected.**
The rest of 0.7.9 is things you can see. **The end-of-game screen now asks whether to play one more
Day** — the question was being drawn underneath the results dialog, so a solitaire player reaching
the end of the timetable was never offered it. **"Waiting on" now names the person and what they are
being asked**, instead of saying nobody was holding the game up while it waited on the
Superintendent. **The game's settings have moved off the top line into a This Game card** at the foot
of the right-hand column, where all of them are listed rather than the four that fitted; the running
collision counts take their place at the top, since those change as you play. **The Office Area's
show/hide button is now three buttons** — auto-hide, always show, always hide — because as a single
cycling button it could not reach every setting. **The history now reads newest first.** And **a
Heavy Grade card shows which way it climbs**, instead of only saying so in its tooltip.
**What changed in 0.7.8.** The solitaire setup screen now appears for everyone. It was being skipped
whenever your browser held a saved solitaire game — and any browser that has ever played holds one —
so most players never saw it at all. Clicking **Play solitaire** now always asks how you want the
@@ -65,7 +85,7 @@ over**, both here and on the multiplayer server, without exception.
**Setting a game up (new in 0.7.0).** The lobby opens on **Join a game**: type the code you were
given and you will see the whole rule set — the opening hand, what the work pays, every way the game
can end — *before* you take a seat. Creating a game instead starts from a **game type**: Co-op,
can end — _before_ you take a seat. Creating a game instead starts from a **game type**: Co-op,
Competitive or Cutthroat. A type just fills in the rules; every one of them is yours to change, and
changing any of them marks the game **Custom**, which keeps the scoring of the type you started
from. The seed, the number of players and the number of Days sit above the type and do not make a
+89 -47
View File
@@ -5,63 +5,105 @@ export const current = VersionInfo.of({
// (`versions.md`'s consistency checklist), so bumping the submodule pin and bumping this are one
// action. The downstream half moves only for packaging-only changes, and RESETS to `:0` when the
// upstream half moves.
version: '0.7.8:0',
version: '0.7.9:0',
releaseNotes: {
en_US:
'Bundles Station Master v0.7.8 \u2014 the solitaire setup screen finally works for everyone. It was ' +
'skipped whenever your browser held a saved solitaire game, and any browser that has ever ' +
'played holds one, so most players never saw it at all. Clicking Play solitaire now always ' +
'asks how you want the game set up. Your game in progress is safe: the screen offers Continue ' +
'saved game, and says plainly that dealing a new one replaces it. Simply reopening the page ' +
'still resumes where you left off, as before. The homepage footer now also names both ways to ' +
'play. No rules changed; games in progress are unaffected.',
'Bundles Station Master v0.7.9. — READ FIRST: SOLITAIRE GAMES IN PROGRESS DO NOT CARRY OVER. ' +
"Solitaire's two collision limits (3 in a Day, 5 in a game) were offered as settings, said the " +
'game would end in a loss, and were never actually checked. They now do what they say — so a ' +
'saved solitaire game that has had collisions will refuse to reopen. It fails safe: the save is ' +
'left untouched and the game simply declines rather than corrupting anything. Finish what you ' +
'care about before updating. Multiplayer games on this server are unaffected. Also in this ' +
'release: the end-of-game screen now asks whether to play one more Day, a question that was ' +
'being drawn underneath it and could not be reached; "waiting on" names the person and what ' +
'they are being asked, instead of saying nobody; the game settings moved off the top line into ' +
'a This Game card, with the running collision counts taking their place; the Office Area ' +
'show/hide control offers all three modes instead of cycling past one; the history reads newest ' +
'first; and a Heavy Grade card now shows which way it climbs.',
es_ES:
'Incluye Station Master v0.7.8: la pantalla de configuraci\u00f3n del solitario por fin funciona para ' +
'todos. Se omit\u00eda siempre que el navegador ten\u00eda una partida de solitario guardada, y cualquier ' +
'navegador que haya jugado alguna vez tiene una, as\u00ed que la mayor\u00eda de los jugadores nunca la ' +
'vio. Al pulsar Jugar en solitario ahora siempre se te pregunta c\u00f3mo quieres configurar la ' +
'partida. Tu partida en curso est\u00e1 a salvo: la pantalla ofrece Continuar partida guardada e ' +
'indica claramente que repartir una nueva la reemplaza. Volver a abrir la p\u00e1gina sigue ' +
'retom\u00e1ndola donde la dejaste, como antes. El pie de la p\u00e1gina de inicio ahora tambi\u00e9n nombra ' +
'las dos formas de jugar. Las reglas no han cambiado; las partidas en curso no se ven afectadas.',
'Incluye Station Master v0.7.9. — LEE ESTO PRIMERO: LAS PARTIDAS DE SOLITARIO EN CURSO NO SE ' +
'CONSERVAN. Los dos límites de colisiones del solitario (3 por Día, 5 por partida) se ofrecían ' +
'como ajustes, decían que la partida terminaría en derrota y nunca se comprobaban. Ahora hacen ' +
'lo que dicen, así que una partida de solitario guardada que haya tenido colisiones se negará a ' +
'abrirse. Falla de forma segura: el archivo guardado queda intacto y la partida simplemente se ' +
'niega, sin corromper nada. Termina lo que te importe antes de actualizar. Las partidas ' +
'multijugador de este servidor no se ven afectadas. Además: la pantalla de fin de partida ya ' +
'pregunta si quieres jugar un Día más, una pregunta que se dibujaba debajo y era inalcanzable; ' +
'"esperando a" nombra a la persona y lo que se le pregunta, en vez de decir que a nadie; los ' +
'ajustes de la partida salen de la línea superior a una tarjeta Esta Partida, y en su lugar ' +
'aparecen los recuentos de colisiones; el control de mostrar/ocultar del Área de Oficina ofrece ' +
'los tres modos en vez de saltarse uno; el historial se lee de lo más reciente a lo más ' +
'antiguo; y una carta de Pendiente Fuerte muestra hacia dónde sube.',
de_DE:
'Enth\u00e4lt Station Master v0.7.8 \u2014 der Solo-Einrichtungsbildschirm funktioniert endlich f\u00fcr alle. ' +
'Er wurde \u00fcbersprungen, sobald der Browser ein gespeichertes Solospiel hielt, und jeder Browser, ' +
'der je gespielt hat, h\u00e4lt eines \u2014 die meisten Spieler sahen ihn also nie. Ein Klick auf Solo ' +
'spielen fragt jetzt immer, wie das Spiel eingerichtet werden soll. Dein laufendes Spiel ist ' +
'sicher: der Bildschirm bietet Gespeichertes Spiel fortsetzen und sagt deutlich, dass ein neues ' +
'Austeilen es ersetzt. Die Seite einfach erneut zu \u00f6ffnen setzt wie bisher dort fort, wo du ' +
'aufgeh\u00f6rt hast. Die Fu\u00dfzeile der Startseite nennt jetzt au\u00dferdem beide Spielarten. Keine ' +
'Regel\u00e4nderungen; laufende Spiele sind nicht betroffen.',
'Enthält Station Master v0.7.9. — ZUERST LESEN: LAUFENDE SOLOSPIELE BLEIBEN NICHT ERHALTEN. Die ' +
'beiden Kollisionsgrenzen des Solospiels (3 pro Tag, 5 pro Partie) wurden als Einstellungen ' +
'angeboten, sagten eine Niederlage an und wurden nie geprüft. Jetzt tun sie, was sie sagen — ' +
'ein gespeichertes Solospiel mit Kollisionen lässt sich also nicht mehr öffnen. Es scheitert ' +
'sicher: der Spielstand bleibt unangetastet und das Spiel verweigert schlicht, statt etwas zu ' +
'beschädigen. Beende vor dem Update, was dir wichtig ist. Mehrspielerpartien auf diesem Server ' +
'sind nicht betroffen. Außerdem: der Endbildschirm fragt jetzt, ob ein weiterer Tag gespielt ' +
'werden soll — diese Frage wurde bisher darunter gezeichnet und war unerreichbar; "wartet auf" ' +
'nennt die Person und ihre Frage, statt niemanden zu nennen; die Spieleinstellungen wandern aus ' +
'der Kopfzeile in eine Karte Dieses Spiel, an ihre Stelle treten die laufenden Kollisionszähler; ' +
'die Anzeigesteuerung des Amtsbereichs bietet alle drei Modi, statt an einem vorbeizuschalten; ' +
'der Verlauf liest sich neueste zuerst; und eine Steigungskarte zeigt jetzt ihre Richtung.',
pl_PL:
'Zawiera Station Master v0.7.8 \u2014 ekran ustawie\u0144 gry solo wreszcie dzia\u0142a dla wszystkich. By\u0142 ' +
'pomijany zawsze, gdy przegl\u0105darka przechowywa\u0142a zapisan\u0105 gr\u0119 solo, a ka\u017cda przegl\u0105darka, kt\u00f3ra ' +
'kiedykolwiek gra\u0142a, tak\u0105 przechowuje \u2014 wi\u0119c wi\u0119kszo\u015b\u0107 graczy nigdy go nie zobaczy\u0142a. ' +
'Klikni\u0119cie Zagraj solo zawsze pyta teraz, jak chcesz ustawi\u0107 gr\u0119. Twoja gra w toku jest ' +
'bezpieczna: ekran oferuje Kontynuuj zapisan\u0105 gr\u0119 i jasno m\u00f3wi, \u017ce rozdanie nowej j\u0105 zast\u0105pi. ' +
'Zwyk\u0142e ponowne otwarcie strony nadal wznawia gr\u0119 w miejscu, w kt\u00f3rym sko\u0144czy\u0142e\u015b. Stopka strony ' +
'g\u0142\u00f3wnej wymienia teraz r\u00f3wnie\u017c oba sposoby gry. Zasady si\u0119 nie zmieni\u0142y; gry w toku nie s\u0105 ' +
'dotkni\u0119te.',
'Zawiera Station Master v0.7.9. — PRZECZYTAJ NAJPIERW: TRWAJĄCE GRY SOLO NIE ZOSTANĄ ZACHOWANE. ' +
'Dwa limity kolizji w grze solo (3 na Dzień, 5 na partię) były oferowane jako ustawienia, ' +
'zapowiadały przegraną i nigdy nie były sprawdzane. Teraz robią to, co mówią — więc zapisana ' +
'gra solo, w której doszło do kolizji, odmówi otwarcia. Zawodzi bezpiecznie: zapis pozostaje ' +
'nietknięty, a gra po prostu odmawia, niczego nie uszkadzając. Dokończ to, na czym ci zależy, ' +
'przed aktualizacją. Gry wieloosobowe na tym serwerze nie są dotknięte. Ponadto: ekran końca ' +
'gry pyta teraz, czy zagrać jeszcze jeden Dzień — to pytanie było rysowane pod nim i ' +
'nieosiągalne; "czeka na" podaje osobę i pytanie, zamiast mówić, że nikogo; ustawienia gry ' +
'przeniosły się z górnego wiersza do karty Ta Gra, a ich miejsce zajęły bieżące liczniki ' +
'kolizji; przełącznik Biura oferuje wszystkie trzy tryby zamiast omijać jeden; historia czyta ' +
'się od najnowszych; a karta Stromego Podjazdu pokazuje, w którą stronę się wznosi.',
fr_FR:
"Inclut Station Master v0.7.8 \u2014 l'\u00e9cran de configuration du solo fonctionne enfin pour tout le " +
'monde. Il \u00e9tait ignor\u00e9 d\u00e8s que le navigateur d\u00e9tenait une partie solo sauvegard\u00e9e, et tout ' +
'navigateur ayant d\u00e9j\u00e0 jou\u00e9 en d\u00e9tient une : la plupart des joueurs ne l\u2019ont donc jamais vu. ' +
'Cliquer sur Jouer en solitaire demande d\u00e9sormais toujours comment configurer la partie. Votre ' +
'partie en cours est en s\u00e9curit\u00e9 : l\u2019\u00e9cran propose Continuer la partie sauvegard\u00e9e et indique ' +
'clairement qu\u2019en distribuer une nouvelle la remplace. Rouvrir simplement la page reprend ' +
'toujours o\u00f9 vous en \u00e9tiez. Le pied de page de l\u2019accueil nomme maintenant les deux fa\u00e7ons de ' +
"jouer. Aucune r\u00e8gle n'a chang\u00e9 ; les parties en cours ne sont pas affect\u00e9es.",
"Inclut Station Master v0.7.9. — À LIRE D'ABORD : LES PARTIES SOLO EN COURS NE SONT PAS " +
'CONSERVÉES. Les deux limites de collisions du solo (3 par Jour, 5 par partie) étaient proposées ' +
'comme réglages, annonçaient une défaite et n’étaient jamais vérifiées. Elles font désormais ce ' +
'qu’elles disent : une partie solo sauvegardée ayant connu des collisions refusera de ' +
's’ouvrir. L’échec est sûr — la sauvegarde reste intacte et la partie refuse simplement, sans ' +
'rien corrompre. Terminez ce qui compte avant de mettre à jour. Les parties multijoueurs de ce ' +
'serveur ne sont pas affectées. Par ailleurs : l’écran de fin demande maintenant s’il faut ' +
'jouer un Jour de plus, question qui était dessinée en dessous et restait inaccessible ; ' +
'« en attente de » nomme la personne et ce qu’on lui demande, au lieu de ne nommer personne ; ' +
'les réglages quittent la ligne du haut pour une carte Cette Partie, remplaçés là par les ' +
'compteurs de collisions ; le contrôle d’affichage du Bureau propose les trois modes au lieu ' +
'd’en sauter un ; l’historique se lit du plus récent au plus ancien ; et une carte de Forte ' +
'Rampe montre desormais dans quel sens elle monte.',
},
migrations: {
/**
* STILL NOTHING TO CARRY. v0.7.8 changes which SCREEN a solitaire visit lands on — the setup
* screen was skipped whenever the browser held a save, so a returning player never saw it — plus
* the splash footer's wording. Both are client-side; no rule the engine enforces and no
* save-format change.
* NOTHING TO CARRY, AND THIS TIME THAT IS NOT THE SAME AS "NOTHING BREAKS".
*
* A SOLITAIRE SAVE LIVES IN THE BROWSER, not on this server, so nothing here can touch it either
* way: `#ss-resume` is what keeps it reachable, and only the player's own Deal clears it. A
* multiplayer game in progress resumes exactly as it would have on v0.7.7.
* v0.7.9 changes a RULE. `advance.ts` gated §3.4's collision check on
* `mode === 'competitive' || mode === 'coop'`, so a solitaire game carried both limits
* (`SOLO_CONFIG`: 3 a Day, 5 total), offered them on the New Game screen as live settings, told
* the player the game would end in a loss — and never checked them. Jesse's ruling was that the
* settings should do what they say, so the gate is gone.
*
* A SOLITAIRE SAVE IS A SEED PLUS THE MOVES PLAYED, and it does NOT carry the collision caps —
* `Save` is `{ seed, history, rules? }`, where `rules` is the house rules only. The caps come
* from today's defaults on restore. So a save recorded under 0.7.8 replays under 0.7.9 with the
* caps now live, and a game that crossed one stops replaying at that point.
*
* MEASURED RATHER THAN ASSUMED, because the first two attempts at measuring it were wrong. With
* the caps disabled, 1200 of 1200 generated solitaire saves replay every intent — that is the
* control, and without it the experiment says nothing (an earlier run reported "no saves break"
* when in fact every replay was failing at intent 2 for an unrelated house-rules mismatch). Of
* those, 74 games crossed the 5-collision total, and 70 of the 74 truncate once the caps are
* enforced: one replays 141 of its 532 intents and stops. So this is "will break for anyone who
* crashed", not "may break".
*
* IT FAILS SAFE. The save file is left untouched and the game declines to open rather than
* loading a position the rules could not have produced, so a player who cares can put 0.7.8 back
* and finish. The release notes lead with it in all five locales.
*
* NOTHING HERE CAN ACT ON IT EITHER WAY: a solitaire save lives in the player's own browser, not
* on this server. A MULTIPLAYER game in progress is unaffected — competitive and coop have been
* inside that gate all along, so their rules did not move.
*/
up: async ({ effects }) => {},
down: IMPOSSIBLE,