docs(android): record D on-device smoke + edge-to-edge fix as-built

Reconcile the Progress/§D status after this session: D is code-complete,
e2e-verified AND on-device-smoke-verified (Pixel_10 / API 37, airplane mode);
the smoke surfaced + fixed the edge-to-edge safe-area bug (top + bottom).
Mark D.5 done (verified by the e2e + the on-device vs_ai turn). Remaining for
D: the reconcile-online leg on-device (hits prod) + the deferred local-game-
visibility decision.
This commit is contained in:
Ilia Denisov
2026-07-12 19:31:22 +02:00
parent 49c53794f4
commit e7cb60c996
+19 -6
View File
@@ -91,10 +91,12 @@ Kept current as parts land so a fresh session resumes without re-deriving. Verif
`clientver`/config/`connectsrv` tests green, `svelte-check` 0, `vitest` 591, e2e 232 (incl.
`update.spec.ts`), client build clean. Silent reconciliation seam deferred to D (owner); in-app
store-update SDK noted Out of scope.
- **D. Offline-first — ✅ CODE-COMPLETE & e2e-verified (D.1D.6 done, 2026-07-12).** Remaining: the on-device
emulator **airplane-mode smoke** (owner / stage G) and the **deferred local-game-visibility decision** (below).
D.5 (both offline modes render + play for the local guest) is verified by `e2e/native.spec.ts` (vs_ai move +
hotseat start).
- **D. Offline-first — ✅ CODE-COMPLETE, e2e-verified & on-device-smoke-verified (D.1D.6 done, 2026-07-12).**
The offline path is proven on-device (Pixel_10 / API 37, airplane mode): cold-boot → offline guest lobby, a
full local vs_ai turn (bundled dawg — Hint placed "FEZ", the robot replied "NEEDFIRE"), New Game offering
both modes; the smoke also surfaced + fixed a native-chrome edge-to-edge safe-area bug (below). Remaining for
D: the **reconcile-online leg on-device** (deferred — it hits prod, minting a guest) and the **deferred
local-game-visibility decision** (below). D.5 is also covered by `e2e/native.spec.ts` (vs_ai move + hotseat).
- **D.1 + D.2 (foundations) — ✅ DONE & committed `bcd5a1d` (2026-07-12).** `ui/scripts/bundle-dicts.mjs`
(release DAWGs → `dist/dict/<variant>@<version>.dawg`, keyed on `VITE_DICT_VERSION`, `OUT_DIR` override
for the e2e); the `dict/loader.ts` **bundled tier** (between IndexedDB and network, **native-gated**
@@ -118,6 +120,15 @@ Kept current as parts land so a fresh session resumes without re-deriving. Verif
LINK buttons are hidden on the native build; email + account management (incl. any existing link's UNLINK,
a redirect-free gateway call) stay. Covered by the `e2e/native.spec.ts` reconcile test (Profile → no Link
Telegram / Link VK buttons, email present).
- **Native chrome: Android 15+ edge-to-edge safe-area — ✅ FIXED & on-device-verified (2026-07-12, owner-confirmed).**
targetSdk 36 forces edge-to-edge, so the WebView draws behind the system bars; the app chrome overlapped the
status bar (top nav, untappable) and the gesture-nav home indicator (the game's centre Hint button — side
buttons fine). Two-part CSS fix consuming the SystemBars core plugin's injected `--safe-area-inset-*`:
the **bottom** via the `--tg-safe-*` token (`app.css`), the **header top** via a native-only `.bar` rule
(`Header.svelte` — its top inset had been Telegram-fullscreen-scoped only, so the token alone didn't reach
it). No dep/config (SystemBars ships in `@capacitor/core` v8). Verified on Pixel_10 / API 37 by live-WebView
CDP measurement (header title y=11→65, `--safe-area-inset-*` = 54/24px) **and** owner re-test on their device.
Full gotcha + CDP recipe in `.claude/CLAUDE.md`. Commits `4a0689a` (bottom) + `49c5379` (top).
- **DEFERRED DECISION (owner-agreed 2026-07-12) — native local-game visibility.** The online lobby lists
only server games (`Lobby.svelte:42/54`), so a native guest's **device-local vs_ai/hotseat games hide from
the lobby once reconciled online** (the pre-existing offline↔online split). For native this IS the primary
@@ -527,10 +538,12 @@ line ref below against current code.**
- **`scheduleRecovery` is now mock-guarded** (like `initNetworkReactivity`) so the e2e's boot does not
race a mock reconcile to online before the spec observes the offline lobby; the e2e drives
reconciliation via a new **`window.__native.reconcile()`** hook (mirrors `__conn`/`__maint`/`__update`).
5. **Both offline modes render for the local guest — ✅ mostly (verify at D close).** `NewGame` gates the
5. **Both offline modes render for the local guest — ✅ DONE & verified (2026-07-12).** `NewGame` gates the
offline flows on `guest || offlineMode.active`; the local guest makes `offlineMode.active` true, so both
"quick" (vs_ai) and "with friends" (hotseat) show. The vs_ai human seat already uses the local-guest id
(D.2).
(D.2). Verified: `e2e/native.spec.ts` plays a vs_ai move + starts a hotseat game, and the on-device smoke
(Pixel_10 / API 37) played a full offline vs_ai turn (Hint "FEZ", robot "NEEDFIRE") and reached New Game
offering both modes.
6. **Soft registration = reuse the `Profile` screen — ✅ DONE & verified (2026-07-12).** As built:
- **Reaching Profile needed no change:** guests keep the Profile tab (`SettingsHub.svelte:27` only hides
friends/wallet for guests; `:33` hides profile/friends/wallet in **offline** mode), so once the native