In offline mode the lobby now shows only the device-local games and its
New-vs-AI entry creates one through the in-browser engine — the visible
payoff of the offline mode.
- LocalSource.list() reconstructs a lobby GameView per stored local game by
replay, exposed through the lazy gamesource proxy; unit-tested via an
in-memory store.
- Lobby.load() branches on offlineMode: lists local games and skips every
gateway call (no online games/invitations/incoming); the Stats tab is
disabled offline.
- NewGame offline: find() creates a device-local vs_ai game via
LocalSource.create using the profile's advertised dict version + a local
seed; the friends flow and the random-opponent option are hidden, and the
variant picker / Start are enabled offline (were gated on connection).
- id.ts: newLocalGameId + randomSeed (tested).
Docs: ARCHITECTURE + FUNCTIONAL(+ru) offline-mode section.
Deferred to fast-follow: the Settings Friends/Profile/Feedback affordance
gating, the flip-to-offline readiness wait, the offline mock e2e (needs
mock-dawg support), and the local-hint UI. The offline flow is verified on
the test contour — the mock e2e cannot enter offline mode (the toggle is
gated to an installed PWA).
The game screen now drives a local vs_ai game through the offline engine, dispatched by
game id — completing the playable local game (on top of the source, #193). Online play
is unchanged.
- gamesource.ts: gameSource(id) returns the local source for a `local:` id, else the
gateway (the same game-loop interface). The offline engine stays OUT of the app entry
bundle — it is dynamically imported on first use (a separate chunk), so online-only
users never pay for it (the app entry stays within its size budget).
- localgame/id.ts: the tiny id helper (no engine imports) the dispatcher branches on.
- Game.svelte: the game-loop calls (state/history/submit/pass/exchange/resign/hint/
evaluate/draft) go through gameSource(id) instead of the gateway directly; a local
game's robot-reply events route through the same app event hub the network stream
feeds, so the screen reacts to opponent_moved / game_over identically.
Behaviour-preserving for network games (gameSource returns the gateway for them). Local
verify green: check + test:unit + build + bundle-size gate + e2e (196 passed).