644b24051a6ff3472b78094d5e001aff67d2171d
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d905c86e69 |
0.8.1.0:0 — bundle Station Master v0.8.1.0, and date the games in Manage Game
A table pass over 0.8.0.17. The second-digit bump is deliberate: 0.8.1 had been reserved for the seatless display table, which is getting more thought, and this batch earned the number on its own. GAMES IN PROGRESS RESUME, AND IT WAS MEASURED BEFORE RELEASE rather than argued from the diff. The bundled release changes what sits in the yards, so the risk was real. All twelve saves on the test box were pulled and replayed through `tryResumeSession` — the server's own boot check — against the new build: six resume, six refuse, and the six refusals are the SAME six, at the same moves, with the same codes, that 0.8.0.17 already logged. Nothing new was stranded. That replay is the check worth repeating on any release that touches state, because it answers before the install rather than after. THE GAME'S OWN FIX, for the README's benefit: the Freight Agent's "clear the red Inbound box" returned the car to the Classification Yard still marked loaded, carrying a load already delivered and already paid for. `pooled()` strips a load's `origin` stamp and keeps `loaded` on purpose — a train can retire at a Division Point with freight aboard — so the call site's comment, "a car back in a yard is back in the common supply, carrying nothing", described something it never did. Coaches suffered worst: detraining takes `coach && !loaded` out of the Division Yard, so a cleared coach came back as stock that could never unload a passenger. 18 loaded coaches against 6 empty over five measured games. THIS PACKAGE'S OWN CHANGE IS THE MANAGE GAME DROPDOWN. It listed each game's code, seat count and position and nothing about when the game was last touched, so four games on a server looked alike — reported 2026-09-22: "I've got four games out there, but I have no idea which one's which or how old they are." `lastMoveAt` was already on the wire from the server's `summary()` and simply unused. Each option now carries both an age and a timestamp, because they answer different questions: "5h ago" answers the one that was asked, and the date beside it is what you quote when deciding to end a game. A lobby has had no move, so it reports when it was created and says so. `when()` moved out of `gamesInProgress.ts` into `utils.ts` alongside a new `ago()`, shared by both actions so an administrator sees one date format wherever a game is named — the second copy would have been the one that drifted. No route, file model or interface changed. README and instructions.md carry the release, and the notes in all five locales say games in progress are unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUizFYCMHRWhbWwXhp7WPR |
||
|
|
81f9d06705 |
0.8.0.13:0 — bundle Station Master v0.8.0.13
Nine fixes from the Day 1-2 playtest of 0.8.0.12, almost all of them about what the table can see. The one that mattered moved a car: the Division Yard chips stayed clickable while a player's board was catching up on other people's turns, so a click submitted a real intent against a position several moves stale. They obey the catch-up queue now, and the yard counts beside them are read from the board on screen rather than the live game. The district picker gained a button for your own seat and is ordered west to east as the map draws it; the Fedora passing is announced and logged; a collision names whose district it was and who loses the 5 Revenue; and a Depot that cannot stock another passenger says which car it is short of instead of the action silently vanishing. Packaging is the submodule pin, the version and the words. No action, route, file model or interface changed — the whole release is inside the bundled game. GAMES IN PROGRESS RESUME NORMALLY, measured rather than assumed: `git diff v0.8.0.12..v0.8.0.13 -- src/engine/` is two ADDED lines — a superintendentChanged variant on the GameEvent union, and the events.push that emits it beside the actorChanged already there. Nothing was removed or edited: check(), legal.ts and every predicate are untouched, so no once-legal move became illegal, and events are derived by replaying a save rather than stored in one, so widening the union cannot invalidate anything on disk. README, instructions.md and the release notes in all five locales say so. Two files come along that this release did not otherwise touch: `prettier --write startos` reflowed a call in restoreSeat.ts and a return type in serverApi.ts, formatting drift left by the 0.8.0.12 commit. The 0.8.0.12 release it follows was deployed and verified at a table: a seat was recovered end to end from a one-time claim code minted by the StartOS action, which is what the previous commit said had not yet been exercised. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DmdqqCNoiqE7GBo6wthBnR |
||
|
|
a70337cf8b |
0.8.0.12:0 — bundle Station Master v0.8.0.12, and a Restore a Seat action
A player who has lost their browser storage can be put back in their seat (Gitea#33 in the game repo). The session token is the only identity the game has and it lives in one browser's localStorage, scoped to the origin joined at, so a cleared profile, a private window or a different browser locks a player out of a game that is still running with their session still on disk. Seen at a real table: of two humans in one game, the host reloaded straight back in and the joiner met an empty lobby. New action, restore-seat: pick a seat from a dropdown of the players actually holding a session — bots never appear, since seatedPlayers is read from the server's session map rather than guessed from display names — and get back a link built from this interface's own address. serverApi gained mintClaim; the dictionary gained 57-64 in all five locales. THE LINK CARRIES A CODE, NOT THE TOKEN. lobby-and-sessions.md §1 says to keep the token out of URLs so it is not shoulder-surfed or pasted into a chat, and a recovery link is exactly what gets pasted into a chat. The code is single-use, expires in 30 minutes, and the page trades it for the real token over a POST. Minting is admin-gated because deciding that somebody has lost a seat is a judgement no route can make safely; spending needs no secret, because the player following the link holds none. GAMES IN PROGRESS RESUME NORMALLY, measured rather than assumed: `git diff v0.8.0.11..v0.8.0.12 -- src/engine/` is EMPTY. The release is the server's HTTP surface, the client and the docs. The codes live in memory and are deliberately not persisted, so nothing new reaches the volume and there is nothing to migrate. README, instructions.md and the release notes in all five locales say so. NOT YET EXERCISED END TO END: the two routes and the action are typechecked and the claim store is unit-tested, but nothing has run them against a live server. This build is what makes that possible. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017nnuCv8UodHucFfx3LWEoX |
||
|
|
5bd06af932 |
Bundle Station Master v0.5.6, and count seats from 1 in Games in Progress
Pin moves to v0.5.6, package version to 0.5.6:0. One packaging change of its own: Games in Progress reported "seat 0" while the game's own screens now say "Seat 1", so an administrator and a player would have been describing different chairs. Same +1, same reason. Verified on phoenix.local as an update from 0.5.5:0. The served client carries all three of the release's fixes: the lobby's seat numbers go through seatLabel, .bs-name.bs-turn has lost the font-weight that made the current player's name unreadable at 11px, and the west-to-east seating line is gated to Day 1 Stage 1. |
||
|
|
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.
|
||
|
|
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. |