• v0.5.2 62b6ed7e1b

    v0.5.2 — the splash's multiplayer door opens, and knows whether it should

    Jesse.Markowitz released this 2026-08-21 15:00:06 +00:00 | 72 commits to main since this release

    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.

    Downloads