feat(ui): on-device move preview (local eval) with network fallback
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 17s
CI / ui (pull_request) Successful in 58s
CI / conformance (pull_request) Successful in 8s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m18s

Score and validate a tentative move on-device instead of a per-arrangement
network round trip. The dawg reader and the validate/score/direction slice of the
scrabble-solver engine are ported to TypeScript (ui/src/lib/dict), pinned
byte-for-byte to the Go engine by a new `conformance` CI job. The server stays
authoritative — submit_play re-validates — so the local result is an advisory
accelerator only; any cache miss, storage eviction or a bad-connection breaker
falls back to the network evaluate.

- backend: Registry.DictBytes + an authed GET /api/v1/user/dict/{variant}/{version}
  (immutable) streaming the pinned per-game dawg.
- gateway: a session-gated /dict edge route proxying it; fetchDict on the transport.
- client: an IndexedDB blob cache (best-effort, storage.persist()) + a loader
  (memory -> IndexedDB -> network, session-scoped bad-connection breaker) + a lobby
  prefetch (your-turn first); an adapter over the existing premiums/alphabet; a
  DictWarmup overlay while a cold dictionary loads (120ms flash-guard, 5s cap ->
  network); a ?nolocal flag; the DebugPanel reset also clears the dict cache.
- parity: generators backend/cmd/{dictgen,validategen} + gated Vitest suites, run
  in CI against the release dictionaries.
- docs: ARCHITECTURE §5, TESTING, UI_DESIGN, FUNCTIONAL (+ru).
This commit is contained in:
Ilia Denisov
2026-07-01 20:13:01 +02:00
parent f0399e1bbc
commit d24a127406
38 changed files with 2375 additions and 11 deletions
+4 -1
View File
@@ -163,7 +163,10 @@ tile that extends
an existing word (down a column or across a row) is accepted. A play is validated
against the game's dictionary at submit time and scored; an unlimited preview
reports the word(s) a tentative move would form and its score, or that it is not
legal, and the move is offered for submission only once it is confirmed legal. The dictionary check tool is
legal, and the move is offered for submission only once it is confirmed legal. The preview is
computed **on-device** for an instant response once the game's dictionary has loaded — a
brief warm-up shows on the first open otherwise — and falls back to the server whenever the
local dictionary is unavailable. The dictionary check tool is
unlimited and offers a complaint on any result; for a word it finds, it also links out to an
external reference dictionary (gramota.ru for Russian games, scrabblewordfinder.org for
English) to look it up. Hints are governed per game —