Land the offline-model redesign (ANDROID_PLAN.md O1-O7): replace the explicit offline toggle with a single detected net-state machine, unify the lobby, and add a two-tier client-version gate. Contour-safe: both version vars empty => dormant, and the wire change is additive, so web/pwa/vk/tg behaviour is unchanged unless the gate is deliberately configured.
O1 pure net-state reducer (test-first). O2 reactive store + event wiring (connection/offline become thin shims; +@capacitor/network). O3 remove the offline toggle + migrate the pref. O4 two-tier gate: hard update_required degrades to an offline Update/Play-offline notice (not terminal); soft GATEWAY_RECOMMENDED_CLIENT_VERSION -> X-Update-Recommended nudge. O5 unified lobby (device-local + greyed-from-cache server games; self-set identity; closes G-step-0). O6 create flows (with-friends online/offline segment + offline dict guard). O7 docs (ARCHITECTURE, FUNCTIONAL +_ru, TESTING, deploy/README).
Also disable the manual android-build CI workflow for now (rename to .disabled); the Android APK release comes later.
Tests: gateway go green, svelte-check 0/0, vitest 617, e2e 122/122 (chromium + webkit).
The native (Capacitor) sign-in surface is guest + email only: VK ID
web-login is a full-page redirect to id.vk.com that cannot return into the
WebView, and the Telegram Login Widget is unreliable there. Profile now
gates telegramLinkable/vkLinkable on !nativeShell (clientChannel android/
ios), hiding both LINK buttons on native; email and account management —
including an existing link's redirect-free UNLINK — stay. Native tg/vk
login (native SDKs / deep-link OAuth) is a separate later stage.
Covered by e2e/native.spec.ts (the reconcile test opens Profile and asserts
no Link Telegram / Link VK buttons, email present).
Native (Capacitor) cold boot with no cached session now enters as a
device-local guest in auto-offline mode and lands straight in the lobby
(never /login), so the app opens and plays local vs_ai / hotseat with the
APK's bundled dictionaries and zero network. When the gateway becomes
reachable, reconcileServerGuest silently mints + adopts a server guest and
clears the auto-offline, lighting up online features. Web / PWA / Telegram /
VK are byte-for-byte unchanged.
- transport: exec gains { silent, allowOffline } so background reconciliation
bypasses the offline kill switch (like the reachability probe) and never
raises the terminal update overlay (a too-old client stays a local guest);
new authGuestSilent on the client interface, the real transport and the mock.
- app: native no-session boot branch; reconcileServerGuest fired at boot, by
the recovery poll and the online event; the poll routes the session-less
guest through reconciliation, since checkReachable needs a token it lacks.
- native: initNativeShell tolerates a missing Capacitor bridge.
- e2e: new native.spec.ts (inject window.androidBridge; boot -> offline lobby,
local vs_ai move, reconcile -> online, hotseat start) + playwright.config
bundles the dawgs into dist-e2e/dict for the loader's bundled tier.