Phase A (2/2) of PWA offline mode: the offline robot picks its move exactly as the
server does, so a local vs_ai game plays the same. Builds on the move generator
from #188; not wired into a game loop yet (Phase B).
- ui/src/lib/robot/strategy.ts: port of backend/internal/robot/strategy.go's
move-choice slice — mix (FNV-1a, via BigInt for bit-exact uint64), playToWin
(~40% play-to-win), deviates (the fading off-strategy wobble) and selectMove
(pick the candidate whose resulting margin lands closest to the +/-[1,30] band,
conservative tie-break), composed by decide(). The generator's ranked moves feed
straight in. Think-time/sleep/nudge scheduling is server-only and not ported.
- backend/internal/robot/strategyfixture_test.go: an in-package, env-gated emitter
(EMIT_STRATEGY_FIXTURES=1) writing golden fixtures from the real Go strategy — it
reaches the unexported mix/playToWin/deviates/selectMove.
- strategy.parity.test.ts: 21 mix + 56 decision cases match Go exactly (play/
exchange/pass, the deviate flip, tie-break, band overshoot).
Pure additive library code; no runtime behavior change (unused at runtime, so the
bundle is unchanged).