Commit Graph
18 Commits
Author SHA1 Message Date
JesseandClaude Opus 5 da0e5d49d6 0.8.0.11:0 — bundle Station Master v0.8.0.11
Sixteen fixes from the second multiplayer playtest. Making up a train now says
what the consist STILL needs rather than only what its card calls for, says that
a player adds one car before the round passes on, marks the train being loaded
on the Division map, and gives an addable car in the yard the same amber every
other button wears. A train's arrival names whose Office it reached instead of
telling every seat they can work it. While the board catches up a player can
pause the playback, look at another player's Office Area, and sees one
consistent Day/Stage/phase rather than a turn chart running ahead of the board.
Saves download named after the game, with the join code, Day and Stage.

GAMES IN PROGRESS RESUME NORMALLY, and that was measured rather than assumed:
`git diff v0.8.0.10..v0.8.0.11 -- src/engine/` is three files and nineteen
insertions — an `owner` field on the `trainArrived` event, the one line that
fills it, and a reworded card description. `check()` and `legal.ts` are
untouched and no predicate changed its answer, so nothing once legal became
illegal, and events are derived rather than persisted. That is the opposite of
0.8.0.10, which deliberately stranded games holding a ruling the rules no longer
ask for — README, instructions.md and the release notes in all five locales say
which of the two this is.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnuCv8UodHucFfx3LWEoX
2026-09-16 16:29:07 -04:00
JesseandClaude Opus 5 c6e17fc473 0.8.0.10:0 — bundle Station Master v0.8.0.10
Playtest fixes. The Superintendent is no longer asked to rule on a train
BEHIND the one departing — which cost a real game a collision, since holding
the departing train kept the only A/D track full and the train behind it
arrived into that. The screen names the player whose move it is showing while
the board catches up, the history no longer runs ahead of it, a Realignment
says which card it converted and flashes it on the map, a ruling made by
holding the office says so, and a seated player can download their own game
as a save file.

GAMES IN PROGRESS OFTEN WILL NOT RESUME, deliberately: a save replays through
the current rules, so a game holding a ruling the rules no longer ask for is
refused at that move. The server logs which move and leaves the file alone;
re-installing 0.8.0.9 finishes such a game. Measured at 28 of 40 recorded
four-seat games. Jesse's call: ship it. The release notes say so in all five
locales, and README and instructions.md carry the warning.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnuCv8UodHucFfx3LWEoX
2026-09-16 05:35:46 -04:00
JesseandClaude Opus 5 3e6e4690e2 0.8.0.9:0 — bundle Station Master v0.8.0.9
The bots that fill empty seats play far better: they plan each switching turn,
stop taking cards they cannot play, no longer run Second Sections by accident,
and lay track where it opens something up. The engine checks moves about three
times faster, with play proven identical. No rule changed, so games in progress
resume; the release notes say so in all five locales.

README's bundled-version line had stayed at 0.7.9.8 through the 0.8.0 series;
it now names 0.8.0.9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnuCv8UodHucFfx3LWEoX
2026-09-15 15:34:35 -04:00
JesseandClaude Opus 5 8f2f733a66 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
2026-09-08 03:56:40 -04:00
JesseandClaude Opus 5 bd802cb512 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
2026-08-30 20:41:27 -04:00
JesseandClaude Sonnet 5 3b7b334968 0.7.8:0 — bundle Station Master v0.7.8
Submodule pinned to v0.7.8 (193800a). current.ts bumped in place at
0.7.8:0 — no new version file, no migration: the change is which screen
a solitaire visit lands on, plus the splash footer's wording. Both are
client-side, and a solitaire save lives in the browser rather than on
this server, so nothing here is involved either way.

0.7.5 skipped the setup screen whenever the browser held a save, and any
browser that has ever played solitaire holds one — so the door could
never reach the screen again. The door outranks a save now; a bare
reload still resumes; #ss-resume keeps the game in progress reachable
since Deal clears it.

Verified on phoenix.local against what the server returns: the door
carries ?solitaire, play.html carries #ss-resume and #ss-saved-note, the
footer names both ways to play, and the build tag is 0.7.8-mtfaojtv.
Migration 0.7.7:0 -> 0.7.8:0 ran empty and both multiplayer games in
progress (WHISTLE-4086, COAL-7370) resumed with their same intent counts.

The behaviour itself is covered by four new tests upstream that
reproduce the reported state (door + existing save) rather than by
reading served output — which is what the two previous attempts did, and
why they were reported as verified while still being wrong.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
2026-08-30 00:16:07 -04:00
JesseandClaude Sonnet 5 921db34b55 0.7.7:0 — bundle Station Master v0.7.7
Submodule pinned to v0.7.7 (af68aac). current.ts bumped in place at
0.7.7:0 — no new version file, no migration: the change is to how the
built client is cached, not to what it does.

Every packaged build until now published ?v=nogit as its cache key (the
.s9pk Dockerfile copies the tree in without .git, so git rev-parse
fails), and serveStatic sent no Cache-Control at all — so 0.7.5's
solitaire setup screen and 0.7.6's fix to it were both installed here
correctly and neither ever reached a browser.

Verified on phoenix.local against what the server actually returns, not
just what was packed: build tag is 0.7.7-mtf7hyxc (not nogit) and the
module graph's inner imports carry the same tag; play.html is no-cache;
a ?v=-tagged module is immutable for a year; an untagged one is
no-cache. Migration 0.7.6:0 -> 0.7.7:0 ran empty and both games in
progress (WHISTLE-4086, COAL-7370) resumed with their same intent counts.

README.md records that a hard reload is NOT a sufficient check for this
class of bug — confirmed in the field on 0.7.6, where only a fresh
private window showed the new build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
2026-08-29 22:46:25 -04:00
JesseandClaude Sonnet 5 590ff5fa0b 0.7.6:0 — bundle Station Master v0.7.6
Submodule pinned to v0.7.6 (b4f09f0). current.ts bumped in place at
0.7.6:0 — no new version file, no migration: fixes a client-side
routing bug in the solitaire door that v0.7.5 introduced (a browser
that had ever held a multiplayer seat could not reach the new setup
screen at all), so every game in progress carries over without
exception.

Verified: npm run check clean, prettier clean, make x86 packs as
v0.7.6:0, installed on phoenix.local — logs show the empty migration
running and both games in progress (WHISTLE-4086, COAL-7370) resuming
with their same intent counts, and the served index.html confirmed to
link the solitaire door to ./play.html?solitaire.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
2026-08-29 21:52:56 -04:00
JesseandClaude Sonnet 5 3fc56de203 0.7.5:0 — bundle Station Master v0.7.5
Submodule pinned to v0.7.5 (3e96149). current.ts bumped in place at
0.7.5:0 — no new version file, no migration: the change is a client-side
flow change (solitaire asks for its options before dealing, the same
question the multiplayer lobby already asks) that touches no rule the
server enforces and no save format, so every game in progress carries
over without exception.

Verified: npm run check clean, prettier clean, make x86 packs as
v0.7.5:0, installed on phoenix.local — logs show the empty migration
running and both games in progress (WHISTLE-4086, COAL-7370) resuming
with their same intent counts, and the served play.html confirmed to
contain the new #solitairesetup screen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
2026-08-29 19:27:35 -04:00
JesseandClaude Opus 5 085b88bb38 0.7.4:0 — bundle Station Master v0.7.4
Submodule pinned to v0.7.4 (19a6a47), `current.ts` at `0.7.4:0`, release notes
rewritten in all five locales, README.md and instructions.md updated. No new version
file and no migration: the outgoing 0.7.3:0's `up` is empty, `versions.md`'s common
case, so `current.ts` bumps in place.

Three rules corrections, all places where the code and the cards disagreed. The Yard
Office is offered rather than imposed, must be reachable in one move, and cars on the
lead collide — none of which it checked. Circus, Campaign and Military trains run
loaded where the yard can supply it, and the per-stop point is earned once per Office
Area by a fully loaded train. Red Flags becomes a directional flag on your own Limits,
spent on the train it stops, playable at the moment the engine sees a certain
collision.

GAMES IN PROGRESS MAY NOT SURVIVE THIS ONE, and the notes lead with it in every locale
— the opposite of 0.7.3 and for a different reason from 0.7.2. Nothing about the save
format changed; what changed is what the rules accept. The Red Flags intent changed
shape, a make-up that was legal may now be refused, and a Yard Office arrival asks a
question no older history has an answer for. It fails safe: the server declines a save
the rules reject, names the move, and leaves the file untouched. A game that never
meets one of the three carries on, which is why this is "may not" rather than 0.7.2's
"will not".

README.md's diagnosing note is extended: the Mainline Phase now stops to ask three
different questions of three different players, and a game sitting on one is waiting
on a person rather than stuck — it shows as active with nobody to wait for, because an
interruption is not a turn.

Verified: `npm run check` clean, prettier clean, `make x86` packs as v0.7.4:0.
NOT verified: not yet installed on a box, and none of the three rules has been played
by a human — upstream TODO.md #35 still stands for extended play too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAgJSmeV8zrMh55Mj85ESb
2026-08-29 08:20:30 -04:00
JesseandClaude Opus 5 74aea24d74 0.7.3:0 — bundle Station Master v0.7.3
Submodule pinned to v0.7.3 (45580d8), `current.ts` at `0.7.3:0`, release notes
rewritten in all five locales, README.md and instructions.md updated. No new
version file and no migration: the outgoing 0.7.2:0's `up` is empty, which is
`versions.md`'s common case, so `current.ts` bumps in place and `index.ts` is
untouched.

Two features, both about the end of a game. A game no longer stops dead when the
timetable runs out — it enters a fourth state, `awaitingExtension`, and asks the
table whether to play one more Day, unanimously in multiplayer with one refusal
decisive. The official result is frozen at the original `config.days` and never
rewritten, so playing on is explicitly an exhibition, and a §3.4 collision breach
is neither extendable nor able to overwrite a recorded result. And the end of a
game renders a full results screen in place of the raw `outcome.reason` enum the
page used to print.

GAMES IN PROGRESS SURVIVE THIS ONE, which is the opposite of the last release and
is why the notes lead with it in every locale. No card data changed and the engine
changes are additive, so every intent in a 0.7.2 save is still legal: the save
replays intact and the game simply pauses on the new question at the end. Upstream
proves it rather than asserting it — the suite replays the three recorded games in
`public/replays`, all made under an older ruleset, and asserts every intent still
applies. Anyone updating from 0.7.1 or earlier is still in the old boat, and both
docs say so.

README.md gains a short diagnosing note, since `awaitingExtension` is a state an
administrator can meet and misread: such a game is persisted and listed as
`active`, resumes on restart like any live game, and shows nobody to wait for —
because a vote is not a turn.

Verified: `npm run check` clean, prettier clean, `make x86` packs as v0.7.3:0.
NOT verified: not installed on a box and not played. Extended play has never been
exercised against a running service — upstream `TODO.md` #35.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAgJSmeV8zrMh55Mj85ESb
2026-08-29 05:07:03 -04:00
Jesse 1bfea8d49f 0.7.2:0 — bundle Station Master v0.7.2
Two engine bugs and two rules corrections, plus the Division map redrawn. The submodule pin moves to
v0.7.2 and the version follows it; the downstream digit resets to :0.

- Backing into a cut through a curve's 45° leg no longer couples it back to front, and a crew pulling
  out through one takes its own cut with it instead of leaving it standing.
- The card deck is the published counts exactly, which halves the track and drops two long-standing
  density multipliers — 206 cards to 121.
- Crossing a Mainline card counts the regions printed on it rather than the printed speed, which was
  only ever scenery. Most trains cross faster, slow trains much faster, and Fast/Slow now matters on
  the Hilly card alone.
- The Division map is one row read left to right, so east is always to the right.

GAMES IN PROGRESS DO NOT SURVIVE THIS UPDATE, and this is the first release of which that is true. A
save is a seed plus the moves played, and the deck changing size means a card id recorded under 0.7.1
refers to a different card or to none — so a save stops replaying at its first card.play. There is no
migration because there is no data to move: those moves were made against a deck that no longer
exists, and re-dealing would invent a game nobody played.

It fails safe. The server refuses to resume a save the rules reject, logs which move it stopped at,
and leaves the file untouched, so an operator can put 0.7.1 back on to finish a game that matters.
The release notes lead with this, in all five locales.

Packed and verified as v0.7.2:0 on x86_64.
2026-08-26 15:32:26 -04:00
JesseandClaude Opus 5 ea8e9dbcb8 0.7.1:0 — bundle Station Master v0.7.1
Four playtest fixes off the Gitea tracker. The submodule pin moves to v0.7.1 and the version follows
it; the downstream digit resets to :0, since v0.7.0 only ended on :3 because three test packs were
played before it was released.

- An empties-only train may couple a caboose again — a caboose carries the crew, not freight.
- The end of a Day is a modal carrying the standings, the Days left and the combined target, instead
  of passing between one click and the next inside the automatic phases.
- A Timetabled train may be discarded to a Department pile for a rival to pick up, governed by a new
  discardTimetabled setting that appears in both the New Game dialog and the lobby, on by default. An
  Extra never may.
- A blocked passenger platform now gives its reason, including the coach shortage and what ends it.

No new version file and no migration: current.ts's migrations.up is empty and nothing is carried from
0.7.0. GAMES IN PROGRESS SURVIVE THIS UPDATE — all three engine-visible changes only widen what is
legal, so every intent a 0.7.0 game recorded still replays, and the server resumes a save by replaying
it rather than by comparing version strings (src/server/index.ts in the game repo).

README.md and instructions.md both named 0.7.0 and carry the three user-visible changes now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLnYR4XtXQNamYJXGYT8oC
2026-08-25 10:58:14 -04:00
JesseandClaude Opus 5 d26d44d9e2 0.7.0:3 — bundle Station Master v0.7.0
The submodule pin is the version; nothing else about the package changed. Four game types in the
lobby, the whole rule set readable before taking a seat, leaving and rejoining a game, and sound in
a multiplayer game for the first time — all upstream, all through the same server this package has
always run.

- startos/versions/current.ts — 0.7.0:3, with release notes in all five languages.
- instructions.md — how a game is set up now, and what Leave / Forget mean for a seat.
- README.md — the bundled version, and a limitation spelled out: a player's identity lives in their
  browser, so a lost token cannot be recovered from this package.
- UPDATING.md — how to pack a test build from work that is not pushed yet, which is how v0.7.0 was
  played before release, and why the downstream digit moves for each one.

The downstream digit is :3 rather than :0 because three test packs were installed on the box while
v0.7.0 was being played; publishing :0 now would be a downgrade it would refuse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JczK5i33ZNSf2PtzZqdhS
2026-08-23 05:50:38 -04:00
Jesse e84c640067 Bundle Station Master v0.6.0: updates stop destroying games in progress
Pin moves to v0.6.0, package version to 0.6.0:0.

README and instructions.md both promised the opposite of what now happens
and had to be rewritten: an update keeps games in progress unless the rules
actually changed, and a game that genuinely cannot replay is named in the
log rather than described as a version mismatch.

Verified on phoenix.local by doing the thing the release is about. A game
(MAIL-4571) was created on the installed 0.5.6:0, then this build was
installed over it. All four saved games on the volume came back:

  Resuming 4 saved game(s)…
  Resumed HOPPER-4607  — 37 intents replayed.   (written under 0.5.2)
  Resumed TRESTLE-5109 —  5 intents replayed.   (written under 0.5.3)
  Resumed TENDER-8092  — 38 intents replayed.   (written under 0.5.5)
  Resumed MAIL-4571    —  0 intents replayed.   (written under 0.5.6)

The first three had been refused on every boot since the release that
stranded them. They were never damaged, only unreachable, and replaying
them is all it took to get them back — which is the clearest evidence that
the version comparison was answering the wrong question. All four now show
in Games in Progress with the correct Day, Stage and waiting-on player.
2026-08-21 21:56:58 -04:00
Jesse c95620d566 Bundle Station Master v0.5.3: games in progress, and a way to end one
Pin moves to v0.5.3, package version to 0.5.3:0.

The health check no longer just probes a port. It 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. A server that doesn't
answer is reported as STARTING, never failed: the server replays its saved
games before binding its port, so a boot legitimately looks like nothing is
listening, and calling that a failure makes an ordinary restart look like a
crash.

Two new actions, both only-running. Games in Progress is read-only and
lists every game and lobby with players, Day/Stage/phase, who it waits on,
when it started and when it last moved. Manage Game picks one from a
dropdown built live from the server and either exports it or ends it —
ending being the only way a game finishes other than being played out,
since an abandoned game otherwise stays active and is resumed on every
restart forever. Ending always returns the deleted game's save, so nothing
is destroyed without being handed back first.

They are only-running because none of it is readable from disk: a save is a
seed plus a list of moves, so whose-turn-it-is exists only after a replay
through the engine, which lives in the game repo rather than here. The
running server has already done that work and is asked for the answer.
startos/serverApi.ts is the single place that asks.

store.json gained adminSecret (32 chars) beside joinSecret, seeded on
install and backfilled on update for a volume written before the field
existed. It is deliberately NOT the join secret: every player holds that
one, so gating a delete with it would let anyone at the table destroy
anyone else's game. init/generateJoinSecret.ts is renamed generateSecrets.ts
now that it mints both.

Also brought getJoinSecret's result strings under i18n(). They shipped as
plain strings two commits ago, which actions.md is explicit about — every
user-facing string including result titles, messages and thrown errors.
The new actions follow it, so the old one shouldn't be the odd one out.

Verified on phoenix.local, installed as an UPDATE from 0.5.2:0 rather than
a fresh install, which exercised three things at once: the boot log line
("Resuming 1 saved game(s)…"), the engine-version refusal firing for real
on a game recorded under 0.5.2, and the adminSecret backfill (store.json
came out with both secrets, 24 and 32 chars). Then, from inside the
container: the package-generated admin secret authenticating against
/api/games (200) while a wrong one is refused (403), health counts tracking
0 -> lobby 1 -> active 1 through a create/bot/start, and every field the
actions render present and correct on the listing.

NOT verified: the actions' own forms and result rendering. `start-cli
package action run` fails with a client-side deserialization error on every
action on this box — including the already-shipped get-join-secret and
actual-budget's equivalent — so it is a start-cli problem, not this
package's. The data path underneath them is verified above; the SDK
form/result rendering needs the web UI.

A test game (TRESTLE-3221, Alice + a bot) is left running on the box so
there is something for Games in Progress to show.
2026-08-21 16:00:05 -04:00
Jesse ea012f1329 Bundle Station Master v0.5.2, and fix the package version scheme
Submodule pin moves to v0.5.2, which carries the working splash-page
multiplayer door and the GET /api/health probe behind it.

The interface goes back to serving `/` — the splash, which is the front
door to all three ways to play. It pointed at /play.html only because the
splash's multiplayer door was hardcoded to "Coming soon", making the front
page a dead end on a real server; v0.5.2 removes the reason for the
workaround. The splash now probes /api/health on load, so served from here
it opens the lobby and served as a plain static site it says plainly that
it needs a server.

The package version was wrong and is corrected: 1.0.0:0 -> 0.5.2:0. That
1.0.0 was the scaffold's placeholder, left in by mistake — versions.md's
consistency checklist requires the upstream half to match the bundled tag,
which is what makes "bump the pin, bump the version" one mechanical action
rather than a judgement call. No historical version file is needed: the
placeholder carried no migration and was never published anywhere.

The correction is a downgrade in ExVer terms, so StartOS refused to install
over the existing copy ("uninit target range `!` is unsatisfiable"). The
installed package was therefore removed and reinstalled — checked first
that the volume held only an auto-generated join secret and no games. Two
consequences, both one-time and both recorded in UPDATING.md: the join
secret is regenerated, and the host's public domain binding was dropped
with the uninstall and has to be re-added.

Verified on phoenix.local: builds as v0.5.2:0, installs, starts, and serves
/api/health 200 with the right body; the splash carries all three doors
including a live ./play.html?lobby, no "Coming soon" anywhere, all three
ids the probe addresses present, and #lobby rendering on play.html?lobby.
2026-08-21 11:13:40 -04:00
Jesse de28b30eea Initial StartOS package for Station Master (v0.5.1)
Built from source via a git submodule pinned to a tag, not a published image
— the Dockerfile, main.ts, and manifest should never need to change for an
ordinary version bump, only the submodule pin (see UPDATING.md). One volume,
one interface serving the browser client + lobby/intent API + SSE stream
from a single origin, no dependencies. The server-wide join secret (D14) is
seeded on install, exposed via the Get Join Secret action, and blocks start
behind a critical task until retrieved — the same first-set/rotation pattern
as actual-budget-startos's admin password.

Verified on phoenix.local: installs, the critical task correctly blocks an
ordinary start, force-starting confirms the daemon binds its port and serves
the client, and store.json correctly holds the install-seeded join secret.
Not verified: the Get Join Secret action's execution end-to-end — start-cli's
`package action run` fails with a client-side deserialization error that
reproduces identically against actual-budget's already-shipped equivalent
action, so this looks like a start-cli issue rather than a defect here.

icon.svg is still the scaffold's hello-world placeholder — no real Station
Master icon exists yet to ship in its place.
2026-08-21 08:44:07 -04:00