# ClaudeGamesReview — Full Games, Mechanics, Retention & UI Review > **Session 2026-07-07 (Claude, senior-dev review round).** Scope: all 7 games verified live on a > fresh 2-emulator couple, mechanics checked against their real-world inspirations (researched), > retention assessment, full-app UI warmth sweep, code-quality audit + fix batches. > Bugs are cross-referenced by ID; canonical defect state lives in `ClaudeReport.md`. > Test couple: **Ava + Ben** (`j39xR7PVZLLCveWnmenU`), created through the real signup → invite-code > → recovery-phrase pairing flow on `CloserQA2` (5554, light) + `CloserCodexQA` (5556, dark). > Premium was granted via admin (user-authorized), verified (partner unlock modal + push), then > revoked (locks confirmed restored). 0 active sessions at session end. ## 1 · Per-game verdicts (mechanics fidelity + live results) | Game | Real-world analog | Fidelity | Live 2-device result | |---|---|---|---| | This or That | Rapid-fire preference quiz | ✅ Faithful | **PASS** — engineered answers → exactly 3/5 "in sync"; simultaneous symmetric reveal; warm framing ("Lots in common 💛", neutral "Differ" chips) | | How Well Do You Know Me | The Newlywed Game | ✅ Core faithful; no round-2 role swap (see R-2) | **PASS** — subject/guesser roles correct on both intros; engineered 2/5 exact; near-miss scale renders amber "4 → 3" (isClose softening); low score framed "Getting there!" | | Desire Sync | Mojo Upgrade-style mutual-desire matching | ✅ Canonical privacy contract, verbatim in intro copy | **PASS** — engineered intersection → exactly "2 shared desires / 3 stayed private"; non-mutual yeses never rendered on either device; count doesn't leak whose/which; answers `enc:v1:` at rest | | Spin the Wheel | Conversation-deck wheel | ✅ Honest randomness (category picked during spin; decorative stop angle) | **PASS** — identical 10-question set both sides; blind until both answered; side-by-side reveal; completion gate blocks finish with unanswered prompts | | Connection Challenges | 7-day couples habit challenge | ✅ Day-gating real (can't complete 2 days in one day) | **PASS** — premium challenge opened with entitlement; day-1 complete → "waiting for partner"; ⚠ day-2 prompt text visible a day early (spoiler, see U-13) | | Memory Lane | Time capsule / letter to future selves | ✅ | **PASS** — sealed capsule shows only title + "Opens in 29 days"; title AND body `enc:v1:` at rest (admin-verified) | | Date Match | Tinder swipe-to-match | ✅ incl. one-sided-like privacy | **PASS** — simultaneous mutual-LOVE race → exactly **1** match doc; celebration modal + "It's a match!" push on BOTH devices | **Shared engine seams, verified live:** one-active-game gate converges the second starter into the active session (Ben's How Well attempt → "Ava is playing a Wheel game / Join the game"); first-finisher `partner_completed_part` fires as an in-app banner (foreground) and real push (killed app, cold-start tap opened the app cleanly, 0 FATAL); mid-game Quit abandons correctly (admin: 0 active sessions after); "you both finished" results banner on both sides. ## 2 · Bugs found (canonical detail in ClaudeReport.md) | ID | Sev | Summary | Status | |---|---|---|---| | DQ-MISMATCH-001 | **P1** | Partners can resolve **different daily questions** for the same day: server assignment is the unresolvable `q_default_daily` rollout fallback → each device falls back locally, and the fallback **pool depends on the viewer's premium state at that moment** (per-user entitlement, transient failures→false, mid-day flips). Reveal then cross-compares answers to different questions. Reproduced live (Ava: premium pool "tiny win" q; Ben: free pool "tiny debate" q; same clock/tz). | **FIXED** (paired fallback pinned to free pool — premium-independent) + follow-up filed to seed real server assignments | | DQ-SLUG-001 | **P1** | Daily reveal renders the partner's answer as a raw option-id slug ("fake_awards_should_be_mandatory") when the id isn't in this device's question config (same class as HW-BREAKDOWN-001). | **FIXED** (humanize fallback in both reveal summaries) | | GAME-HANG-001 (B1) | **P2** | ToT/HowWell/DesireSync answer listeners swallowed snapshot errors → game stuck on WAITING forever, no feedback (Wheel/Capsule already had the correct `close(err)` pattern). | **FIXED** (sources `close(err)` + VM `.catch` → retryable ERROR with "Try again" re-attach) | | DST-001 (B2) | **P2** | `assignDailyQuestion.ts` hardcoded `CST_OFFSET_HOURS=-6`: wrong date labels + reveal times shifted 1h for the ~8 CDT months. | **FIXED** (Intl/America-Chicago helpers, matches streakReminder.ts pattern; 5 DST regression tests incl. spring-forward round-trip) | | A-003b | P3 | Challenges catalog still shows 🔒 Premium badge after couple premium unlock (gate itself honors premium — opens fine). | Filed | | BANNER-LIFE-001 | P3 | "You both finished · View" game banner persists across screens/games long after results were viewed (still up entering a NEW game's setup, and shown on top of the results screen it links to). | Filed | | AUTH-TRUNC-001 | P3 | Welcome/splash privacy tagline clips mid-sentence without ellipsis ("Only you and your paired") — first-run first impression. | Filed | | Copy/theming P3s | P3 | "Daily Fun Mc" internal category name as user-facing pill; unthemed teal date picker; DOB asked twice in signup→profile funnel; "It is a match!" vs push "It's a match!"; HW matched-row question text low contrast in dark; Date Match card-underlay text bleed; joiner screen titled "Waiting for X" when it's your turn. | Filed | ## 3 · Retention assessment (Hooked / Fogg / SDT lens) **Strong foundations:** daily-question blind-reveal is a genuine daily anchor with a variable reward (partner's answer) · streaks with repair + grace (aligned with Duolingo's leniency findings) · Memory Lane = stored-value investment · Weekly Recap + Your Progress = progress evidence · first-finisher nudges close the async loop (verified: banner + push both fire) · notification suite respects quiet hours. **Prioritized recommendations:** - **R-1 (P1): Fix the daily anchor supply chain.** `q_default_daily` fallback means the server never really assigns; seed the Firestore `questions` pool (or make the callable assign a real id from a synced catalog) so both devices always agree. (Client-side consistency fix landed this session; assignment seeding is the durable fix.) - **R-2 (P2): Role-swap rematch in How Well.** Newlywed Game's round structure swaps roles; the results screen should offer "Now you guess — swap roles" (starter becomes guesser). Cheap, doubles sessions per sitting, and answers "what do we do next?" at the emotional peak. - **R-3 (P2): Return-tomorrow beat on results screens.** After every reveal the only CTAs are "Play again / Back to Play". Add the next anchor: tomorrow's question teaser, challenge day N+1, or streak state ("Day 2 tomorrow — keep it alive"). - **R-4 (P2): Repeat-avoidance for game pools.** Desire Sync's effective pool is 102 binary items drawn `shuffled().take(n)` per session (no cross-session memory) and Date Match's deck is deterministic (identical first card for every couple, every install). Persist seen-ids per couple. - **R-5 (P3): Purify the How Well pool.** `getQuestionsForPrediction()` pulls all choice/scale questions including 500 `daily_fun_mc` novelty MCs ("laugh-track move") — dilutes the partner-knowledge premise. Exclude `daily_fun_mc` (or curate a prediction-worthy tag). - **R-6 (P3): Challenges — hide tomorrow's prompt** (spoiler kills the daily ritual) and consider a visible 7-day chain with both partners' marks (social accountability). - **R-7 (P3): Analytics funnel gaps.** `RetentionEvent` has GameStarted/GameCompleted but no first-answer, reveal-viewed, waiting-abandoned, or notification-tap-attribution events — the async dead-end (biggest churn risk) is unmeasurable today. - **Content notes:** 48/150 sexual_preferences items unreachable by Desire Sync (non-binary configs — fine, Wheel uses them) · `daily_fun_mc` rows carry `sex='neutral'` (currently benign only because of the binary filter; retag to avoid a future landmine) · This or That mood pools healthy (60–75 per mood vs 15 max draw); `rebuilding_trust` (45 q) reachable only via "All topics". ## 4 · UI warmth sweep (vs docs/copy-guide.md) Scores 1–5 per cluster (tone / emotional safety / welcome / consistency): - **Games (all 7): 5/5/–/4.** Best-in-class results framing (no shaming anywhere: "Getting there!", "Differ" not ✗, "Nothing in common this round" never blames). Consistency dinged for the banner lifecycle + slug leak (fixed) + per-game accent divergence (DS magenta is intentional and works). - **Onboarding/pairing: 4/–/5/3.** "You're in / Now bring your person in", value-prop checklist, recovery-phrase ceremony with word-confirmation are excellent. Dinged: tagline truncation, DOB asked twice, unthemed date picker, dead-end Create-Profile when signed out. - **Home/Today: 4/5/5/3.** Daily card + mode system (Tiny Win Tuesday live-verified) is a strong anchor; "Daily Fun Mc" pill leak; Home-card question can disagree with Today tab (DQ-MISMATCH). - **Empty states: 5.** Memory Lane's "No capsules yet" is the pattern to copy everywhere. - Both themes render cleanly on every screen driven this session (fresh-couple run covered light on 5554 + dark on 5556 throughout); HW matched-row contrast is the one dark-mode ding. ## 5 · Code-quality fixes landed this session - **Batch 1 (correctness):** B1 observer `close(err)` ×3 + VM `.catch`→retryable ERROR ×3 (+ `GameCopy.SYNC_ERROR`); DQ paired-fallback premium-independence; reveal slug humanization ×2; DST-safe Chicago date helpers + 5 regression tests. - **Batch 2 (dead code / hygiene):** see ClaudeReport.md fix log. - **Filed (structural, specced in Future.md):** generic session-game engine (ToT/HW/DS VMs are ~80% clones; ~250-line state machine ×4), generic replay VM/screen (3× ~60-line clones), shared waiting/length-picker composables, premium-check invocation helper, `GameConstants` for divergent `ADVANCE_DELAY_MS` (420/380), dispatcher injection, error-surfacing standardization for 6 silent-load VMs, `npm audit` 10 moderate (GCP transitive). ## 5.1 · R30 polish + experience follow-up (2026-07-07) All Tier-A P3s and Tier-B UX gaps from the review shipped and were live-verified (detail: ClaudeReport R30). Highlights that change the player experience: - **Daily question is fixed at the root.** The server pool was empty (every couple got the unresolvable `q_default_daily`); now Firestore `questions` is seeded with the free weekday pool and the server picks the same mode-aware, deterministic question the client would — so both partners get the identical themed question, even across time zones. Verified: server assigns `daily_single_choice_weekly_v1_072` (Tiny Win Tuesday), both devices resolve it, no slugs. - **Games no longer dead-end:** NextBeatCard ("Tonight's question is ready →" / streak) under every results screen; How Well offers a Newlywed-style role swap. - **Content freshness:** Desire Sync remembers served questions; Date Match shuffles per couple and skips already-swiped ideas (no more identical first card for everyone). - **Waiting isn't passive:** a "Send a little nudge 💜" button on the waiting screen (reuses the quiet-hours-safe thinking-of-you callable). - **Onboarding polish:** themed M3 date pickers; the birth date now survives an app restart mid-signup (no more double-ask). - **A11y + copy:** score visuals carry TalkBack descriptions; banners speak per-game ("guess their answers"); the internal "Daily Fun Mc" label never faces users. ## 6 · Coverage notes - Verified live: all 7 games happy path 2-device · result extremes (0-match impossible for DS reveal? engineered 3/5, 2/5, 2-shared, 3/5-sync variants) · one-active gate · abandon · cold-start push join · simultaneous-LOVE race · premium grant/unlock/revoke lifecycle · daily answer→reveal · day-0 check-in · pairing + recovery-phrase ceremony · deep-link scheme audit (only /join/ links exist; game entries are notification-driven, all tested). - Deferred (unchanged from plan): full Pass E matrix, Pass K money path, release build, monkey, TalkBack full pass (spot: n/a this round), TodayWidget interactive smoke (code-read only), am-kill mid-session resume (cold-start-from-push covered the recovery class).