feat(offline): offline lobby — list + create + play local vs_ai games [C6] #198

Merged
developer merged 3 commits from feature/offline-lobby into development 2026-07-06 12:43:23 +00:00
Owner

Part of the PWA offline mode (Phase C, C6). The visible payoff: in offline mode the lobby lists, creates and plays device-local vs_ai games.

What

  • LocalSource.list() reconstructs a lobby GameView per stored local game (by replay), exposed through the lazy gamesource proxy — unit-tested with an in-memory store.
  • Lobby (load()) branches on offlineMode: it lists local games, skips every gateway call (no online games/invitations/incoming), and disables the Stats tab.
  • New Game offline: creates a device-local vs_ai game via LocalSource.create, using the profile's advertised dict version (dict_versions, from #196) + a local seed; the with friends flow and the random opponent option are hidden, and the variant picker / Start are enabled offline (they were gated on connection.online).
  • id.ts: newLocalGameId + randomSeed (tested).

Docs: ARCHITECTURE + FUNCTIONAL (+_ru) offline-mode section.

Tests

UI: check (0 errors), unit (476 — LocalSource.list ×3, id helpers ×3), online mock e2e (196 — no regression to online play), build + bundle gate (112.4 / 113).

⚠️ The offline flow itself is contour-verified, not e2e-tested: the mock e2e cannot enter offline mode (the toggle is gated to an installed PWA + confirmed email). Please try it on the contour — Settings → Play mode → Offline → New Game → play a local game.

Deferred to fast-follows

  • The Settings Friends/Profile/Feedback affordance gating (this PR gates the lobby Stats tab; the Settings-internal items come next — they aren't plain navigate calls, so I'll wire them separately).
  • The flip-to-offline readiness wait (grey / ≤5 s / revert when a variant's dictionary isn't cached yet).
  • The offline mock e2e (needs mock-dawg support — C8), which would then cover this whole flow automatically.
  • The local hint UI (the 30-minute gate already exists in the source — B4).
Part of the PWA **offline mode** (Phase C, C6). The **visible payoff**: in offline mode the lobby lists, creates and plays device-local `vs_ai` games. ## What - **`LocalSource.list()`** reconstructs a lobby `GameView` per stored local game (by replay), exposed through the lazy `gamesource` proxy — unit-tested with an in-memory store. - **Lobby** (`load()`) branches on `offlineMode`: it lists local games, skips every gateway call (no online games/invitations/incoming), and disables the Stats tab. - **New Game** offline: creates a device-local `vs_ai` game via `LocalSource.create`, using the profile's advertised dict version (`dict_versions`, from #196) + a local seed; the *with friends* flow and the *random opponent* option are hidden, and the variant picker / Start are enabled offline (they were gated on `connection.online`). - **`id.ts`**: `newLocalGameId` + `randomSeed` (tested). Docs: ARCHITECTURE + FUNCTIONAL (+`_ru`) offline-mode section. ## Tests UI: `check` (0 errors), unit (476 — `LocalSource.list` ×3, id helpers ×3), online mock e2e (196 — no regression to online play), `build` + bundle gate (112.4 / 113). ⚠️ **The offline flow itself is contour-verified, not e2e-tested**: the mock e2e cannot enter offline mode (the toggle is gated to an installed PWA + confirmed email). Please try it on the contour — Settings → Play mode → Offline → New Game → play a local game. ## Deferred to fast-follows - The Settings **Friends/Profile/Feedback** affordance gating (this PR gates the lobby Stats tab; the Settings-internal items come next — they aren't plain `navigate` calls, so I'll wire them separately). - The **flip-to-offline readiness wait** (grey / ≤5 s / revert when a variant's dictionary isn't cached yet). - The **offline mock e2e** (needs mock-dawg support — C8), which would then cover this whole flow automatically. - The local **hint UI** (the 30-minute gate already exists in the source — B4).
developer added 1 commit 2026-07-06 09:36:05 +00:00
feat(offline): offline lobby lists + creates local vs_ai games
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m10s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m39s
ef832b823d
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).
developer added 1 commit 2026-07-06 12:04:24 +00:00
fix(offline): route word-check through the game source; reload lobby on offline flip
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m11s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m40s
2f70ef1b85
Two offline bugs found on the contour:
- The word-check screen (CheckScreen) called gateway.gameState/checkWord
  directly, so in an offline (local) game it hit the network and errored
  ("something went wrong"). Route both through gameSource(id) — the local
  source answers from the device dawg. The complaint control (online-only,
  no offline backend) is hidden for a local game.
- The lobby did not react to the offline-mode toggle (which lives in Settings,
  so the lobby can stay mounted): an online game lingered until the next
  reload. Reload on an offlineMode flip so entering offline immediately shows
  only device-local games.

Cold offline launch hanging on the splash (boot still fetches the profile over
the network) is the separate C2 offline-boot follow-up (needs a persisted
profile + a boot short-circuit).
developer added 1 commit 2026-07-06 12:22:04 +00:00
fix(offline): AI comms hub opens straight to the Dictionary, not via Chat
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m10s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m41s
5643c8be10
For an honest-AI (vs_ai) game the comms hub relied on a post-mount $effect to
switch from the Chat tab to the Dictionary, so ChatScreen mounted for a beat
and fired its chat/state fetch over the network. Online that was a wasted
call; offline it threw and raised a 'something went wrong' toast on entering
the word-check form (the check itself already worked). Start the comms hub on
the Dictionary tab immediately for a vs_ai game, so ChatScreen never mounts.
owner approved these changes 2026-07-06 12:41:48 +00:00
developer merged commit ec0c13bebc into development 2026-07-06 12:43:23 +00:00
developer deleted branch feature/offline-lobby 2026-07-06 12:43:23 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#198