Commit Graph
4 Commits
Author SHA1 Message Date
Jesse 62b6ed7e1b v0.5.2 — the splash's multiplayer door opens, and knows whether it should
The "Play multiplayer" door on index.html had sat disabled, labelled
"Coming soon", since before the server existed — Phases 2 through 4 built
a working lobby and nothing ever linked to it. Loading the site landed on
the same solitaire splash whether a real multiplayer server was behind it
or not, with no visible way in. Found packaging Phase 6 for StartOS.

The door is now a live link to ./play.html?lobby, and main.ts's start()
routes ?lobby straight to the lobby screen — the same showScreen('lobby');
runLobby(beginRemote) the in-game Multiplayer button already used —
instead of dealing a solitaire game first.

GET /api/health is new, and exists to be failed. The same dist/ ships both
served by src/server/ and uploaded as flat files by deploy-web.ts, and the
bundle is identical either way (D4), so the page cannot know from its own
build which it is; every other route 404s an unknown path exactly as a
static host does, so nothing distinguished them. The splash probes it on
load and closes the door when nothing names itself in reply.

The door starts open and only ever closes, deliberately: a wrong "no
server" is the bug above again — invisible, and it strands a player who
does have one — while a wrong "there is one" costs a click and a lobby
that says it cannot connect. The reply must name itself rather than merely
return 200, or a host answering every path with its index page would pass.

Verified: tsc clean; 659 tests pass (656 + 3); /api/health exercised live
against a running server — 200 with the right body, unauthenticated, while
an unknown path and a wrong method both still 404, which is what makes the
probe discriminate at all.

The probe's own test was vacuous on the first attempt — both its "closes"
cases reached close() through the .catch arm, so deleting the body-naming
check outright still passed. Caught by mutating splash.ts and re-running;
the test now covers all three closing routes and fails without the check.
2026-08-21 11:00:06 -04:00
Jesse e76bd77099 v0.5.1 — multiplayer Phase 4: lobby, sessions, reconnection
A real server existed since v0.5.0 but nobody could reach it without a hand-built ?seat=&secret=
URL. This is what makes it a game you can actually create or join.

The server now hosts more than one game: src/server/lobby.ts (new) is pure logic — creating,
joining, bot seats, host transfer, starting — same split session.ts already draws for a running
game. persistence.ts gained one directory per gameId plus a top-level index so index.ts resumes
every saved game on boot. /api/stream and /api/intent now authenticate by session token instead of
?seat=&secret= — the token alone proves identity (lobby-and-sessions.md §1), so the join secret's
job ends at the lobby door.

Bots fill empty seats at Lobby.Start only, never take over a disconnected human (D8): session.ts
gained driveBots(), playing developerBot forward through consecutive bot seats after every accepted
intent. Disconnect keeps the seat and says so — Push gained an optional presence field, built
entirely by http.ts and never routed through the engine, since a disconnect is transport news, not
a GameEvent. Host rights pass to the earliest-joined remaining player if the host drops before
start.

Client: src/web/lobby.ts adds create/join forms and a live seating screen; localStorage replaces
?seat= for reconnecting straight back into a game already joined. A Multiplayer button sits beside
New game; the New Game dialog itself is untouched.

Found only by the live smoke test, not by typechecking: /api/intent read its token from the JSON
body while the client sends it in the query string (matching /api/stream) — every intent failed
"no such game" until caught by curl-level verification.

Doc fix: multiplayer.md's D18 said the player cap was 6; lobby-and-sessions.md §2 says 2-4 with the
reasoning and the test coverage to back it. The two had drifted apart. D18 now reads 2-4.

Not verified: an actual browser walking through the lobby screens — none available in this
environment, same limitation Phase 2's RemoteSession shipped under. 656 tests, 0 failures.

tools/jitsi-harness/ deliberately left untracked — unrelated side-project work, not part of this
release.
2026-08-21 05:25:47 -04:00
Jesse a7221dcf20 v0.4.1 - bug fixes. initial d12 rolls determine what player in which seat. 2026-08-13 15:28:53 -04:00
Jesse 49f8504b05 v0.4.0 — multiplayer Phases 0 and 1: seat and player split apart, turn state per player, the page behind a Session, and eight seat/player mix-ups fixed with tests that fail without them 2026-08-13 14:06:02 -04:00